xref: /petsc/src/binding/petsc4py/docs/source/conf.py (revision d919c72d2de0eb5c3eb5bf7264ee17d105b04577)
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
12*d919c72dSLisandro 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
2755a74a43SLisandro Dalcin
2855a74a43SLisandro Dalcin# -- Project information -----------------------------------------------------
2955a74a43SLisandro Dalcin# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
3055a74a43SLisandro Dalcin
3155a74a43SLisandro Dalcinpackage = 'petsc4py'
3255a74a43SLisandro Dalcin
33*d919c72dSLisandro Dalcindocdir = os.path.abspath(os.path.dirname(__file__))
34*d919c72dSLisandro Dalcintopdir = os.path.abspath(os.path.join(docdir, *[os.path.pardir]*2))
3555a74a43SLisandro Dalcin
3655a74a43SLisandro Dalcindef pkg_version():
37*d919c72dSLisandro Dalcin    with open(os.path.join(topdir, 'src', package, '__init__.py')) as f:
385808f684SSatish Balay        m = re.search(r"__version__\s*=\s*'(.*)'", f.read())
395808f684SSatish Balay        return m.groups()[0]
405808f684SSatish Balay
415808f684SSatish Balay
42*d919c72dSLisandro Dalcindef get_doc_branch():
43*d919c72dSLisandro Dalcin    release = 1
44*d919c72dSLisandro Dalcin    if topdir.endswith(os.path.join(os.path.sep, 'src', 'binding', package)):
45*d919c72dSLisandro Dalcin        rootdir = os.path.abspath(os.path.join(topdir, *[os.path.pardir]*3))
46*d919c72dSLisandro Dalcin        rootname = package.replace('4py', '')
47*d919c72dSLisandro Dalcin        version_h = os.path.join(rootdir, 'include', f'{rootname}version.h')
48*d919c72dSLisandro Dalcin        if os.path.exists(version_h) and os.path.isfile(version_h):
49*d919c72dSLisandro Dalcin            release_macro = f'{rootname.upper()}_VERSION_RELEASE'
50*d919c72dSLisandro Dalcin            version_re = re.compile(rf"#define\s+{release_macro}\s+([-]*\d+)")
51*d919c72dSLisandro Dalcin            with open(version_h, 'r') as f:
52*d919c72dSLisandro Dalcin                release = int(version_re.search(f.read()).groups()[0])
53*d919c72dSLisandro Dalcin    return 'release' if release else 'main'
54*d919c72dSLisandro Dalcin
55*d919c72dSLisandro Dalcin
5655a74a43SLisandro Dalcinproject = 'PETSc for Python'
5755a74a43SLisandro Dalcinauthor = 'Lisandro Dalcin'
5855a74a43SLisandro Dalcincopyright = f'{_today.year}, {author}'
595808f684SSatish Balay
6055a74a43SLisandro Dalcinrelease = pkg_version()
6155a74a43SLisandro Dalcinversion = release.rsplit('.', 1)[0]
625808f684SSatish Balay
635808f684SSatish Balay
6455a74a43SLisandro Dalcin# -- General configuration ---------------------------------------------------
6555a74a43SLisandro Dalcin# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
665808f684SSatish Balay
6755a74a43SLisandro Dalcinextensions = [
6855a74a43SLisandro Dalcin    'sphinx.ext.autodoc',
6955a74a43SLisandro Dalcin    'sphinx.ext.autosummary',
7055a74a43SLisandro Dalcin    'sphinx.ext.intersphinx',
7155a74a43SLisandro Dalcin    'sphinx.ext.napoleon',
72b3f8c7a1SStefano Zampini    'sphinx.ext.extlinks',
7355a74a43SLisandro Dalcin]
745808f684SSatish Balay
7555a74a43SLisandro Dalcintemplates_path = ['_templates']
765808f684SSatish Balayexclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
775808f684SSatish Balay
7855a74a43SLisandro Dalcinneeds_sphinx = '5.0.0'
795808f684SSatish Balay
8055a74a43SLisandro Dalcindefault_role = 'any'
8155a74a43SLisandro Dalcin
8255a74a43SLisandro Dalcinpygments_style = 'tango'
8355a74a43SLisandro Dalcin
8455a74a43SLisandro Dalcinnitpicky = True
8555a74a43SLisandro Dalcinnitpick_ignore = [
8655a74a43SLisandro Dalcin    ('envvar', 'NUMPY_INCLUDE'),
8755a74a43SLisandro Dalcin    ('py:class', 'ndarray'),  # FIXME
8855a74a43SLisandro Dalcin    ('py:class', 'typing_extensions.Self'),
8955a74a43SLisandro Dalcin]
9055a74a43SLisandro Dalcinnitpick_ignore_regex = [
9155a74a43SLisandro Dalcin    (r'c:.*', r'MPI_.*'),
9255a74a43SLisandro Dalcin    (r'c:.*', r'Petsc.*'),
9355a74a43SLisandro Dalcin    (r'envvar', r'(LD_LIBRARY_)?PATH'),
9455a74a43SLisandro Dalcin    (r'envvar', r'(MPICH|OMPI|MPIEXEC)_.*'),
9555a74a43SLisandro Dalcin]
9655a74a43SLisandro Dalcin
9755a74a43SLisandro Dalcintoc_object_entries = False
9855a74a43SLisandro Dalcintoc_object_entries_show_parents = 'hide'
9955a74a43SLisandro Dalcin# python_use_unqualified_type_names = True
10055a74a43SLisandro Dalcin
10155a74a43SLisandro Dalcinautodoc_class_signature = 'separated'
10255a74a43SLisandro Dalcinautodoc_typehints = 'description'
10355a74a43SLisandro Dalcinautodoc_typehints_format = 'short'
10455a74a43SLisandro Dalcinautodoc_mock_imports = []
10555a74a43SLisandro Dalcinautodoc_type_aliases = {}
10655a74a43SLisandro Dalcin
10755a74a43SLisandro Dalcinautosummary_context = {
10855a74a43SLisandro Dalcin    'synopsis': {},
10955a74a43SLisandro Dalcin    'autotype': {},
11055a74a43SLisandro Dalcin}
1115808f684SSatish Balay
112b3f8c7a1SStefano Zampini# This can be customized
113b3f8c7a1SStefano Zampiniwww = 'https://gitlab.com/petsc/petsc/-/tree/main'
114b3f8c7a1SStefano Zampiniextlinks = {'sources': (f'{www}/src/binding/petsc4py/src/%s','')}
1155808f684SSatish Balay
116*d919c72dSLisandro Dalcinnapoleon_preprocess_types = True
117*d919c72dSLisandro Dalcin
118*d919c72dSLisandro Dalcintry:
119*d919c72dSLisandro Dalcin    import sphinx_rtd_theme
120*d919c72dSLisandro Dalcin    if 'sphinx_rtd_theme' not in extensions:
121*d919c72dSLisandro Dalcin        extensions.append('sphinx_rtd_theme')
122*d919c72dSLisandro Dalcinexcept ImportError:
123*d919c72dSLisandro Dalcin    sphinx_rtd_theme = None
124*d919c72dSLisandro Dalcin
125*d919c72dSLisandro Dalcinintersphinx_mapping = {
126*d919c72dSLisandro Dalcin    'python': ('https://docs.python.org/3/', None),
127*d919c72dSLisandro Dalcin    'numpy': ('https://numpy.org/doc/stable/', None),
128*d919c72dSLisandro Dalcin    'numpydoc': ('https://numpydoc.readthedocs.io/en/latest/', None),
129*d919c72dSLisandro Dalcin    'mpi4py': ('https://mpi4py.readthedocs.io/en/stable/', None),
130*d919c72dSLisandro Dalcin    'pyopencl': ('https://documen.tician.de/pyopencl/', None),
131*d919c72dSLisandro Dalcin    'dlpack': ('https://dmlc.github.io/dlpack/latest/', None),
132*d919c72dSLisandro Dalcin    'petsc': ('https://petsc.org/release/', None),
133*d919c72dSLisandro Dalcin}
134*d919c72dSLisandro Dalcin
13555a74a43SLisandro Dalcindef _mangle_petsc_intersphinx():
13655a74a43SLisandro Dalcin    """Preprocess the keys in PETSc's intersphinx inventory.
13755a74a43SLisandro Dalcin
13855a74a43SLisandro Dalcin    PETSc have intersphinx keys of the form:
13955a74a43SLisandro Dalcin
14055a74a43SLisandro Dalcin        manualpages/Vec/VecShift
14155a74a43SLisandro Dalcin
14255a74a43SLisandro Dalcin    instead of:
14355a74a43SLisandro Dalcin
14455a74a43SLisandro Dalcin        petsc.VecShift
14555a74a43SLisandro Dalcin
14655a74a43SLisandro Dalcin    This function downloads their object inventory and strips the leading path
14755a74a43SLisandro Dalcin    elements so that references to PETSc names actually resolve."""
148*d919c72dSLisandro Dalcin    website = intersphinx_mapping['petsc'][0].partition('/release/')[0]
149*d919c72dSLisandro Dalcin    branch = get_doc_branch()
150*d919c72dSLisandro Dalcin    base_doc_url = f"{website}/{branch}/"
15155a74a43SLisandro Dalcin
152*d919c72dSLisandro Dalcin    running_on_ci = False  # os.environ.get("CI", "false") == "true"
153*d919c72dSLisandro Dalcin    if running_on_ci:
154*d919c72dSLisandro Dalcin        local_petsc_docs = "path/to/petsc/documentation" # TODO
155*d919c72dSLisandro Dalcin        local_inventory_filename = os.path.join(local_petsc_docs, "objects.inv")
156*d919c72dSLisandro Dalcin        inventory = sphobjinv.Inventory(local_inventory_filename)
157*d919c72dSLisandro Dalcin    else:
158*d919c72dSLisandro Dalcin        inventory = sphobjinv.Inventory(url=f"{base_doc_url}objects.inv")
159*d919c72dSLisandro Dalcin
160*d919c72dSLisandro Dalcin    for obj in inventory.objects:
16155a74a43SLisandro Dalcin        if obj.name.startswith("manualpages"):
16255a74a43SLisandro Dalcin            obj.name = "petsc." + "/".join(obj.name.split("/")[2:])
16355a74a43SLisandro Dalcin            obj.role = "class"
16455a74a43SLisandro Dalcin            obj.domain = "py"
16555a74a43SLisandro Dalcin
166*d919c72dSLisandro Dalcin    new_inventory_filename = "petsc_objects.inv"
167*d919c72dSLisandro Dalcin    sphobjinv.writebytes(
168*d919c72dSLisandro Dalcin        new_inventory_filename,
169*d919c72dSLisandro Dalcin        sphobjinv.compress(inventory.data_file(contract=True))
170*d919c72dSLisandro Dalcin    )
171*d919c72dSLisandro Dalcin    intersphinx_mapping['petsc'] = (base_doc_url, new_inventory_filename)
17255a74a43SLisandro Dalcin
17355a74a43SLisandro Dalcin
17455a74a43SLisandro Dalcin_mangle_petsc_intersphinx()
17555a74a43SLisandro Dalcin
17655a74a43SLisandro Dalcin
17755a74a43SLisandro Dalcindef _setup_mpi4py_typing():
17855a74a43SLisandro Dalcin    pkg = type(sys)('mpi4py')
17955a74a43SLisandro Dalcin    mod = type(sys)('mpi4py.MPI')
18055a74a43SLisandro Dalcin    mod.__package__ = pkg.__name__
18155a74a43SLisandro Dalcin    sys.modules[pkg.__name__] = pkg
18255a74a43SLisandro Dalcin    sys.modules[mod.__name__] = mod
18355a74a43SLisandro Dalcin    for clsname in (
18455a74a43SLisandro Dalcin        'Intracomm',
18555a74a43SLisandro Dalcin        'Datatype',
18655a74a43SLisandro Dalcin        'Op',
18755a74a43SLisandro Dalcin    ):
18855a74a43SLisandro Dalcin        cls = type(clsname, (), {})
18955a74a43SLisandro Dalcin        cls.__module__ = mod.__name__
19055a74a43SLisandro Dalcin        setattr(mod, clsname, cls)
19155a74a43SLisandro Dalcin
19255a74a43SLisandro Dalcin
19355a74a43SLisandro Dalcindef _patch_domain_python():
19455a74a43SLisandro Dalcin    from sphinx.domains.python import PythonDomain
19555a74a43SLisandro Dalcin    PythonDomain.object_types['data'].roles += ('class',)
19655a74a43SLisandro Dalcin
19755a74a43SLisandro Dalcin
19855a74a43SLisandro Dalcindef _setup_autodoc(app):
19955a74a43SLisandro Dalcin    from sphinx.ext import autodoc
20055a74a43SLisandro Dalcin    from sphinx.util import inspect
20155a74a43SLisandro Dalcin    from sphinx.util import typing
20255a74a43SLisandro Dalcin
20355a74a43SLisandro Dalcin    #
20455a74a43SLisandro Dalcin
20555a74a43SLisandro Dalcin    def stringify_annotation(annotation, mode='fully-qualified-except-typing'):
20655a74a43SLisandro Dalcin        qualname = getattr(annotation, '__qualname__', '')
20755a74a43SLisandro Dalcin        module = getattr(annotation, '__module__', '')
20855a74a43SLisandro Dalcin        args = getattr(annotation, '__args__', None)
20955a74a43SLisandro Dalcin        if module == 'builtins' and qualname and args is not None:
21055a74a43SLisandro Dalcin            args = ', '.join(stringify_annotation(a, mode) for a in args)
21155a74a43SLisandro Dalcin            return f'{qualname}[{args}]'
21255a74a43SLisandro Dalcin        return stringify_annotation_orig(annotation, mode)
21355a74a43SLisandro Dalcin
21455a74a43SLisandro Dalcin    try:
21555a74a43SLisandro Dalcin        stringify_annotation_orig = typing.stringify_annotation
21655a74a43SLisandro Dalcin        inspect.stringify_annotation = stringify_annotation
21755a74a43SLisandro Dalcin        typing.stringify_annotation = stringify_annotation
21855a74a43SLisandro Dalcin        autodoc.stringify_annotation = stringify_annotation
21955a74a43SLisandro Dalcin        autodoc.typehints.stringify_annotation = stringify_annotation
22055a74a43SLisandro Dalcin    except AttributeError:
22155a74a43SLisandro Dalcin        stringify_annotation_orig = typing.stringify
22255a74a43SLisandro Dalcin        inspect.stringify_annotation = stringify_annotation
22355a74a43SLisandro Dalcin        typing.stringify = stringify_annotation
22455a74a43SLisandro Dalcin        autodoc.stringify_typehint = stringify_annotation
22555a74a43SLisandro Dalcin
22655a74a43SLisandro Dalcin    #
22755a74a43SLisandro Dalcin
22855a74a43SLisandro Dalcin    class ClassDocumenterMixin:
22955a74a43SLisandro Dalcin
23055a74a43SLisandro Dalcin        def __init__(self, *args, **kwargs):
23155a74a43SLisandro Dalcin            super().__init__(*args, **kwargs)
23255a74a43SLisandro Dalcin            if self.config.autodoc_class_signature == 'separated':
23355a74a43SLisandro Dalcin                members = self.options.members
23455a74a43SLisandro Dalcin                special_members = self.options.special_members
23555a74a43SLisandro Dalcin                if special_members is not None:
23655a74a43SLisandro Dalcin                    for name in ('__new__', '__init__'):
23755a74a43SLisandro Dalcin                        if name in members:
23855a74a43SLisandro Dalcin                            members.remove(name)
23955a74a43SLisandro Dalcin                        if name in special_members:
24055a74a43SLisandro Dalcin                            special_members.remove(name)
24155a74a43SLisandro Dalcin
24255a74a43SLisandro Dalcin    class ClassDocumenter(
24355a74a43SLisandro Dalcin        ClassDocumenterMixin,
24455a74a43SLisandro Dalcin        autodoc.ClassDocumenter,
24555a74a43SLisandro Dalcin    ):
24655a74a43SLisandro Dalcin        pass
24755a74a43SLisandro Dalcin
24855a74a43SLisandro Dalcin    class ExceptionDocumenter(
24955a74a43SLisandro Dalcin        ClassDocumenterMixin,
25055a74a43SLisandro Dalcin        autodoc.ExceptionDocumenter,
25155a74a43SLisandro Dalcin    ):
25255a74a43SLisandro Dalcin        pass
25355a74a43SLisandro Dalcin
25455a74a43SLisandro Dalcin    app.add_autodocumenter(ClassDocumenter, override=True)
25555a74a43SLisandro Dalcin    app.add_autodocumenter(ExceptionDocumenter, override=True)
25655a74a43SLisandro Dalcin
25755a74a43SLisandro Dalcin
25855a74a43SLisandro Dalcindef _monkey_patch_returns():
25955a74a43SLisandro Dalcin    """Rewrite the role of names in "Returns" sections.
26055a74a43SLisandro Dalcin
26155a74a43SLisandro Dalcin    This is needed because Napoleon uses ``:class:`` for the return types
26255a74a43SLisandro Dalcin    and this does not work with type aliases like ``ArrayScalar``. To resolve
26355a74a43SLisandro Dalcin    this we swap ``:class:`` for ``:any:``.
26455a74a43SLisandro Dalcin
26555a74a43SLisandro Dalcin    """
26655a74a43SLisandro Dalcin    _parse_returns_section = \
26755a74a43SLisandro Dalcin        NumpyDocstring._parse_returns_section
26855a74a43SLisandro Dalcin
26955a74a43SLisandro Dalcin    @functools.wraps(NumpyDocstring._parse_returns_section)
27055a74a43SLisandro Dalcin    def wrapper(*args, **kwargs):
27155a74a43SLisandro Dalcin        out = _parse_returns_section(*args, **kwargs)
27255a74a43SLisandro Dalcin        return [line.replace(":class:", ":any:") for line in out]
27355a74a43SLisandro Dalcin
27455a74a43SLisandro Dalcin    NumpyDocstring._parse_returns_section = wrapper
27555a74a43SLisandro Dalcin
27655a74a43SLisandro Dalcin
27755a74a43SLisandro Dalcindef _monkey_patch_see_also():
27855a74a43SLisandro Dalcin    """Rewrite the role of names in "see also" sections.
27955a74a43SLisandro Dalcin
28055a74a43SLisandro Dalcin    Napoleon uses :obj: for all names found in "see also" sections but we
28155a74a43SLisandro Dalcin    need :all: so that references to labels work."""
28255a74a43SLisandro Dalcin
28355a74a43SLisandro Dalcin    _parse_numpydoc_see_also_section = \
28455a74a43SLisandro Dalcin        NumpyDocstring._parse_numpydoc_see_also_section
28555a74a43SLisandro Dalcin
28655a74a43SLisandro Dalcin    @functools.wraps(NumpyDocstring._parse_numpydoc_see_also_section)
28755a74a43SLisandro Dalcin    def wrapper(*args, **kwargs):
28855a74a43SLisandro Dalcin        out = _parse_numpydoc_see_also_section(*args, **kwargs)
28955a74a43SLisandro Dalcin        return [line.replace(":obj:", ":any:") for line in out]
29055a74a43SLisandro Dalcin
29155a74a43SLisandro Dalcin    NumpyDocstring._parse_numpydoc_see_also_section = wrapper
29255a74a43SLisandro Dalcin
29355a74a43SLisandro Dalcin
29455a74a43SLisandro Dalcindef _apply_monkey_patches():
29555a74a43SLisandro Dalcin    """Modify Napoleon types after parsing to make references work."""
29655a74a43SLisandro Dalcin    _monkey_patch_returns()
29755a74a43SLisandro Dalcin    _monkey_patch_see_also()
29855a74a43SLisandro Dalcin
29955a74a43SLisandro Dalcin
30055a74a43SLisandro Dalcin_apply_monkey_patches()
30155a74a43SLisandro Dalcin
30255a74a43SLisandro Dalcin
30355a74a43SLisandro Dalcindef _process_demos(*demos):
30455a74a43SLisandro Dalcin    # Convert demo .py files to rst. Also copy the .py file so it can be
30555a74a43SLisandro Dalcin    # linked from the demo rst file.
30655a74a43SLisandro Dalcin    try:
30755a74a43SLisandro Dalcin        os.mkdir("demo")
30855a74a43SLisandro Dalcin    except FileExistsError:
30955a74a43SLisandro Dalcin        pass
31055a74a43SLisandro Dalcin    for demo in demos:
31155a74a43SLisandro Dalcin        demo_dir = os.path.join("demo", os.path.dirname(demo))
31255a74a43SLisandro Dalcin        demo_src = os.path.join(os.pardir, os.pardir, "demo", demo)
31355a74a43SLisandro Dalcin        try:
31455a74a43SLisandro Dalcin            os.mkdir(demo_dir)
31555a74a43SLisandro Dalcin        except FileExistsError:
31655a74a43SLisandro Dalcin            pass
31755a74a43SLisandro Dalcin        with open(demo_src, "r") as infile:
31855a74a43SLisandro Dalcin            with open(os.path.join(
31955a74a43SLisandro Dalcin                os.path.join("demo", os.path.splitext(demo)[0] + ".rst")), "w"
32055a74a43SLisandro Dalcin            ) as outfile:
32155a74a43SLisandro Dalcin                converter = pylit.Code2Text(infile)
32255a74a43SLisandro Dalcin                outfile.write(str(converter))
32355a74a43SLisandro Dalcin        demo_copy_name = os.path.join(demo_dir, os.path.basename(demo))
32455a74a43SLisandro Dalcin        shutil.copyfile(demo_src, demo_copy_name)
32555a74a43SLisandro Dalcin        html_static_path.append(demo_copy_name)
32655a74a43SLisandro Dalcin    with open(os.path.join("demo", "demo.rst"), "w") as demofile:
32755a74a43SLisandro Dalcin        demofile.write("""
32855a74a43SLisandro Dalcinpetsc4py demos
32955a74a43SLisandro Dalcin==============
33055a74a43SLisandro Dalcin
33155a74a43SLisandro Dalcin.. toctree::
33255a74a43SLisandro Dalcin
33355a74a43SLisandro Dalcin""")
33455a74a43SLisandro Dalcin        for demo in demos:
33555a74a43SLisandro Dalcin            demofile.write("    " + os.path.splitext(demo)[0] + "\n")
33655a74a43SLisandro Dalcin        demofile.write("\n")
33755a74a43SLisandro Dalcin
33855a74a43SLisandro Dalcinhtml_static_path=[]
33955a74a43SLisandro Dalcin_process_demos(
34055a74a43SLisandro Dalcin    "poisson2d/poisson2d.py"
34155a74a43SLisandro Dalcin)
34255a74a43SLisandro Dalcin
34355a74a43SLisandro Dalcin
34455a74a43SLisandro Dalcindef setup(app):
34555a74a43SLisandro Dalcin    _setup_mpi4py_typing()
34655a74a43SLisandro Dalcin    _patch_domain_python()
34755a74a43SLisandro Dalcin    _monkey_patch_returns()
34855a74a43SLisandro Dalcin    _monkey_patch_see_also()
34955a74a43SLisandro Dalcin    _setup_autodoc(app)
35055a74a43SLisandro Dalcin
35155a74a43SLisandro Dalcin    try:
35255a74a43SLisandro Dalcin        from petsc4py import PETSc
35355a74a43SLisandro Dalcin    except ImportError:
35455a74a43SLisandro Dalcin        autodoc_mock_imports.append('PETSc')
35555a74a43SLisandro Dalcin        return
35655a74a43SLisandro Dalcin    del PETSc.DA  # FIXME
35755a74a43SLisandro Dalcin
35855a74a43SLisandro Dalcin    sys_dwb = sys.dont_write_bytecode
35955a74a43SLisandro Dalcin    sys.dont_write_bytecode = True
36055a74a43SLisandro Dalcin    import apidoc
36155a74a43SLisandro Dalcin    sys.dont_write_bytecode = sys_dwb
36255a74a43SLisandro Dalcin
36355a74a43SLisandro Dalcin    name = PETSc.__name__
36455a74a43SLisandro Dalcin    here = os.path.abspath(os.path.dirname(__file__))
36555a74a43SLisandro Dalcin    outdir = os.path.join(here, apidoc.OUTDIR)
36655a74a43SLisandro Dalcin    source = os.path.join(outdir, f'{name}.py')
36755a74a43SLisandro Dalcin    getmtime = os.path.getmtime
36855a74a43SLisandro Dalcin    generate = (
36955a74a43SLisandro Dalcin        not os.path.exists(source)
37055a74a43SLisandro Dalcin        or getmtime(source) < getmtime(PETSc.__file__)
37155a74a43SLisandro Dalcin        or getmtime(source) < getmtime(apidoc.__file__)
37255a74a43SLisandro Dalcin    )
37355a74a43SLisandro Dalcin    if generate:
37455a74a43SLisandro Dalcin        apidoc.generate(source)
37555a74a43SLisandro Dalcin    module = apidoc.load_module(source)
37655a74a43SLisandro Dalcin    apidoc.replace_module(module)
37755a74a43SLisandro Dalcin
37855a74a43SLisandro Dalcin    modules = [
37955a74a43SLisandro Dalcin        'petsc4py',
38055a74a43SLisandro Dalcin    ]
38155a74a43SLisandro Dalcin    typing_overload = typing.overload
38255a74a43SLisandro Dalcin    typing.overload = lambda arg: arg
38355a74a43SLisandro Dalcin    for name in modules:
38455a74a43SLisandro Dalcin        mod = importlib.import_module(name)
38555a74a43SLisandro Dalcin        ann = apidoc.load_module(f'{mod.__file__}i', name)
38655a74a43SLisandro Dalcin        apidoc.annotate(mod, ann)
38755a74a43SLisandro Dalcin    typing.overload = typing_overload
38855a74a43SLisandro Dalcin
38955a74a43SLisandro Dalcin    from petsc4py import typing as tp
39055a74a43SLisandro Dalcin    for attr in tp.__all__:
39155a74a43SLisandro Dalcin        autodoc_type_aliases[attr] = f'~petsc4py.typing.{attr}'
39255a74a43SLisandro Dalcin
39355a74a43SLisandro Dalcin# -- Options for HTML output -------------------------------------------------
39455a74a43SLisandro Dalcin# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
3955808f684SSatish Balay
3965808f684SSatish Balay# The theme to use for HTML and HTML Help pages.  See the documentation for
3975808f684SSatish Balay# a list of builtin themes.
39855a74a43SLisandro Dalcinhtml_theme = 'pydata_sphinx_theme'
3995808f684SSatish Balay
4005808f684SSatish Balay# -- Options for HTMLHelp output ------------------------------------------
4015808f684SSatish Balay
4025808f684SSatish Balay# Output file base name for HTML help builder.
40355a74a43SLisandro Dalcinhtmlhelp_basename = f'{package}-man'
4045808f684SSatish Balay
4055808f684SSatish Balay
4065808f684SSatish Balay# -- Options for LaTeX output ---------------------------------------------
4075808f684SSatish Balay
4085808f684SSatish Balay# (source start file, target name, title,
4095808f684SSatish Balay#  author, documentclass [howto, manual, or own class]).
4105808f684SSatish Balaylatex_documents = [
41155a74a43SLisandro Dalcin    ('index', f'{package}.tex', project, author, 'howto'),
4125808f684SSatish Balay]
4135808f684SSatish Balay
41455a74a43SLisandro Dalcinlatex_elements = {
41555a74a43SLisandro Dalcin    'papersize': 'a4',
41655a74a43SLisandro Dalcin}
41755a74a43SLisandro Dalcin
4185808f684SSatish Balay
4195808f684SSatish Balay# -- Options for manual page output ---------------------------------------
4205808f684SSatish Balay
4215808f684SSatish Balay# (source start file, name, description, authors, manual section).
4225808f684SSatish Balayman_pages = [
42355a74a43SLisandro Dalcin    ('index', package, project, [author], 3)
4245808f684SSatish Balay]
4255808f684SSatish Balay
4265808f684SSatish Balay
4275808f684SSatish Balay# -- Options for Texinfo output -------------------------------------------
4285808f684SSatish Balay
4295808f684SSatish Balay# (source start file, target name, title, author,
4305808f684SSatish Balay#  dir menu entry, description, category)
4315808f684SSatish Balaytexinfo_documents = [
43255a74a43SLisandro Dalcin    ('index', package, project, author,
43355a74a43SLisandro Dalcin     package, f'{project}.', 'Miscellaneous'),
4345808f684SSatish Balay]
4355808f684SSatish Balay
43655a74a43SLisandro Dalcin
4375808f684SSatish Balay# -- Options for Epub output ----------------------------------------------
4385808f684SSatish Balay
43955a74a43SLisandro Dalcin# Output file base name for ePub builder.
44055a74a43SLisandro Dalcinepub_basename = package
441