xref: /petsc/src/binding/petsc4py/docs/source/conf.py (revision 6f33641175f69f1db294cc9ba81c3f4ad4f81d49)
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
1655a74a43SLisandro Dalcinimport typing
1755a74a43SLisandro Dalcinimport datetime
1855a74a43SLisandro Dalcinimport importlib
1955a74a43SLisandro Dalcinimport sphobjinv
2055a74a43SLisandro Dalcinimport functools
2155a74a43SLisandro Dalcinimport pylit
2255a74a43SLisandro Dalcinfrom sphinx.ext.napoleon.docstring import NumpyDocstring
2355a74a43SLisandro Dalcin
2455a74a43SLisandro Dalcinsys.path.insert(0, os.path.abspath('.'))
2555a74a43SLisandro Dalcin_today = datetime.datetime.now()
2655a74a43SLisandro Dalcin
27*6f336411SStefano Zampini# FIXME: allow building from build?
2855a74a43SLisandro Dalcin
2955a74a43SLisandro Dalcin# -- Project information -----------------------------------------------------
3055a74a43SLisandro Dalcin# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
3155a74a43SLisandro Dalcin
3255a74a43SLisandro Dalcinpackage = 'petsc4py'
3355a74a43SLisandro Dalcin
34d919c72dSLisandro Dalcindocdir = os.path.abspath(os.path.dirname(__file__))
35d919c72dSLisandro Dalcintopdir = os.path.abspath(os.path.join(docdir, *[os.path.pardir] * 2))
3655a74a43SLisandro Dalcin
37*6f336411SStefano Zampini
3855a74a43SLisandro Dalcindef pkg_version():
39d919c72dSLisandro Dalcin    with open(os.path.join(topdir, 'src', package, '__init__.py')) as f:
405808f684SSatish Balay        m = re.search(r"__version__\s*=\s*'(.*)'", f.read())
415808f684SSatish Balay        return m.groups()[0]
425808f684SSatish Balay
435808f684SSatish Balay
44d919c72dSLisandro Dalcindef get_doc_branch():
45d919c72dSLisandro Dalcin    release = 1
46d919c72dSLisandro Dalcin    if topdir.endswith(os.path.join(os.path.sep, 'src', 'binding', package)):
47d919c72dSLisandro Dalcin        rootdir = os.path.abspath(os.path.join(topdir, *[os.path.pardir] * 3))
48d919c72dSLisandro Dalcin        rootname = package.replace('4py', '')
49d919c72dSLisandro Dalcin        version_h = os.path.join(rootdir, 'include', f'{rootname}version.h')
50d919c72dSLisandro Dalcin        if os.path.exists(version_h) and os.path.isfile(version_h):
51d919c72dSLisandro Dalcin            release_macro = f'{rootname.upper()}_VERSION_RELEASE'
52*6f336411SStefano Zampini            version_re = re.compile(rf'#define\s+{release_macro}\s+([-]*\d+)')
53d919c72dSLisandro Dalcin            with open(version_h, 'r') as f:
54d919c72dSLisandro Dalcin                release = int(version_re.search(f.read()).groups()[0])
55d919c72dSLisandro Dalcin    return 'release' if release else 'main'
56d919c72dSLisandro Dalcin
57d919c72dSLisandro Dalcin
58*6f336411SStefano Zampini__project__ = 'PETSc for Python'
59*6f336411SStefano Zampini__author__ = 'Lisandro Dalcin'
60*6f336411SStefano Zampini__copyright__ = f'{_today.year}, {__author__}'
615808f684SSatish Balay
6255a74a43SLisandro Dalcinrelease = pkg_version()
6355a74a43SLisandro Dalcinversion = release.rsplit('.', 1)[0]
645808f684SSatish Balay
655808f684SSatish Balay
6655a74a43SLisandro Dalcin# -- General configuration ---------------------------------------------------
6755a74a43SLisandro Dalcin# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
685808f684SSatish Balay
6955a74a43SLisandro Dalcinextensions = [
7055a74a43SLisandro Dalcin    'sphinx.ext.autodoc',
7155a74a43SLisandro Dalcin    'sphinx.ext.autosummary',
7255a74a43SLisandro Dalcin    'sphinx.ext.intersphinx',
7355a74a43SLisandro Dalcin    'sphinx.ext.napoleon',
74b3f8c7a1SStefano Zampini    'sphinx.ext.extlinks',
7555a74a43SLisandro Dalcin]
765808f684SSatish Balay
7755a74a43SLisandro Dalcintemplates_path = ['_templates']
785808f684SSatish Balayexclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
795808f684SSatish Balay
8055a74a43SLisandro Dalcinneeds_sphinx = '5.0.0'
815808f684SSatish Balay
8255a74a43SLisandro Dalcindefault_role = 'any'
8355a74a43SLisandro Dalcin
8455a74a43SLisandro Dalcinpygments_style = 'tango'
8555a74a43SLisandro Dalcin
8655a74a43SLisandro Dalcinnitpicky = True
8755a74a43SLisandro Dalcinnitpick_ignore = [
8855a74a43SLisandro Dalcin    ('envvar', 'NUMPY_INCLUDE'),
8955a74a43SLisandro Dalcin    ('py:class', 'ndarray'),  # FIXME
9055a74a43SLisandro Dalcin    ('py:class', 'typing_extensions.Self'),
9155a74a43SLisandro Dalcin]
9255a74a43SLisandro Dalcinnitpick_ignore_regex = [
9355a74a43SLisandro Dalcin    (r'c:.*', r'MPI_.*'),
9455a74a43SLisandro Dalcin    (r'c:.*', r'Petsc.*'),
9555a74a43SLisandro Dalcin    (r'envvar', r'(LD_LIBRARY_)?PATH'),
9655a74a43SLisandro Dalcin    (r'envvar', r'(MPICH|OMPI|MPIEXEC)_.*'),
9755a74a43SLisandro Dalcin]
9855a74a43SLisandro Dalcin
9955a74a43SLisandro Dalcintoc_object_entries = False
10055a74a43SLisandro Dalcintoc_object_entries_show_parents = 'hide'
10155a74a43SLisandro Dalcin# python_use_unqualified_type_names = True
10255a74a43SLisandro Dalcin
10355a74a43SLisandro Dalcinautodoc_class_signature = 'separated'
10455a74a43SLisandro Dalcinautodoc_typehints = 'description'
10555a74a43SLisandro Dalcinautodoc_typehints_format = 'short'
10655a74a43SLisandro Dalcinautodoc_mock_imports = []
10755a74a43SLisandro Dalcinautodoc_type_aliases = {}
10855a74a43SLisandro Dalcin
10955a74a43SLisandro Dalcinautosummary_context = {
11055a74a43SLisandro Dalcin    'synopsis': {},
11155a74a43SLisandro Dalcin    'autotype': {},
11255a74a43SLisandro Dalcin}
1135808f684SSatish Balay
1141d9f564dSStefano Zampini# Links depends on the actual branch -> release or main
1151d9f564dSStefano Zampiniwww = f'https://gitlab.com/petsc/petsc/-/tree/{get_doc_branch()}'
116*6f336411SStefano Zampiniextlinks = {'sources': (f'{www}/src/binding/petsc4py/src/%s', '%s')}
1175808f684SSatish Balay
118d919c72dSLisandro Dalcinnapoleon_preprocess_types = True
119d919c72dSLisandro Dalcin
120d919c72dSLisandro Dalcintry:
121d919c72dSLisandro Dalcin    import sphinx_rtd_theme
122*6f336411SStefano Zampini
123d919c72dSLisandro Dalcin    if 'sphinx_rtd_theme' not in extensions:
124d919c72dSLisandro Dalcin        extensions.append('sphinx_rtd_theme')
125d919c72dSLisandro Dalcinexcept ImportError:
126d919c72dSLisandro Dalcin    sphinx_rtd_theme = None
127d919c72dSLisandro Dalcin
128d919c72dSLisandro Dalcinintersphinx_mapping = {
129d919c72dSLisandro Dalcin    'python': ('https://docs.python.org/3/', None),
130d919c72dSLisandro Dalcin    'numpy': ('https://numpy.org/doc/stable/', None),
131d919c72dSLisandro Dalcin    'numpydoc': ('https://numpydoc.readthedocs.io/en/latest/', None),
132d919c72dSLisandro Dalcin    'mpi4py': ('https://mpi4py.readthedocs.io/en/stable/', None),
133d919c72dSLisandro Dalcin    'pyopencl': ('https://documen.tician.de/pyopencl/', None),
134d919c72dSLisandro Dalcin    'dlpack': ('https://dmlc.github.io/dlpack/latest/', None),
135d919c72dSLisandro Dalcin    'petsc': ('https://petsc.org/release/', None),
136d919c72dSLisandro Dalcin}
137d919c72dSLisandro Dalcin
138*6f336411SStefano Zampini
13955a74a43SLisandro Dalcindef _mangle_petsc_intersphinx():
14055a74a43SLisandro Dalcin    """Preprocess the keys in PETSc's intersphinx inventory.
14155a74a43SLisandro Dalcin
14255a74a43SLisandro Dalcin    PETSc have intersphinx keys of the form:
14355a74a43SLisandro Dalcin
14455a74a43SLisandro Dalcin        manualpages/Vec/VecShift
14555a74a43SLisandro Dalcin
14655a74a43SLisandro Dalcin    instead of:
14755a74a43SLisandro Dalcin
14855a74a43SLisandro Dalcin        petsc.VecShift
14955a74a43SLisandro Dalcin
15055a74a43SLisandro Dalcin    This function downloads their object inventory and strips the leading path
15155a74a43SLisandro Dalcin    elements so that references to PETSc names actually resolve."""
152e3ec4a52SBarry Smith
153d919c72dSLisandro Dalcin    website = intersphinx_mapping['petsc'][0].partition('/release/')[0]
154d919c72dSLisandro Dalcin    branch = get_doc_branch()
155*6f336411SStefano Zampini    doc_url = f'{website}/{branch}/'
156*6f336411SStefano Zampini    if 'LOC' in os.environ and os.path.isfile(
157*6f336411SStefano Zampini        os.path.join(os.environ['LOC'], 'objects.inv')
158*6f336411SStefano Zampini    ):
159*6f336411SStefano Zampini        inventory_url = 'file://' + os.path.join(os.environ['LOC'], 'objects.inv')
1600c386d85SStefano Zampini    else:
161*6f336411SStefano Zampini        inventory_url = f'{doc_url}objects.inv'
162*6f336411SStefano Zampini    print('Using PETSC inventory from ' + inventory_url)
1630c386d85SStefano Zampini    inventory = sphobjinv.Inventory(url=inventory_url)
164e3ec4a52SBarry Smith    print(inventory)
165d919c72dSLisandro Dalcin
166d919c72dSLisandro Dalcin    for obj in inventory.objects:
167*6f336411SStefano Zampini        if obj.name.startswith('manualpages'):
168*6f336411SStefano Zampini            obj.name = 'petsc.' + '/'.join(obj.name.split('/')[2:])
169*6f336411SStefano Zampini            obj.role = 'class'
170*6f336411SStefano Zampini            obj.domain = 'py'
17155a74a43SLisandro Dalcin
172*6f336411SStefano Zampini    new_inventory_filename = 'petsc_objects.inv'
173d919c72dSLisandro Dalcin    sphobjinv.writebytes(
174*6f336411SStefano Zampini        new_inventory_filename, sphobjinv.compress(inventory.data_file(contract=True))
175d919c72dSLisandro Dalcin    )
1760c386d85SStefano Zampini    intersphinx_mapping['petsc'] = (doc_url, new_inventory_filename)
17755a74a43SLisandro Dalcin
17855a74a43SLisandro Dalcin
17955a74a43SLisandro Dalcin_mangle_petsc_intersphinx()
18055a74a43SLisandro Dalcin
18155a74a43SLisandro Dalcin
18255a74a43SLisandro Dalcindef _setup_mpi4py_typing():
18355a74a43SLisandro Dalcin    pkg = type(sys)('mpi4py')
18455a74a43SLisandro Dalcin    mod = type(sys)('mpi4py.MPI')
18555a74a43SLisandro Dalcin    mod.__package__ = pkg.__name__
18655a74a43SLisandro Dalcin    sys.modules[pkg.__name__] = pkg
18755a74a43SLisandro Dalcin    sys.modules[mod.__name__] = mod
18855a74a43SLisandro Dalcin    for clsname in (
18955a74a43SLisandro Dalcin        'Intracomm',
19055a74a43SLisandro Dalcin        'Datatype',
19155a74a43SLisandro Dalcin        'Op',
19255a74a43SLisandro Dalcin    ):
19355a74a43SLisandro Dalcin        cls = type(clsname, (), {})
19455a74a43SLisandro Dalcin        cls.__module__ = mod.__name__
19555a74a43SLisandro Dalcin        setattr(mod, clsname, cls)
19655a74a43SLisandro Dalcin
19755a74a43SLisandro Dalcin
19855a74a43SLisandro Dalcindef _patch_domain_python():
19955a74a43SLisandro Dalcin    from sphinx.domains.python import PythonDomain
200*6f336411SStefano Zampini
20155a74a43SLisandro Dalcin    PythonDomain.object_types['data'].roles += ('class',)
20255a74a43SLisandro Dalcin
20355a74a43SLisandro Dalcin
20455a74a43SLisandro Dalcindef _setup_autodoc(app):
20555a74a43SLisandro Dalcin    from sphinx.ext import autodoc
20655a74a43SLisandro Dalcin    from sphinx.util import inspect
20755a74a43SLisandro Dalcin    from sphinx.util import typing
20855a74a43SLisandro Dalcin
20955a74a43SLisandro Dalcin    #
21055a74a43SLisandro Dalcin
21155a74a43SLisandro Dalcin    def stringify_annotation(annotation, mode='fully-qualified-except-typing'):
21255a74a43SLisandro Dalcin        qualname = getattr(annotation, '__qualname__', '')
21355a74a43SLisandro Dalcin        module = getattr(annotation, '__module__', '')
21455a74a43SLisandro Dalcin        args = getattr(annotation, '__args__', None)
21555a74a43SLisandro Dalcin        if module == 'builtins' and qualname and args is not None:
21655a74a43SLisandro Dalcin            args = ', '.join(stringify_annotation(a, mode) for a in args)
21755a74a43SLisandro Dalcin            return f'{qualname}[{args}]'
21855a74a43SLisandro Dalcin        return stringify_annotation_orig(annotation, mode)
21955a74a43SLisandro Dalcin
22055a74a43SLisandro Dalcin    try:
22155a74a43SLisandro Dalcin        stringify_annotation_orig = typing.stringify_annotation
22255a74a43SLisandro Dalcin        inspect.stringify_annotation = stringify_annotation
22355a74a43SLisandro Dalcin        typing.stringify_annotation = stringify_annotation
22455a74a43SLisandro Dalcin        autodoc.stringify_annotation = stringify_annotation
22555a74a43SLisandro Dalcin        autodoc.typehints.stringify_annotation = stringify_annotation
22655a74a43SLisandro Dalcin    except AttributeError:
22755a74a43SLisandro Dalcin        stringify_annotation_orig = typing.stringify
22855a74a43SLisandro Dalcin        inspect.stringify_annotation = stringify_annotation
22955a74a43SLisandro Dalcin        typing.stringify = stringify_annotation
23055a74a43SLisandro Dalcin        autodoc.stringify_typehint = stringify_annotation
23155a74a43SLisandro Dalcin
23255a74a43SLisandro Dalcin    #
23355a74a43SLisandro Dalcin
23455a74a43SLisandro Dalcin    class ClassDocumenterMixin:
23555a74a43SLisandro Dalcin        def __init__(self, *args, **kwargs):
23655a74a43SLisandro Dalcin            super().__init__(*args, **kwargs)
23755a74a43SLisandro Dalcin            if self.config.autodoc_class_signature == 'separated':
23855a74a43SLisandro Dalcin                members = self.options.members
23955a74a43SLisandro Dalcin                special_members = self.options.special_members
24055a74a43SLisandro Dalcin                if special_members is not None:
24155a74a43SLisandro Dalcin                    for name in ('__new__', '__init__'):
24255a74a43SLisandro Dalcin                        if name in members:
24355a74a43SLisandro Dalcin                            members.remove(name)
24455a74a43SLisandro Dalcin                        if name in special_members:
24555a74a43SLisandro Dalcin                            special_members.remove(name)
24655a74a43SLisandro Dalcin
24755a74a43SLisandro Dalcin    class ClassDocumenter(
24855a74a43SLisandro Dalcin        ClassDocumenterMixin,
24955a74a43SLisandro Dalcin        autodoc.ClassDocumenter,
25055a74a43SLisandro Dalcin    ):
25155a74a43SLisandro Dalcin        pass
25255a74a43SLisandro Dalcin
25355a74a43SLisandro Dalcin    class ExceptionDocumenter(
25455a74a43SLisandro Dalcin        ClassDocumenterMixin,
25555a74a43SLisandro Dalcin        autodoc.ExceptionDocumenter,
25655a74a43SLisandro Dalcin    ):
25755a74a43SLisandro Dalcin        pass
25855a74a43SLisandro Dalcin
25955a74a43SLisandro Dalcin    app.add_autodocumenter(ClassDocumenter, override=True)
26055a74a43SLisandro Dalcin    app.add_autodocumenter(ExceptionDocumenter, override=True)
26155a74a43SLisandro Dalcin
26255a74a43SLisandro Dalcin
26355a74a43SLisandro Dalcindef _monkey_patch_returns():
26455a74a43SLisandro Dalcin    """Rewrite the role of names in "Returns" sections.
26555a74a43SLisandro Dalcin
26655a74a43SLisandro Dalcin    This is needed because Napoleon uses ``:class:`` for the return types
26755a74a43SLisandro Dalcin    and this does not work with type aliases like ``ArrayScalar``. To resolve
26855a74a43SLisandro Dalcin    this we swap ``:class:`` for ``:any:``.
26955a74a43SLisandro Dalcin
27055a74a43SLisandro Dalcin    """
271*6f336411SStefano Zampini    _parse_returns_section = NumpyDocstring._parse_returns_section
27255a74a43SLisandro Dalcin
27355a74a43SLisandro Dalcin    @functools.wraps(NumpyDocstring._parse_returns_section)
27455a74a43SLisandro Dalcin    def wrapper(*args, **kwargs):
27555a74a43SLisandro Dalcin        out = _parse_returns_section(*args, **kwargs)
276*6f336411SStefano Zampini        return [line.replace(':class:', ':any:') for line in out]
27755a74a43SLisandro Dalcin
27855a74a43SLisandro Dalcin    NumpyDocstring._parse_returns_section = wrapper
27955a74a43SLisandro Dalcin
28055a74a43SLisandro Dalcin
28155a74a43SLisandro Dalcindef _monkey_patch_see_also():
28255a74a43SLisandro Dalcin    """Rewrite the role of names in "see also" sections.
28355a74a43SLisandro Dalcin
28455a74a43SLisandro Dalcin    Napoleon uses :obj: for all names found in "see also" sections but we
28555a74a43SLisandro Dalcin    need :all: so that references to labels work."""
28655a74a43SLisandro Dalcin
287*6f336411SStefano Zampini    _parse_numpydoc_see_also_section = NumpyDocstring._parse_numpydoc_see_also_section
28855a74a43SLisandro Dalcin
28955a74a43SLisandro Dalcin    @functools.wraps(NumpyDocstring._parse_numpydoc_see_also_section)
29055a74a43SLisandro Dalcin    def wrapper(*args, **kwargs):
29155a74a43SLisandro Dalcin        out = _parse_numpydoc_see_also_section(*args, **kwargs)
292*6f336411SStefano Zampini        return [line.replace(':obj:', ':any:') for line in out]
29355a74a43SLisandro Dalcin
29455a74a43SLisandro Dalcin    NumpyDocstring._parse_numpydoc_see_also_section = wrapper
29555a74a43SLisandro Dalcin
29655a74a43SLisandro Dalcin
29755a74a43SLisandro Dalcindef _apply_monkey_patches():
29855a74a43SLisandro Dalcin    """Modify Napoleon types after parsing to make references work."""
29955a74a43SLisandro Dalcin    _monkey_patch_returns()
30055a74a43SLisandro Dalcin    _monkey_patch_see_also()
30155a74a43SLisandro Dalcin
30255a74a43SLisandro Dalcin
30355a74a43SLisandro Dalcin_apply_monkey_patches()
30455a74a43SLisandro Dalcin
30555a74a43SLisandro Dalcin
30655a74a43SLisandro Dalcindef _process_demos(*demos):
30755a74a43SLisandro Dalcin    # Convert demo .py files to rst. Also copy the .py file so it can be
30855a74a43SLisandro Dalcin    # linked from the demo rst file.
30955a74a43SLisandro Dalcin    try:
310*6f336411SStefano Zampini        os.mkdir('demo')
31155a74a43SLisandro Dalcin    except FileExistsError:
31255a74a43SLisandro Dalcin        pass
31355a74a43SLisandro Dalcin    for demo in demos:
314*6f336411SStefano Zampini        demo_dir = os.path.join('demo', os.path.dirname(demo))
315*6f336411SStefano Zampini        demo_src = os.path.join(os.pardir, os.pardir, 'demo', demo)
31655a74a43SLisandro Dalcin        try:
31755a74a43SLisandro Dalcin            os.mkdir(demo_dir)
31855a74a43SLisandro Dalcin        except FileExistsError:
31955a74a43SLisandro Dalcin            pass
320*6f336411SStefano Zampini        with open(demo_src, 'r') as infile:
321*6f336411SStefano Zampini            with open(
322*6f336411SStefano Zampini                os.path.join(os.path.join('demo', os.path.splitext(demo)[0] + '.rst')),
323*6f336411SStefano Zampini                'w',
32455a74a43SLisandro Dalcin            ) as outfile:
32555a74a43SLisandro Dalcin                converter = pylit.Code2Text(infile)
32655a74a43SLisandro Dalcin                outfile.write(str(converter))
32755a74a43SLisandro Dalcin        demo_copy_name = os.path.join(demo_dir, os.path.basename(demo))
32855a74a43SLisandro Dalcin        shutil.copyfile(demo_src, demo_copy_name)
32955a74a43SLisandro Dalcin        html_static_path.append(demo_copy_name)
330*6f336411SStefano Zampini    with open(os.path.join('demo', 'demo.rst'), 'w') as demofile:
33155a74a43SLisandro Dalcin        demofile.write("""
33255a74a43SLisandro Dalcinpetsc4py demos
33355a74a43SLisandro Dalcin==============
33455a74a43SLisandro Dalcin
33555a74a43SLisandro Dalcin.. toctree::
33655a74a43SLisandro Dalcin
33755a74a43SLisandro Dalcin""")
33855a74a43SLisandro Dalcin        for demo in demos:
339*6f336411SStefano Zampini            demofile.write('    ' + os.path.splitext(demo)[0] + '\n')
340*6f336411SStefano Zampini        demofile.write('\n')
341*6f336411SStefano Zampini
34255a74a43SLisandro Dalcin
34355a74a43SLisandro Dalcinhtml_static_path = []
344*6f336411SStefano Zampini_process_demos('poisson2d/poisson2d.py')
34555a74a43SLisandro Dalcin
34655a74a43SLisandro Dalcin
34755a74a43SLisandro Dalcindef setup(app):
34855a74a43SLisandro Dalcin    _setup_mpi4py_typing()
34955a74a43SLisandro Dalcin    _patch_domain_python()
35055a74a43SLisandro Dalcin    _monkey_patch_returns()
35155a74a43SLisandro Dalcin    _monkey_patch_see_also()
35255a74a43SLisandro Dalcin    _setup_autodoc(app)
35355a74a43SLisandro Dalcin
35455a74a43SLisandro Dalcin    try:
35555a74a43SLisandro Dalcin        from petsc4py import PETSc
35655a74a43SLisandro Dalcin    except ImportError:
35755a74a43SLisandro Dalcin        autodoc_mock_imports.append('PETSc')
35855a74a43SLisandro Dalcin        return
35955a74a43SLisandro Dalcin    del PETSc.DA  # FIXME
36055a74a43SLisandro Dalcin
36155a74a43SLisandro Dalcin    sys_dwb = sys.dont_write_bytecode
36255a74a43SLisandro Dalcin    sys.dont_write_bytecode = True
36355a74a43SLisandro Dalcin    import apidoc
364*6f336411SStefano Zampini
36555a74a43SLisandro Dalcin    sys.dont_write_bytecode = sys_dwb
36655a74a43SLisandro Dalcin
36755a74a43SLisandro Dalcin    name = PETSc.__name__
36855a74a43SLisandro Dalcin    here = os.path.abspath(os.path.dirname(__file__))
36955a74a43SLisandro Dalcin    outdir = os.path.join(here, apidoc.OUTDIR)
37055a74a43SLisandro Dalcin    source = os.path.join(outdir, f'{name}.py')
37155a74a43SLisandro Dalcin    getmtime = os.path.getmtime
37255a74a43SLisandro Dalcin    generate = (
37355a74a43SLisandro Dalcin        not os.path.exists(source)
37455a74a43SLisandro Dalcin        or getmtime(source) < getmtime(PETSc.__file__)
37555a74a43SLisandro Dalcin        or getmtime(source) < getmtime(apidoc.__file__)
37655a74a43SLisandro Dalcin    )
37755a74a43SLisandro Dalcin    if generate:
37855a74a43SLisandro Dalcin        apidoc.generate(source)
37955a74a43SLisandro Dalcin    module = apidoc.load_module(source)
38055a74a43SLisandro Dalcin    apidoc.replace_module(module)
38155a74a43SLisandro Dalcin
38255a74a43SLisandro Dalcin    modules = [
38355a74a43SLisandro Dalcin        'petsc4py',
38455a74a43SLisandro Dalcin    ]
38555a74a43SLisandro Dalcin    typing_overload = typing.overload
38655a74a43SLisandro Dalcin    typing.overload = lambda arg: arg
38755a74a43SLisandro Dalcin    for name in modules:
38855a74a43SLisandro Dalcin        mod = importlib.import_module(name)
38955a74a43SLisandro Dalcin        ann = apidoc.load_module(f'{mod.__file__}i', name)
39055a74a43SLisandro Dalcin        apidoc.annotate(mod, ann)
39155a74a43SLisandro Dalcin    typing.overload = typing_overload
39255a74a43SLisandro Dalcin
39355a74a43SLisandro Dalcin    from petsc4py import typing as tp
394*6f336411SStefano Zampini
39555a74a43SLisandro Dalcin    for attr in tp.__all__:
39655a74a43SLisandro Dalcin        autodoc_type_aliases[attr] = f'~petsc4py.typing.{attr}'
39755a74a43SLisandro Dalcin
398*6f336411SStefano Zampini
39955a74a43SLisandro Dalcin# -- Options for HTML output -------------------------------------------------
40055a74a43SLisandro Dalcin# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
4015808f684SSatish Balay
4025808f684SSatish Balay# The theme to use for HTML and HTML Help pages.  See the documentation for
4035808f684SSatish Balay# a list of builtin themes.
40455a74a43SLisandro Dalcinhtml_theme = 'pydata_sphinx_theme'
4055808f684SSatish Balay
406*6f336411SStefano Zampinihtml_theme_options = {'navigation_with_keys': True}
407bc1908f0SBarry Smith
4085808f684SSatish Balay# -- Options for HTMLHelp output ------------------------------------------
4095808f684SSatish Balay
4105808f684SSatish Balay# Output file base name for HTML help builder.
41155a74a43SLisandro Dalcinhtmlhelp_basename = f'{package}-man'
4125808f684SSatish Balay
4135808f684SSatish Balay
4145808f684SSatish Balay# -- Options for LaTeX output ---------------------------------------------
4155808f684SSatish Balay
4165808f684SSatish Balay# (source start file, target name, title,
4175808f684SSatish Balay#  author, documentclass [howto, manual, or own class]).
4185808f684SSatish Balaylatex_documents = [
419*6f336411SStefano Zampini    ('index', f'{package}.tex', __project__, __author__, 'howto'),
4205808f684SSatish Balay]
4215808f684SSatish Balay
42255a74a43SLisandro Dalcinlatex_elements = {
42355a74a43SLisandro Dalcin    'papersize': 'a4',
42455a74a43SLisandro Dalcin}
42555a74a43SLisandro Dalcin
4265808f684SSatish Balay
4275808f684SSatish Balay# -- Options for manual page output ---------------------------------------
4285808f684SSatish Balay
4295808f684SSatish Balay# (source start file, name, description, authors, manual section).
430*6f336411SStefano Zampiniman_pages = [('index', package, __project__, [__author__], 3)]
4315808f684SSatish Balay
4325808f684SSatish Balay
4335808f684SSatish Balay# -- Options for Texinfo output -------------------------------------------
4345808f684SSatish Balay
4355808f684SSatish Balay# (source start file, target name, title, author,
4365808f684SSatish Balay#  dir menu entry, description, category)
4375808f684SSatish Balaytexinfo_documents = [
438*6f336411SStefano Zampini    (
439*6f336411SStefano Zampini        'index',
440*6f336411SStefano Zampini        package,
441*6f336411SStefano Zampini        __project__,
442*6f336411SStefano Zampini        __author__,
443*6f336411SStefano Zampini        package,
444*6f336411SStefano Zampini        f'{__project__}.',
445*6f336411SStefano Zampini        'Miscellaneous',
446*6f336411SStefano Zampini    ),
4475808f684SSatish Balay]
4485808f684SSatish Balay
44955a74a43SLisandro Dalcin
4505808f684SSatish Balay# -- Options for Epub output ----------------------------------------------
4515808f684SSatish Balay
45255a74a43SLisandro Dalcin# Output file base name for ePub builder.
45355a74a43SLisandro Dalcinepub_basename = package
454