xref: /petsc/src/binding/petsc4py/docs/source/conf.py (revision 73b1570004d1c7386566f44b343ecce99017c419)
155a74a43SLisandro Dalcin# Configuration file for the Sphinx documentation builder.
25808f684SSatish Balay#
355a74a43SLisandro Dalcin# For the full list of built-in configuration values, see the documentation:
455a74a43SLisandro Dalcin# https://www.sphinx-doc.org/en/master/usage/configuration.html
555a74a43SLisandro Dalcin
655a74a43SLisandro Dalcin# -- Path setup --------------------------------------------------------------
75808f684SSatish Balay
85808f684SSatish Balay# If extensions (or modules to document with autodoc) are in another directory,
95808f684SSatish Balay# add these directories to sys.path here. If the directory is relative to the
105808f684SSatish Balay# documentation root, use os.path.abspath to make it absolute, like shown here.
115808f684SSatish Balay
12d919c72dSLisandro Dalcinimport re
1355a74a43SLisandro Dalcinimport os
1455a74a43SLisandro Dalcinimport shutil
1555a74a43SLisandro Dalcinimport sys
162c804a55SBarry Smithimport subprocess
1755a74a43SLisandro Dalcinimport typing
1855a74a43SLisandro Dalcinimport datetime
1955a74a43SLisandro Dalcinimport importlib
2055a74a43SLisandro Dalcinimport sphobjinv
2155a74a43SLisandro Dalcinimport functools
2255a74a43SLisandro Dalcinimport pylit
237e3bcaecSStefano Zampinifrom sphinx import __version__ as sphinx_version
2455a74a43SLisandro Dalcinfrom sphinx.ext.napoleon.docstring import NumpyDocstring
257e3bcaecSStefano Zampinifrom packaging.version import Version
2655a74a43SLisandro Dalcin
2755a74a43SLisandro Dalcinsys.path.insert(0, os.path.abspath('.'))
2855a74a43SLisandro Dalcin_today = datetime.datetime.now()
2955a74a43SLisandro Dalcin
306f336411SStefano Zampini# FIXME: allow building from build?
3155a74a43SLisandro Dalcin
3255a74a43SLisandro Dalcin# -- Project information -----------------------------------------------------
3355a74a43SLisandro Dalcin# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
3455a74a43SLisandro Dalcin
3555a74a43SLisandro Dalcinpackage = 'petsc4py'
36*59c9a94dSJose E. Romanproject = 'petsc4py'   # shown in top left corner of the petsc4py documentation
3755a74a43SLisandro Dalcin
38d919c72dSLisandro Dalcindocdir = os.path.abspath(os.path.dirname(__file__))
39d919c72dSLisandro Dalcintopdir = os.path.abspath(os.path.join(docdir, *[os.path.pardir] * 2))
4055a74a43SLisandro Dalcin
416f336411SStefano Zampini
4255a74a43SLisandro Dalcindef pkg_version():
43d919c72dSLisandro Dalcin    with open(os.path.join(topdir, 'src', package, '__init__.py')) as f:
445808f684SSatish Balay        m = re.search(r"__version__\s*=\s*'(.*)'", f.read())
455808f684SSatish Balay        return m.groups()[0]
465808f684SSatish Balay
475808f684SSatish Balay
48d919c72dSLisandro Dalcindef get_doc_branch():
49d919c72dSLisandro Dalcin    release = 1
50d919c72dSLisandro Dalcin    if topdir.endswith(os.path.join(os.path.sep, 'src', 'binding', package)):
51d919c72dSLisandro Dalcin        rootdir = os.path.abspath(os.path.join(topdir, *[os.path.pardir] * 3))
52d919c72dSLisandro Dalcin        rootname = package.replace('4py', '')
53d919c72dSLisandro Dalcin        version_h = os.path.join(rootdir, 'include', f'{rootname}version.h')
54d919c72dSLisandro Dalcin        if os.path.exists(version_h) and os.path.isfile(version_h):
55d919c72dSLisandro Dalcin            release_macro = f'{rootname.upper()}_VERSION_RELEASE'
566f336411SStefano Zampini            version_re = re.compile(rf'#define\s+{release_macro}\s+([-]*\d+)')
57d919c72dSLisandro Dalcin            with open(version_h, 'r') as f:
58d919c72dSLisandro Dalcin                release = int(version_re.search(f.read()).groups()[0])
59d919c72dSLisandro Dalcin    return 'release' if release else 'main'
60d919c72dSLisandro Dalcin
61d919c72dSLisandro Dalcin
626f336411SStefano Zampini__project__ = 'PETSc for Python'
636f336411SStefano Zampini__author__ = 'Lisandro Dalcin'
646f336411SStefano Zampini__copyright__ = f'{_today.year}, {__author__}'
655808f684SSatish Balay
6655a74a43SLisandro Dalcinrelease = pkg_version()
6755a74a43SLisandro Dalcinversion = release.rsplit('.', 1)[0]
685808f684SSatish Balay
695808f684SSatish Balay
7055a74a43SLisandro Dalcin# -- General configuration ---------------------------------------------------
7155a74a43SLisandro Dalcin# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
725808f684SSatish Balay
7355a74a43SLisandro Dalcinextensions = [
7455a74a43SLisandro Dalcin    'sphinx.ext.autodoc',
7555a74a43SLisandro Dalcin    'sphinx.ext.autosummary',
7655a74a43SLisandro Dalcin    'sphinx.ext.intersphinx',
7755a74a43SLisandro Dalcin    'sphinx.ext.napoleon',
78b3f8c7a1SStefano Zampini    'sphinx.ext.extlinks',
7955a74a43SLisandro Dalcin]
805808f684SSatish Balay
8155a74a43SLisandro Dalcintemplates_path = ['_templates']
825808f684SSatish Balayexclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
835808f684SSatish Balay
8455a74a43SLisandro Dalcindefault_role = 'any'
8555a74a43SLisandro Dalcin
8655a74a43SLisandro Dalcinpygments_style = 'tango'
8755a74a43SLisandro Dalcin
8855a74a43SLisandro Dalcinnitpicky = True
8955a74a43SLisandro Dalcinnitpick_ignore = [
9055a74a43SLisandro Dalcin    ('envvar', 'NUMPY_INCLUDE'),
9155a74a43SLisandro Dalcin    ('py:class', 'ndarray'),  # FIXME
9255a74a43SLisandro Dalcin    ('py:class', 'typing_extensions.Self'),
9355a74a43SLisandro Dalcin]
9455a74a43SLisandro Dalcinnitpick_ignore_regex = [
9555a74a43SLisandro Dalcin    (r'c:.*', r'MPI_.*'),
9655a74a43SLisandro Dalcin    (r'c:.*', r'Petsc.*'),
9755a74a43SLisandro Dalcin    (r'envvar', r'(LD_LIBRARY_)?PATH'),
9855a74a43SLisandro Dalcin    (r'envvar', r'(MPICH|OMPI|MPIEXEC)_.*'),
9955a74a43SLisandro Dalcin]
10055a74a43SLisandro Dalcin
10155a74a43SLisandro Dalcintoc_object_entries = False
10255a74a43SLisandro Dalcintoc_object_entries_show_parents = 'hide'
10355a74a43SLisandro Dalcin# python_use_unqualified_type_names = True
10455a74a43SLisandro Dalcin
10555a74a43SLisandro Dalcinautodoc_class_signature = 'separated'
10655a74a43SLisandro Dalcinautodoc_typehints = 'description'
10755a74a43SLisandro Dalcinautodoc_typehints_format = 'short'
10855a74a43SLisandro Dalcinautodoc_mock_imports = []
10955a74a43SLisandro Dalcinautodoc_type_aliases = {}
11055a74a43SLisandro Dalcin
11155a74a43SLisandro Dalcinautosummary_context = {
11255a74a43SLisandro Dalcin    'synopsis': {},
11355a74a43SLisandro Dalcin    'autotype': {},
11455a74a43SLisandro Dalcin}
1155808f684SSatish Balay
1167e3bcaecSStefano Zampinisuppress_warnings = []
1177e3bcaecSStefano Zampiniif Version(sphinx_version) >= Version(
1187e3bcaecSStefano Zampini    '7.4'
1197e3bcaecSStefano Zampini):  # https://github.com/sphinx-doc/sphinx/issues/12589
1207e3bcaecSStefano Zampini    suppress_warnings.append('autosummary.import_cycle')
1217e3bcaecSStefano Zampini
1221d9f564dSStefano Zampini# Links depends on the actual branch -> release or main
1231d9f564dSStefano Zampiniwww = f'https://gitlab.com/petsc/petsc/-/tree/{get_doc_branch()}'
1246f336411SStefano Zampiniextlinks = {'sources': (f'{www}/src/binding/petsc4py/src/%s', '%s')}
1255808f684SSatish Balay
126d919c72dSLisandro Dalcinnapoleon_preprocess_types = True
127d919c72dSLisandro Dalcin
128d919c72dSLisandro Dalcintry:
129d919c72dSLisandro Dalcin    import sphinx_rtd_theme
1306f336411SStefano Zampini
131d919c72dSLisandro Dalcin    if 'sphinx_rtd_theme' not in extensions:
132d919c72dSLisandro Dalcin        extensions.append('sphinx_rtd_theme')
133d919c72dSLisandro Dalcinexcept ImportError:
134d919c72dSLisandro Dalcin    sphinx_rtd_theme = None
135d919c72dSLisandro Dalcin
136d919c72dSLisandro Dalcinintersphinx_mapping = {
137d919c72dSLisandro Dalcin    'python': ('https://docs.python.org/3/', None),
138d919c72dSLisandro Dalcin    'numpy': ('https://numpy.org/doc/stable/', None),
139d919c72dSLisandro Dalcin    'numpydoc': ('https://numpydoc.readthedocs.io/en/latest/', None),
140d919c72dSLisandro Dalcin    'mpi4py': ('https://mpi4py.readthedocs.io/en/stable/', None),
141d919c72dSLisandro Dalcin    'pyopencl': ('https://documen.tician.de/pyopencl/', None),
142d919c72dSLisandro Dalcin    'dlpack': ('https://dmlc.github.io/dlpack/latest/', None),
143d919c72dSLisandro Dalcin    'petsc': ('https://petsc.org/release/', None),
144d919c72dSLisandro Dalcin}
145d919c72dSLisandro Dalcin
1466f336411SStefano Zampini
14755a74a43SLisandro Dalcindef _mangle_petsc_intersphinx():
14855a74a43SLisandro Dalcin    """Preprocess the keys in PETSc's intersphinx inventory.
14955a74a43SLisandro Dalcin
15055a74a43SLisandro Dalcin    PETSc have intersphinx keys of the form:
15155a74a43SLisandro Dalcin
15255a74a43SLisandro Dalcin        manualpages/Vec/VecShift
15355a74a43SLisandro Dalcin
15455a74a43SLisandro Dalcin    instead of:
15555a74a43SLisandro Dalcin
15655a74a43SLisandro Dalcin        petsc.VecShift
15755a74a43SLisandro Dalcin
15855a74a43SLisandro Dalcin    This function downloads their object inventory and strips the leading path
15955a74a43SLisandro Dalcin    elements so that references to PETSc names actually resolve."""
160e3ec4a52SBarry Smith
161d919c72dSLisandro Dalcin    website = intersphinx_mapping['petsc'][0].partition('/release/')[0]
162d919c72dSLisandro Dalcin    branch = get_doc_branch()
1636f336411SStefano Zampini    doc_url = f'{website}/{branch}/'
1646f336411SStefano Zampini    if 'LOC' in os.environ and os.path.isfile(
1656f336411SStefano Zampini        os.path.join(os.environ['LOC'], 'objects.inv')
1666f336411SStefano Zampini    ):
1676f336411SStefano Zampini        inventory_url = 'file://' + os.path.join(os.environ['LOC'], 'objects.inv')
1680c386d85SStefano Zampini    else:
1696f336411SStefano Zampini        inventory_url = f'{doc_url}objects.inv'
1706f336411SStefano Zampini    print('Using PETSC inventory from ' + inventory_url)
1710c386d85SStefano Zampini    inventory = sphobjinv.Inventory(url=inventory_url)
172e3ec4a52SBarry Smith    print(inventory)
173d919c72dSLisandro Dalcin
174d919c72dSLisandro Dalcin    for obj in inventory.objects:
1756f336411SStefano Zampini        if obj.name.startswith('manualpages'):
1766f336411SStefano Zampini            obj.name = 'petsc.' + '/'.join(obj.name.split('/')[2:])
1776f336411SStefano Zampini            obj.role = 'class'
1786f336411SStefano Zampini            obj.domain = 'py'
17955a74a43SLisandro Dalcin
1806f336411SStefano Zampini    new_inventory_filename = 'petsc_objects.inv'
181d919c72dSLisandro Dalcin    sphobjinv.writebytes(
1826f336411SStefano Zampini        new_inventory_filename, sphobjinv.compress(inventory.data_file(contract=True))
183d919c72dSLisandro Dalcin    )
1840c386d85SStefano Zampini    intersphinx_mapping['petsc'] = (doc_url, new_inventory_filename)
18555a74a43SLisandro Dalcin
18655a74a43SLisandro Dalcin
18755a74a43SLisandro Dalcin_mangle_petsc_intersphinx()
18855a74a43SLisandro Dalcin
18955a74a43SLisandro Dalcin
19055a74a43SLisandro Dalcindef _setup_mpi4py_typing():
19155a74a43SLisandro Dalcin    pkg = type(sys)('mpi4py')
19255a74a43SLisandro Dalcin    mod = type(sys)('mpi4py.MPI')
19355a74a43SLisandro Dalcin    mod.__package__ = pkg.__name__
19455a74a43SLisandro Dalcin    sys.modules[pkg.__name__] = pkg
19555a74a43SLisandro Dalcin    sys.modules[mod.__name__] = mod
19655a74a43SLisandro Dalcin    for clsname in (
19755a74a43SLisandro Dalcin        'Intracomm',
19855a74a43SLisandro Dalcin        'Datatype',
19955a74a43SLisandro Dalcin        'Op',
20055a74a43SLisandro Dalcin    ):
20155a74a43SLisandro Dalcin        cls = type(clsname, (), {})
20255a74a43SLisandro Dalcin        cls.__module__ = mod.__name__
20355a74a43SLisandro Dalcin        setattr(mod, clsname, cls)
20455a74a43SLisandro Dalcin
20555a74a43SLisandro Dalcin
20655a74a43SLisandro Dalcindef _patch_domain_python():
20755a74a43SLisandro Dalcin    from sphinx.domains.python import PythonDomain
2086f336411SStefano Zampini
20955a74a43SLisandro Dalcin    PythonDomain.object_types['data'].roles += ('class',)
21055a74a43SLisandro Dalcin
21155a74a43SLisandro Dalcin
21255a74a43SLisandro Dalcindef _setup_autodoc(app):
21355a74a43SLisandro Dalcin    from sphinx.ext import autodoc
21455a74a43SLisandro Dalcin    from sphinx.util import inspect
21555a74a43SLisandro Dalcin    from sphinx.util import typing
21655a74a43SLisandro Dalcin
21755a74a43SLisandro Dalcin    #
21855a74a43SLisandro Dalcin
219a8b7c094SLisandro Dalcin    def stringify_annotation(annotation, *p, **kw):
22055a74a43SLisandro Dalcin        qualname = getattr(annotation, '__qualname__', '')
22155a74a43SLisandro Dalcin        module = getattr(annotation, '__module__', '')
22255a74a43SLisandro Dalcin        args = getattr(annotation, '__args__', None)
22355a74a43SLisandro Dalcin        if module == 'builtins' and qualname and args is not None:
224a8b7c094SLisandro Dalcin            args = ', '.join(stringify_annotation(a, *p, **kw) for a in args)
22555a74a43SLisandro Dalcin            return f'{qualname}[{args}]'
226a8b7c094SLisandro Dalcin        return stringify_annotation_orig(annotation, *p, **kw)
22755a74a43SLisandro Dalcin
22855a74a43SLisandro Dalcin    try:
22955a74a43SLisandro Dalcin        stringify_annotation_orig = typing.stringify_annotation
23055a74a43SLisandro Dalcin        inspect.stringify_annotation = stringify_annotation
23155a74a43SLisandro Dalcin        typing.stringify_annotation = stringify_annotation
23255a74a43SLisandro Dalcin        autodoc.stringify_annotation = stringify_annotation
23355a74a43SLisandro Dalcin        autodoc.typehints.stringify_annotation = stringify_annotation
23455a74a43SLisandro Dalcin    except AttributeError:
23555a74a43SLisandro Dalcin        stringify_annotation_orig = typing.stringify
23655a74a43SLisandro Dalcin        inspect.stringify_annotation = stringify_annotation
23755a74a43SLisandro Dalcin        typing.stringify = stringify_annotation
23855a74a43SLisandro Dalcin        autodoc.stringify_typehint = stringify_annotation
23955a74a43SLisandro Dalcin
240a8b7c094SLisandro Dalcin    inspect.TypeAliasForwardRef.__repr__ = lambda self: self.name
241a8b7c094SLisandro Dalcin
24255a74a43SLisandro Dalcin    #
24355a74a43SLisandro Dalcin
24455a74a43SLisandro Dalcin    class ClassDocumenterMixin:
24555a74a43SLisandro Dalcin        def __init__(self, *args, **kwargs):
24655a74a43SLisandro Dalcin            super().__init__(*args, **kwargs)
24755a74a43SLisandro Dalcin            if self.config.autodoc_class_signature == 'separated':
24855a74a43SLisandro Dalcin                members = self.options.members
24955a74a43SLisandro Dalcin                special_members = self.options.special_members
25055a74a43SLisandro Dalcin                if special_members is not None:
25155a74a43SLisandro Dalcin                    for name in ('__new__', '__init__'):
25255a74a43SLisandro Dalcin                        if name in members:
25355a74a43SLisandro Dalcin                            members.remove(name)
25455a74a43SLisandro Dalcin                        if name in special_members:
25555a74a43SLisandro Dalcin                            special_members.remove(name)
25655a74a43SLisandro Dalcin
25755a74a43SLisandro Dalcin    class ClassDocumenter(
25855a74a43SLisandro Dalcin        ClassDocumenterMixin,
25955a74a43SLisandro Dalcin        autodoc.ClassDocumenter,
26055a74a43SLisandro Dalcin    ):
26155a74a43SLisandro Dalcin        pass
26255a74a43SLisandro Dalcin
26355a74a43SLisandro Dalcin    class ExceptionDocumenter(
26455a74a43SLisandro Dalcin        ClassDocumenterMixin,
26555a74a43SLisandro Dalcin        autodoc.ExceptionDocumenter,
26655a74a43SLisandro Dalcin    ):
26755a74a43SLisandro Dalcin        pass
26855a74a43SLisandro Dalcin
26955a74a43SLisandro Dalcin    app.add_autodocumenter(ClassDocumenter, override=True)
27055a74a43SLisandro Dalcin    app.add_autodocumenter(ExceptionDocumenter, override=True)
27155a74a43SLisandro Dalcin
27255a74a43SLisandro Dalcin
27355a74a43SLisandro Dalcindef _monkey_patch_returns():
27455a74a43SLisandro Dalcin    """Rewrite the role of names in "Returns" sections.
27555a74a43SLisandro Dalcin
27655a74a43SLisandro Dalcin    This is needed because Napoleon uses ``:class:`` for the return types
27755a74a43SLisandro Dalcin    and this does not work with type aliases like ``ArrayScalar``. To resolve
27855a74a43SLisandro Dalcin    this we swap ``:class:`` for ``:any:``.
27955a74a43SLisandro Dalcin
28055a74a43SLisandro Dalcin    """
2816f336411SStefano Zampini    _parse_returns_section = NumpyDocstring._parse_returns_section
28255a74a43SLisandro Dalcin
28355a74a43SLisandro Dalcin    @functools.wraps(NumpyDocstring._parse_returns_section)
28455a74a43SLisandro Dalcin    def wrapper(*args, **kwargs):
28555a74a43SLisandro Dalcin        out = _parse_returns_section(*args, **kwargs)
286a8b7c094SLisandro Dalcin        for role in (':py:class:', ':class:'):
287a8b7c094SLisandro Dalcin            out = [line.replace(role, ':any:') for line in out]
288a8b7c094SLisandro Dalcin        return out
28955a74a43SLisandro Dalcin
29055a74a43SLisandro Dalcin    NumpyDocstring._parse_returns_section = wrapper
29155a74a43SLisandro Dalcin
29255a74a43SLisandro Dalcin
29355a74a43SLisandro Dalcindef _monkey_patch_see_also():
29455a74a43SLisandro Dalcin    """Rewrite the role of names in "see also" sections.
29555a74a43SLisandro Dalcin
29655a74a43SLisandro Dalcin    Napoleon uses :obj: for all names found in "see also" sections but we
29755a74a43SLisandro Dalcin    need :all: so that references to labels work."""
29855a74a43SLisandro Dalcin
2996f336411SStefano Zampini    _parse_numpydoc_see_also_section = NumpyDocstring._parse_numpydoc_see_also_section
30055a74a43SLisandro Dalcin
30155a74a43SLisandro Dalcin    @functools.wraps(NumpyDocstring._parse_numpydoc_see_also_section)
30255a74a43SLisandro Dalcin    def wrapper(*args, **kwargs):
30355a74a43SLisandro Dalcin        out = _parse_numpydoc_see_also_section(*args, **kwargs)
304a8b7c094SLisandro Dalcin        for role in (':py:obj:', ':obj:'):
305a8b7c094SLisandro Dalcin            out = [line.replace(role, ':any:') for line in out]
306a8b7c094SLisandro Dalcin        return out
30755a74a43SLisandro Dalcin
30855a74a43SLisandro Dalcin    NumpyDocstring._parse_numpydoc_see_also_section = wrapper
30955a74a43SLisandro Dalcin
31055a74a43SLisandro Dalcin
31155a74a43SLisandro Dalcindef _apply_monkey_patches():
31255a74a43SLisandro Dalcin    """Modify Napoleon types after parsing to make references work."""
31355a74a43SLisandro Dalcin    _monkey_patch_returns()
31455a74a43SLisandro Dalcin    _monkey_patch_see_also()
31555a74a43SLisandro Dalcin
31655a74a43SLisandro Dalcin
31755a74a43SLisandro Dalcin_apply_monkey_patches()
31855a74a43SLisandro Dalcin
31955a74a43SLisandro Dalcin
32055a74a43SLisandro Dalcindef _process_demos(*demos):
32155a74a43SLisandro Dalcin    # Convert demo .py files to rst. Also copy the .py file so it can be
32255a74a43SLisandro Dalcin    # linked from the demo rst file.
32355a74a43SLisandro Dalcin    try:
3246f336411SStefano Zampini        os.mkdir('demo')
32555a74a43SLisandro Dalcin    except FileExistsError:
32655a74a43SLisandro Dalcin        pass
32755a74a43SLisandro Dalcin    for demo in demos:
3286f336411SStefano Zampini        demo_dir = os.path.join('demo', os.path.dirname(demo))
3296f336411SStefano Zampini        demo_src = os.path.join(os.pardir, os.pardir, 'demo', demo)
33055a74a43SLisandro Dalcin        try:
33155a74a43SLisandro Dalcin            os.mkdir(demo_dir)
33255a74a43SLisandro Dalcin        except FileExistsError:
33355a74a43SLisandro Dalcin            pass
3346f336411SStefano Zampini        with open(demo_src, 'r') as infile:
3356f336411SStefano Zampini            with open(
3366f336411SStefano Zampini                os.path.join(os.path.join('demo', os.path.splitext(demo)[0] + '.rst')),
3376f336411SStefano Zampini                'w',
33855a74a43SLisandro Dalcin            ) as outfile:
33955a74a43SLisandro Dalcin                converter = pylit.Code2Text(infile)
34055a74a43SLisandro Dalcin                outfile.write(str(converter))
34155a74a43SLisandro Dalcin        demo_copy_name = os.path.join(demo_dir, os.path.basename(demo))
34255a74a43SLisandro Dalcin        shutil.copyfile(demo_src, demo_copy_name)
34355a74a43SLisandro Dalcin        html_static_path.append(demo_copy_name)
3446f336411SStefano Zampini    with open(os.path.join('demo', 'demo.rst'), 'w') as demofile:
34555a74a43SLisandro Dalcin        demofile.write("""
34655a74a43SLisandro Dalcinpetsc4py demos
34755a74a43SLisandro Dalcin==============
34855a74a43SLisandro Dalcin
34955a74a43SLisandro Dalcin.. toctree::
35055a74a43SLisandro Dalcin
35155a74a43SLisandro Dalcin""")
35255a74a43SLisandro Dalcin        for demo in demos:
3536f336411SStefano Zampini            demofile.write('    ' + os.path.splitext(demo)[0] + '\n')
3546f336411SStefano Zampini        demofile.write('\n')
3556f336411SStefano Zampini
35655a74a43SLisandro Dalcin
35755a74a43SLisandro Dalcinhtml_static_path = []
3586f336411SStefano Zampini_process_demos('poisson2d/poisson2d.py')
35955a74a43SLisandro Dalcin
36055a74a43SLisandro Dalcin
36155a74a43SLisandro Dalcindef setup(app):
36255a74a43SLisandro Dalcin    _setup_mpi4py_typing()
36355a74a43SLisandro Dalcin    _patch_domain_python()
36455a74a43SLisandro Dalcin    _monkey_patch_returns()
36555a74a43SLisandro Dalcin    _monkey_patch_see_also()
36655a74a43SLisandro Dalcin    _setup_autodoc(app)
36755a74a43SLisandro Dalcin
36855a74a43SLisandro Dalcin    try:
36955a74a43SLisandro Dalcin        from petsc4py import PETSc
37055a74a43SLisandro Dalcin    except ImportError:
37155a74a43SLisandro Dalcin        autodoc_mock_imports.append('PETSc')
37255a74a43SLisandro Dalcin        return
37355a74a43SLisandro Dalcin    del PETSc.DA  # FIXME
37455a74a43SLisandro Dalcin
37555a74a43SLisandro Dalcin    sys_dwb = sys.dont_write_bytecode
37655a74a43SLisandro Dalcin    sys.dont_write_bytecode = True
37755a74a43SLisandro Dalcin    import apidoc
3786f336411SStefano Zampini
37955a74a43SLisandro Dalcin    sys.dont_write_bytecode = sys_dwb
38055a74a43SLisandro Dalcin
38155a74a43SLisandro Dalcin    name = PETSc.__name__
38255a74a43SLisandro Dalcin    here = os.path.abspath(os.path.dirname(__file__))
38355a74a43SLisandro Dalcin    outdir = os.path.join(here, apidoc.OUTDIR)
38455a74a43SLisandro Dalcin    source = os.path.join(outdir, f'{name}.py')
38555a74a43SLisandro Dalcin    getmtime = os.path.getmtime
38655a74a43SLisandro Dalcin    generate = (
38755a74a43SLisandro Dalcin        not os.path.exists(source)
38855a74a43SLisandro Dalcin        or getmtime(source) < getmtime(PETSc.__file__)
38955a74a43SLisandro Dalcin        or getmtime(source) < getmtime(apidoc.__file__)
39055a74a43SLisandro Dalcin    )
39155a74a43SLisandro Dalcin    if generate:
39255a74a43SLisandro Dalcin        apidoc.generate(source)
39355a74a43SLisandro Dalcin    module = apidoc.load_module(source)
39455a74a43SLisandro Dalcin    apidoc.replace_module(module)
39555a74a43SLisandro Dalcin
39655a74a43SLisandro Dalcin    modules = [
39755a74a43SLisandro Dalcin        'petsc4py',
39855a74a43SLisandro Dalcin    ]
39955a74a43SLisandro Dalcin    typing_overload = typing.overload
40055a74a43SLisandro Dalcin    typing.overload = lambda arg: arg
40155a74a43SLisandro Dalcin    for name in modules:
40255a74a43SLisandro Dalcin        mod = importlib.import_module(name)
40355a74a43SLisandro Dalcin        ann = apidoc.load_module(f'{mod.__file__}i', name)
40455a74a43SLisandro Dalcin        apidoc.annotate(mod, ann)
40555a74a43SLisandro Dalcin    typing.overload = typing_overload
40655a74a43SLisandro Dalcin
40755a74a43SLisandro Dalcin    from petsc4py import typing as tp
4086f336411SStefano Zampini
40955a74a43SLisandro Dalcin    for attr in tp.__all__:
41055a74a43SLisandro Dalcin        autodoc_type_aliases[attr] = f'~petsc4py.typing.{attr}'
41155a74a43SLisandro Dalcin
4126f336411SStefano Zampini
41355a74a43SLisandro Dalcin# -- Options for HTML output -------------------------------------------------
41455a74a43SLisandro Dalcin# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
4155808f684SSatish Balay
4165808f684SSatish Balay# The theme to use for HTML and HTML Help pages.  See the documentation for
4175808f684SSatish Balay# a list of builtin themes.
41855a74a43SLisandro Dalcinhtml_theme = 'pydata_sphinx_theme'
4195808f684SSatish Balay
4202c804a55SBarry Smithhtml_theme_options = {
4212c804a55SBarry Smith    'navigation_with_keys': True,
4227e3bcaecSStefano Zampini    'footer_end': ['theme-version', 'last-updated'],
4232c804a55SBarry Smith}
4247e3bcaecSStefano Zampinigit_describe_version = (
4257e3bcaecSStefano Zampini    subprocess.check_output(['git', 'describe', '--always']).strip().decode('utf-8')  # noqa: S603, S607
4267e3bcaecSStefano Zampini)
4272c804a55SBarry Smithhtml_last_updated_fmt = r'%Y-%m-%dT%H:%M:%S%z (' + git_describe_version + ')'
428bc1908f0SBarry Smith
4295808f684SSatish Balay# -- Options for HTMLHelp output ------------------------------------------
4305808f684SSatish Balay
4315808f684SSatish Balay# Output file base name for HTML help builder.
43255a74a43SLisandro Dalcinhtmlhelp_basename = f'{package}-man'
4335808f684SSatish Balay
4345808f684SSatish Balay
4355808f684SSatish Balay# -- Options for LaTeX output ---------------------------------------------
4365808f684SSatish Balay
4375808f684SSatish Balay# (source start file, target name, title,
4385808f684SSatish Balay#  author, documentclass [howto, manual, or own class]).
4395808f684SSatish Balaylatex_documents = [
4406f336411SStefano Zampini    ('index', f'{package}.tex', __project__, __author__, 'howto'),
4415808f684SSatish Balay]
4425808f684SSatish Balay
44355a74a43SLisandro Dalcinlatex_elements = {
44455a74a43SLisandro Dalcin    'papersize': 'a4',
44555a74a43SLisandro Dalcin}
44655a74a43SLisandro Dalcin
4475808f684SSatish Balay
4485808f684SSatish Balay# -- Options for manual page output ---------------------------------------
4495808f684SSatish Balay
4505808f684SSatish Balay# (source start file, name, description, authors, manual section).
4516f336411SStefano Zampiniman_pages = [('index', package, __project__, [__author__], 3)]
4525808f684SSatish Balay
4535808f684SSatish Balay
4545808f684SSatish Balay# -- Options for Texinfo output -------------------------------------------
4555808f684SSatish Balay
4565808f684SSatish Balay# (source start file, target name, title, author,
4575808f684SSatish Balay#  dir menu entry, description, category)
4585808f684SSatish Balaytexinfo_documents = [
4596f336411SStefano Zampini    (
4606f336411SStefano Zampini        'index',
4616f336411SStefano Zampini        package,
4626f336411SStefano Zampini        __project__,
4636f336411SStefano Zampini        __author__,
4646f336411SStefano Zampini        package,
4656f336411SStefano Zampini        f'{__project__}.',
4666f336411SStefano Zampini        'Miscellaneous',
4676f336411SStefano Zampini    ),
4685808f684SSatish Balay]
4695808f684SSatish Balay
47055a74a43SLisandro Dalcin
4715808f684SSatish Balay# -- Options for Epub output ----------------------------------------------
4725808f684SSatish Balay
47355a74a43SLisandro Dalcin# Output file base name for ePub builder.
47455a74a43SLisandro Dalcinepub_basename = package
475