mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
357 lines
12 KiB
Python
357 lines
12 KiB
Python
# Sphinx documentation build configuration file
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import re
|
|
from typing import TYPE_CHECKING
|
|
|
|
from sphinx import __display_version__
|
|
|
|
os.environ['SPHINX_AUTODOC_RELOAD_MODULES'] = '1'
|
|
|
|
extensions = [
|
|
'sphinx.ext.autodoc',
|
|
'sphinx.ext.doctest',
|
|
'sphinx.ext.todo',
|
|
'sphinx.ext.autosummary',
|
|
'sphinx.ext.extlinks',
|
|
'sphinx.ext.intersphinx',
|
|
'sphinx.ext.viewcode',
|
|
'sphinx.ext.inheritance_diagram',
|
|
'sphinx.ext.coverage',
|
|
'sphinx.ext.graphviz',
|
|
]
|
|
coverage_statistics_to_report = coverage_statistics_to_stdout = True
|
|
templates_path = ['_templates']
|
|
exclude_patterns = ['_build']
|
|
|
|
project = 'Sphinx'
|
|
copyright = '2007-%Y, the Sphinx developers'
|
|
release = version = __display_version__
|
|
show_authors = True
|
|
nitpicky = True
|
|
show_warning_types = True
|
|
|
|
html_theme = 'sphinx13'
|
|
html_theme_path = ['_themes']
|
|
html_css_files = [
|
|
# 'basic.css', # included through inheritance from the basic theme
|
|
'sphinx13.css',
|
|
]
|
|
modindex_common_prefix = ['sphinx.']
|
|
html_static_path = ['_static']
|
|
html_title = 'Sphinx documentation'
|
|
html_additional_pages = {'contents': 'contents.html'}
|
|
html_use_opensearch = 'https://www.sphinx-doc.org/en/master'
|
|
html_baseurl = 'https://www.sphinx-doc.org/en/master/'
|
|
html_favicon = '_static/favicon.svg'
|
|
|
|
htmlhelp_basename = 'Sphinxdoc'
|
|
|
|
epub_theme = 'epub'
|
|
epub_basename = 'sphinx'
|
|
epub_author = 'the Sphinx developers'
|
|
epub_publisher = 'https://www.sphinx-doc.org/'
|
|
epub_uid = 'web-site'
|
|
epub_scheme = 'url'
|
|
epub_identifier = epub_publisher
|
|
epub_pre_files = [('index.xhtml', 'Welcome')]
|
|
epub_post_files = [
|
|
('usage/installation.xhtml', 'Installing Sphinx'),
|
|
('develop.xhtml', 'Sphinx development'),
|
|
]
|
|
epub_exclude_files = [
|
|
'_static/opensearch.xml',
|
|
'_static/doctools.js',
|
|
'_static/searchtools.js',
|
|
'_static/sphinx_highlight.js',
|
|
'_static/basic.css',
|
|
'_static/language_data.js',
|
|
'search.html',
|
|
'_static/websupport.js',
|
|
]
|
|
epub_fix_images = False
|
|
epub_max_image_width = 0
|
|
epub_show_urls = 'inline'
|
|
epub_use_index = False
|
|
epub_description = 'Sphinx documentation generator system manual'
|
|
|
|
latex_documents = [
|
|
(
|
|
'index',
|
|
'sphinx.tex',
|
|
'Sphinx Documentation',
|
|
'the Sphinx developers',
|
|
'manual',
|
|
1,
|
|
)
|
|
]
|
|
latex_logo = '_static/sphinx.png'
|
|
latex_elements = {
|
|
'fontenc': r'\usepackage[LGR,X2,T1]{fontenc}',
|
|
'passoptionstopackages': r"""
|
|
\PassOptionsToPackage{svgnames}{xcolor}
|
|
""",
|
|
'preamble': r"""
|
|
\DeclareUnicodeCharacter{229E}{\ensuremath{\boxplus}}
|
|
\setcounter{tocdepth}{3}% depth of what main TOC shows (3=subsubsection)
|
|
\setcounter{secnumdepth}{1}% depth of section numbering
|
|
\setlength{\tymin}{2cm}% avoid too cramped table columns
|
|
""",
|
|
# fix missing index entry due to RTD doing only once pdflatex after makeindex
|
|
'printindex': r"""
|
|
\IfFileExists{\jobname.ind}
|
|
{\footnotesize\raggedright\printindex}
|
|
{\begin{sphinxtheindex}\end{sphinxtheindex}}
|
|
""",
|
|
}
|
|
latex_show_urls = 'footnote'
|
|
latex_use_xindy = True
|
|
|
|
linkcheck_timeout = 5
|
|
linkcheck_ignore = [
|
|
r'^contents\.html$', # extra generated page
|
|
r'^\.\./contents\.html$',
|
|
re.escape('https://gitlab.com/projects/new'), # requires sign-in
|
|
re.escape('https://web.libera.chat/?channel=#sphinx-doc'),
|
|
]
|
|
linkcheck_anchors_ignore_for_url = [
|
|
# anchors in Markdown files cannot be accessed directly
|
|
'https://github.com/Khan/style-guides/blob/master/style/python.md',
|
|
]
|
|
|
|
autodoc_member_order = 'groupwise'
|
|
autosummary_generate = False
|
|
todo_include_todos = 'READTHEDOCS' not in os.environ
|
|
extlinks = {
|
|
'dupage': ('https://docutils.sourceforge.io/docs/ref/rst/%s.html', '%s'),
|
|
'duref': (
|
|
'https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#%s',
|
|
'%s',
|
|
),
|
|
'durole': ('https://docutils.sourceforge.io/docs/ref/rst/roles.html#%s', '%s'),
|
|
'dudir': ('https://docutils.sourceforge.io/docs/ref/rst/directives.html#%s', '%s'),
|
|
}
|
|
|
|
man_pages = [
|
|
(
|
|
'index',
|
|
'sphinx-all',
|
|
'Sphinx documentation generator system manual',
|
|
'the Sphinx developers',
|
|
1,
|
|
),
|
|
('man/sphinx-build', 'sphinx-build', 'Sphinx documentation generator tool', '', 1),
|
|
(
|
|
'man/sphinx-quickstart',
|
|
'sphinx-quickstart',
|
|
'Sphinx documentation template generator',
|
|
'',
|
|
1,
|
|
),
|
|
('man/sphinx-apidoc', 'sphinx-apidoc', 'Sphinx API doc generator tool', '', 1),
|
|
('man/sphinx-autogen', 'sphinx-autogen', 'Generate autodoc stub pages', '', 1),
|
|
]
|
|
|
|
texinfo_documents = [
|
|
(
|
|
'index',
|
|
'sphinx',
|
|
'Sphinx Documentation',
|
|
'the Sphinx developers',
|
|
'Sphinx',
|
|
'The Sphinx documentation builder.',
|
|
'Documentation tools',
|
|
True,
|
|
),
|
|
]
|
|
|
|
intersphinx_mapping = {
|
|
'python': ('https://docs.python.org/3/', None),
|
|
'requests': ('https://requests.readthedocs.io/en/latest/', None),
|
|
'readthedocs': ('https://docs.readthedocs.io/en/stable', None),
|
|
}
|
|
|
|
# Sphinx document translation with sphinx gettext feature uses these settings:
|
|
gettext_compact = False
|
|
|
|
nitpick_ignore = {
|
|
(
|
|
'cpp:class',
|
|
'template<typename TOuter> template<typename TInner> Wrapper::Outer<TOuter>::Inner',
|
|
),
|
|
('cpp:identifier', 'MyContainer'),
|
|
('js:func', 'SomeError'),
|
|
('js:func', 'number'),
|
|
('js:func', 'string'),
|
|
('py:attr', 'srcline'),
|
|
('py:class', '_AutodocProcessDocstringListener'),
|
|
('py:class', '_ConfigRebuild'), # sphinx.application.Sphinx.add_config_value
|
|
('py:class', '_StrPath'), # sphinx.environment.BuildEnvironment.doc2path
|
|
('py:class', 'Element'), # sphinx.domains.Domain
|
|
('py:class', 'Documenter'), # sphinx.application.Sphinx.add_autodocumenter
|
|
('py:class', 'IndexEntry'), # sphinx.domains.IndexEntry
|
|
('py:class', 'Lexer'), # sphinx.application.Sphinx.add_lexer
|
|
('py:class', 'Node'), # sphinx.domains.Domain
|
|
('py:class', 'NullTranslations'), # gettext.NullTranslations
|
|
('py:class', 'Path'), # sphinx.application.Sphinx.connect
|
|
('py:class', 'RoleFunction'), # sphinx.domains.Domain
|
|
('py:class', 'RSTState'), # sphinx.utils.parsing.nested_parse_to_nodes
|
|
('py:class', 'Theme'), # sphinx.application.TemplateBridge
|
|
('py:class', 'SearchLanguage'), # sphinx.application.Sphinx.add_search_language
|
|
('py:class', 'StringList'), # sphinx.utils.parsing.nested_parse_to_nodes
|
|
('py:class', 'system_message'), # sphinx.utils.docutils.SphinxDirective
|
|
('py:class', 'TitleGetter'), # sphinx.domains.Domain
|
|
('py:class', 'todo_node'), # sphinx.application.Sphinx.connect
|
|
('py:class', 'Transform'), # sphinx.application.Sphinx.add_transform
|
|
('py:class', 'XRefRole'), # sphinx.domains.Domain
|
|
('py:class', 'docutils.nodes.Element'),
|
|
('py:class', 'docutils.nodes.Node'),
|
|
('py:class', 'docutils.nodes.NodeVisitor'),
|
|
('py:class', 'docutils.nodes.TextElement'),
|
|
('py:class', 'docutils.nodes.document'),
|
|
('py:class', 'docutils.nodes.system_message'),
|
|
('py:class', 'docutils.parsers.Parser'),
|
|
('py:class', 'docutils.parsers.rst.states.Inliner'),
|
|
('py:class', 'docutils.transforms.Transform'),
|
|
('py:class', 'nodes.NodeVisitor'),
|
|
('py:class', 'nodes.TextElement'), # sphinx.application.Sphinx.connect
|
|
('py:class', 'nodes.document'),
|
|
('py:class', 'nodes.reference'),
|
|
('py:class', 'pygments.lexer.Lexer'),
|
|
('py:class', 'sphinx.directives.ObjDescT'),
|
|
('py:class', 'sphinx.domains.IndexEntry'),
|
|
('py:class', 'sphinx.ext.autodoc.Documenter'),
|
|
('py:class', 'sphinx.errors.NoUri'),
|
|
('py:class', 'sphinx.roles.XRefRole'),
|
|
('py:class', 'sphinx.search.SearchLanguage'),
|
|
('py:class', 'sphinx.theming.Theme'),
|
|
('py:class', 'sphinx.util._pathlib._StrPath'), # sphinx.project.Project.doc2path
|
|
('py:class', 'sphinxcontrib.websupport.errors.DocumentNotFoundError'),
|
|
('py:class', 'sphinxcontrib.websupport.errors.UserNotAuthorizedError'),
|
|
('py:exc', 'docutils.nodes.SkipNode'),
|
|
('py:exc', 'sphinx.environment.NoUri'),
|
|
('py:func', 'setup'),
|
|
('py:func', 'sphinx.util.nodes.nested_parse_with_titles'),
|
|
# Error in sphinxcontrib.websupport.core::WebSupport.add_comment
|
|
('py:meth', 'get_comments'),
|
|
('py:mod', 'autodoc'),
|
|
('py:mod', 'docutils.nodes'),
|
|
('py:mod', 'docutils.parsers.rst.directives'),
|
|
('py:mod', 'sphinx.ext'),
|
|
('py:obj', 'sphinx.util.relative_uri'),
|
|
('rst:role', 'c:any'),
|
|
('std:confval', 'autodoc_inherit_docstring'),
|
|
('std:confval', 'automodule_skip_lines'),
|
|
('std:confval', 'autossummary_imported_members'),
|
|
('std:confval', 'gettext_language_team'),
|
|
('std:confval', 'gettext_last_translator'),
|
|
('std:confval', 'globaltoc_collapse'),
|
|
('std:confval', 'globaltoc_includehidden'),
|
|
('std:confval', 'globaltoc_maxdepth'),
|
|
}
|
|
|
|
|
|
# -- Extension interface -------------------------------------------------------
|
|
|
|
from sphinx import addnodes # NoQA: E402
|
|
|
|
if TYPE_CHECKING:
|
|
from pathlib import Path
|
|
|
|
from docutils.nodes import Element
|
|
|
|
from sphinx.application import Sphinx
|
|
from sphinx.environment import BuildEnvironment
|
|
|
|
_event_sig_re = re.compile(r'([a-zA-Z-]+)\s*\((.*)\)')
|
|
|
|
|
|
def parse_event(_env: BuildEnvironment, sig: str, signode: Element) -> str:
|
|
m = _event_sig_re.match(sig)
|
|
if m is None:
|
|
signode += addnodes.desc_name(sig, sig)
|
|
return sig
|
|
name, args = m.groups()
|
|
signode += addnodes.desc_name(name, name)
|
|
plist = addnodes.desc_parameterlist()
|
|
for arg in args.split(','):
|
|
arg = arg.strip()
|
|
plist += addnodes.desc_parameter(arg, arg)
|
|
signode += plist
|
|
return name
|
|
|
|
|
|
def linkify_issues_in_changelog(
|
|
_app: Sphinx, _path: Path, docname: str, source: list[str]
|
|
) -> None:
|
|
"""Linkify issue references like #123 in changelog to GitHub."""
|
|
if docname == 'changes':
|
|
|
|
def linkify(match: re.Match[str]) -> str:
|
|
url = 'https://github.com/sphinx-doc/sphinx/issues/' + match[1]
|
|
return f'`{match[0]} <{url}>`_'
|
|
|
|
linkified_changelog = re.sub(r'(?:PR)?#([0-9]+)\b', linkify, source[0])
|
|
|
|
source[0] = linkified_changelog
|
|
|
|
|
|
REDIRECT_TEMPLATE = """
|
|
<html>
|
|
<head>
|
|
<noscript>
|
|
<meta http-equiv="refresh" content="0; url={{rel_url}}"/>
|
|
</noscript>
|
|
</head>
|
|
<body>
|
|
<script>
|
|
window.location.href = '{{rel_url}}' + (window.location.search || '') + (window.location.hash || '');
|
|
</script>
|
|
<p>You should have been redirected.</p>
|
|
<a href="{{rel_url}}">If not, click here to continue.</a>
|
|
</body>
|
|
</html>
|
|
""" # NoQA: E501
|
|
|
|
|
|
def build_redirects(app: Sphinx, exception: Exception | None) -> None:
|
|
# this is a very simple implementation of
|
|
# https://github.com/wpilibsuite/sphinxext-rediraffe/blob/main/sphinxext/rediraffe.py
|
|
# to re-direct some old pages to new ones
|
|
if exception is not None or app.builder.name != 'html':
|
|
return
|
|
for page, rel_redirect in (
|
|
(('changes.html',), 'changes/index.html'),
|
|
(('development', 'overview.html'), 'index.html'),
|
|
(('development', 'builders.html'), 'howtos/builders.html'),
|
|
(('development', 'theming.html'), 'html_themes/index.html'),
|
|
(('development', 'templating.html'), 'html_themes/templating.html'),
|
|
(('development', 'tutorials', 'helloworld.html'), 'extending_syntax.html'),
|
|
(('development', 'tutorials', 'todo.html'), 'extending_build.html'),
|
|
(('development', 'tutorials', 'recipe.html'), 'adding_domain.html'),
|
|
):
|
|
path = app.outdir.joinpath(*page)
|
|
if path.exists():
|
|
continue
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
with path.open('w', encoding='utf-8') as f:
|
|
f.write(REDIRECT_TEMPLATE.replace('{{rel_url}}', rel_redirect))
|
|
|
|
|
|
def setup(app: Sphinx) -> None:
|
|
from sphinx.util.docfields import GroupedField
|
|
|
|
app.connect('include-read', linkify_issues_in_changelog)
|
|
app.connect('build-finished', build_redirects)
|
|
fdesc = GroupedField(
|
|
'parameter', label='Parameters', names=('param',), can_collapse=True
|
|
)
|
|
app.add_object_type(
|
|
'event',
|
|
'event',
|
|
'pair: %s; event',
|
|
parse_event,
|
|
doc_field_types=[fdesc],
|
|
)
|