xref: /petsc/doc/conf.py (revision 9d13fa56c5c6523e02c36edc0e4e22bf2d0334a8)
1# Configuration file for the Sphinx documentation builder.
2#
3# For information on options, see
4#   http://www.sphinx-doc.org/en/master/config
5#
6
7import os
8import sys
9import subprocess
10import re
11import datetime
12import shutil
13
14sys.path.append(os.getcwd())
15sys.path.append(os.path.abspath('./ext'))
16
17import add_man_page_redirects
18import build_classic_docs
19import fix_man_page_edit_links
20import make_links_relative
21import update_htmlmap_links
22import fix_pydata_margins
23
24
25if not os.path.isdir("images"):
26    print("-----------------------------------------------------------------------------")
27    print("ERROR")
28    print("images directory does not seem to exist.")
29    print("To clone the required repository, try")
30    print("   make images")
31    print("-----------------------------------------------------------------------------")
32    raise Exception("Aborting because images missing")
33
34
35# -- Project information -------------------------------------------------------
36
37project = 'PETSc'
38copyright = '1991-%d, UChicago Argonne, LLC and the PETSc Development Team' % datetime.date.today().year
39author = 'The PETSc Development Team'
40
41with open(os.path.join('..', 'include', 'petscversion.h'),'r') as version_file:
42    buf = version_file.read()
43    petsc_release_flag = re.search(' PETSC_VERSION_RELEASE[ ]*([0-9]*)',buf).group(1)
44    major_version      = re.search(' PETSC_VERSION_MAJOR[ ]*([0-9]*)',buf).group(1)
45    minor_version      = re.search(' PETSC_VERSION_MINOR[ ]*([0-9]*)',buf).group(1)
46    subminor_version   = re.search(' PETSC_VERSION_SUBMINOR[ ]*([0-9]*)',buf).group(1)
47
48    git_describe_version = subprocess.check_output(['git', 'describe', '--always']).strip().decode('utf-8')
49    if petsc_release_flag == '0':
50        version = git_describe_version
51        release = git_describe_version
52    else:
53        version = '.'.join([major_version, minor_version])
54        release = '.'.join([major_version,minor_version,subminor_version])
55
56
57# -- General configuration -----------------------------------------------------
58
59# The information on the next line must also be the same in requirements.txt
60needs_sphinx='5.3'
61nitpicky = True  # checks internal links. For external links, use "make linkcheck"
62master_doc = 'index'
63templates_path = ['_templates']
64exclude_patterns = ['_build*', 'images', 'Thumbs.db', '.DS_Store','community/meetings/pre-2023']
65highlight_language = 'c'
66numfig = True
67
68# -- Extensions ----------------------------------------------------------------
69
70extensions = [
71    'sphinx_copybutton',
72    'sphinx_design',
73    'sphinxcontrib.bibtex',
74    'sphinxcontrib.katex',
75    'sphinxcontrib.rsvgconverter',
76    'myst_parser',
77    'html5_petsc',
78    'sphinx_remove_toctrees',
79]
80
81copybutton_prompt_text = '$ '
82
83bibtex_bibfiles = ['petsc.bib']
84
85myst_enable_extensions = ["fieldlist", "dollarmath", "amsmath", "deflist"]
86
87remove_from_toctrees = ['manualpages/*/[A-Z]*','changes/2*','changes/3*']
88
89# -- Options for HTML output ---------------------------------------------------
90
91html_theme = 'pydata_sphinx_theme'
92
93html_logo_light = os.path.join('images', 'logos', 'PETSc_TAO_logos', 'PETSc-TAO', 'web', 'PETSc-TAO_RGB.svg')
94html_logo_dark = os.path.join('images', 'logos', 'PETSc_TAO_logos', 'PETSc-TAO', 'web', 'PETSc-TAO_RGB_white.svg')
95
96html_static_path = ['_static', html_logo_light, html_logo_dark]
97
98# use much smaller font for h1, h2 etc. They are absurdly large in the standard style
99# https://pydata-sphinx-theme.readthedocs.io/en/v0.12.0/user_guide/styling.html
100html_css_files = [
101    'css/custom.css',
102]
103
104html_theme_options = {
105    "icon_links": [
106        {
107            "name": "GitLab",
108            "url": "https://gitlab.com/petsc/petsc",
109            "icon": "fab fa-gitlab",
110        },
111    ],
112    "use_edit_page_button": True,
113    "footer_items": ["copyright", "sphinx-version", "last-updated"],
114#    "secondary_sidebar_items" : ["edit-this-page"],
115     "header_links_before_dropdown": 10,
116    "logo": {
117        "image_light": os.path.basename(html_logo_light),
118        "image_dark": os.path.basename(html_logo_dark)
119    }
120}
121
122try:
123  git_ref = subprocess.check_output(["git", "rev-parse", "HEAD"]).rstrip()
124  git_ref_release = subprocess.check_output(["git", "rev-parse", "origin/release"]).rstrip()
125  edit_branch = "release" if git_ref == git_ref_release else "main"
126except subprocess.CalledProcessError:
127  print("WARNING: determining branch for page edit links failed")
128  edit_branch = "main"
129
130html_context = {
131    "github_url": "https://gitlab.com",
132    "github_user": "petsc",
133    "github_repo": "petsc",
134    "github_version": edit_branch,
135    "doc_path": "doc",
136}
137
138html_logo = html_logo_light
139html_favicon = os.path.join('images', 'logos', 'PETSc_TAO_logos', 'PETSc', 'petsc_favicon.png')
140html_last_updated_fmt = r'%Y-%m-%dT%H:%M:%S%z (' + git_describe_version + ')'
141
142
143# -- Options for LaTeX output --------------------------------------------------
144latex_engine = 'xelatex'
145
146# How to arrange the documents into LaTeX files, building only the manual.
147latex_documents = [
148        ('manual/index', 'manual.tex', 'PETSc/TAO Users Manual', author, 'manual', False)
149        ]
150
151latex_additional_files = [
152    'images/manual/anl_tech_report/ArgonneLogo.pdf',
153    'images/manual/anl_tech_report/ArgonneReportTemplateLastPage.pdf',
154    'images/manual/anl_tech_report/ArgonneReportTemplatePage2.pdf',
155    'manual/anl_tech_report/first.inc',
156    'manual/anl_tech_report/last.inc',
157]
158
159latex_elements = {
160    'maketitle': r'\newcommand{\techreportversion}{%s}' % version +
161r'''
162\input{first.inc}
163''',
164    'printindex': r'''
165\printindex
166\input{last.inc}
167''',
168    'fontpkg': r'''
169\setsansfont{DejaVu Sans}
170\setmonofont{DejaVu Sans Mono}
171''',
172    'tableofcontents' : r''
173}
174
175
176# -- Setup and event callbacks -------------------------------------------------
177
178def setup(app):
179        app.connect('builder-inited', builder_init_handler)
180        app.connect('build-finished', build_finished_handler)
181
182
183def builder_init_handler(app):
184    if app.builder.name.endswith('html'):
185        _build_classic_docs(app, 'pre')
186        _update_htmlmap_links(app)
187
188
189def build_finished_handler(app, exception):
190    if app.builder.name.endswith('html'):
191        _build_classic_docs(app, 'post')
192        build_petsc4py_docs(app)
193        _fix_links(app, exception)
194        _fix_man_page_edit_links(app, exception)
195        fix_pydata_margins.fix_pydata_margins(app.outdir)
196        if app.builder.name == 'dirhtml':
197            _add_man_page_redirects(app, exception)
198        # remove sources for manual pages since they are automatically generated and should not be looked at on the website
199        if os.path.isdir(os.path.join(app.outdir,'_sources','manualpages')):
200            shutil.rmtree(os.path.join(app.outdir,'_sources','manualpages'))
201        if app.builder.name == 'html':
202            print("==========================================================================")
203            print("    open %s/index.html in your browser to view the documentation " % app.outdir)
204            print("==========================================================================")
205
206def _add_man_page_redirects(app, exception):
207    if exception is None:
208        print("============================================")
209        print("    Adding man pages redirects")
210        print("============================================")
211        add_man_page_redirects.add_man_page_redirects(app.outdir)
212
213def _build_classic_docs(app, stage):
214    '''Builds the .md versions of the manual pages and the .html version of the source code'''
215    build_classic_docs.main(stage,app.outdir)
216
217def _fix_man_page_edit_links(app, exception):
218    if exception is None:
219        print("============================================")
220        print("    Fixing man page edit links")
221        print("============================================")
222        fix_man_page_edit_links.fix_man_page_edit_links(app.outdir)
223
224#
225#   The following two scripts are needed because the Sphinx html and dirhtml builds save the output html
226#   files at different levels of the directory hierarchy. file.rst -> file.html with html but
227#   file.rst -> file/index.html with dirhtml and we want both to work correctly using relative links.
228
229def _fix_links(app, exception):
230    """We need to manage our own relative paths in the User's Manual for the source code files which
231       are auto-generated by c2html outside of Sphinx so Sphinx cannot directly handle those links for use.
232       We use the string PETSC_DOC_OUT_ROOT_PLACEHOLDER in URLs in the Sphinx .rst files as a stand in
233       for the root directory that needs to be constructed based on if the Sphinx build is html or dirhtml
234    """
235    if exception is None:
236        print("============================================")
237        print("    Fixing relative links")
238        print("============================================")
239        make_links_relative.make_links_relative(app.outdir)
240
241
242def _update_htmlmap_links(app):
243    """htmlmap maps from manualpage names to relative locations in the generated documentation directory
244       hierarchy. The format of the directory location needs to be different for the Sphinx html and dirhtml
245       builds
246    """
247    print("============================================")
248    print("    Updating htmlmap")
249    print("============================================")
250    update_htmlmap_links.update_htmlmap_links(app.builder,os.path.join('manualpages','htmlmap'))
251
252def build_petsc4py_docs(app):
253    petsc_dir = os.path.dirname(os.path.abspath(os.path.join(__file__,'..')))
254    petsc_arch = 'arch-classic-docs'
255
256    # Lisandro, does petsc4py need to be built to build petsc4py docs now?
257    command = ['make', 'all',
258               'PETSC_DIR=%s' % petsc_dir,
259               'PETSC_ARCH=%s' % petsc_arch]
260    print('==============================================')
261    print('Building library to make petsc4py docs')
262    print(command)
263    print('==============================================')
264    subprocess.run(command, cwd=petsc_dir, check=True)
265
266    command = ['make', 'website',
267               'PETSC_DIR=%s' % petsc_dir,
268               'PETSC_ARCH=%s' % petsc_arch,
269               'LOC=%s' % app.outdir]
270    print('============================================')
271    print('Building petsc4py docs')
272    print(command)
273    print('============================================')
274    subprocess.run(command, cwd=os.path.join(petsc_dir,'src','binding','petsc4py'), check=True)
275