Sphinx 7.1.2__py3-none-any.whl → 7.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of Sphinx might be problematic. Click here for more details.
- sphinx/__init__.py +6 -6
- sphinx/__main__.py +3 -1
- sphinx/addnodes.py +35 -22
- sphinx/application.py +40 -38
- sphinx/builders/__init__.py +16 -12
- sphinx/builders/_epub_base.py +15 -11
- sphinx/builders/changes.py +6 -4
- sphinx/builders/dirhtml.py +4 -2
- sphinx/builders/dummy.py +6 -4
- sphinx/builders/epub3.py +16 -8
- sphinx/builders/gettext.py +40 -43
- sphinx/builders/html/__init__.py +166 -196
- sphinx/builders/html/_assets.py +116 -0
- sphinx/builders/html/transforms.py +4 -2
- sphinx/builders/latex/__init__.py +12 -7
- sphinx/builders/latex/theming.py +5 -2
- sphinx/builders/latex/transforms.py +6 -3
- sphinx/builders/linkcheck.py +18 -11
- sphinx/builders/manpage.py +6 -4
- sphinx/builders/singlehtml.py +16 -9
- sphinx/builders/texinfo.py +11 -6
- sphinx/builders/text.py +8 -3
- sphinx/builders/xml.py +9 -4
- sphinx/cmd/build.py +27 -14
- sphinx/cmd/make_mode.py +13 -4
- sphinx/cmd/quickstart.py +13 -4
- sphinx/config.py +17 -14
- sphinx/deprecation.py +4 -2
- sphinx/directives/__init__.py +44 -12
- sphinx/directives/code.py +5 -4
- sphinx/directives/other.py +92 -44
- sphinx/directives/patches.py +1 -1
- sphinx/domains/__init__.py +11 -8
- sphinx/domains/c.py +67 -57
- sphinx/domains/changeset.py +3 -2
- sphinx/domains/citation.py +2 -1
- sphinx/domains/cpp.py +136 -93
- sphinx/domains/index.py +9 -5
- sphinx/domains/javascript.py +32 -19
- sphinx/domains/math.py +5 -3
- sphinx/domains/python.py +69 -57
- sphinx/domains/rst.py +20 -11
- sphinx/domains/std.py +21 -15
- sphinx/environment/__init__.py +97 -65
- sphinx/environment/adapters/indexentries.py +13 -10
- sphinx/environment/adapters/toctree.py +485 -308
- sphinx/environment/collectors/__init__.py +3 -4
- sphinx/environment/collectors/asset.py +10 -4
- sphinx/environment/collectors/dependencies.py +7 -4
- sphinx/environment/collectors/metadata.py +7 -5
- sphinx/environment/collectors/title.py +5 -3
- sphinx/environment/collectors/toctree.py +13 -8
- sphinx/errors.py +1 -1
- sphinx/events.py +5 -5
- sphinx/ext/apidoc.py +49 -27
- sphinx/ext/autodoc/__init__.py +179 -161
- sphinx/ext/autodoc/directive.py +10 -6
- sphinx/ext/autodoc/importer.py +22 -13
- sphinx/ext/autodoc/mock.py +4 -1
- sphinx/ext/autodoc/preserve_defaults.py +80 -12
- sphinx/ext/autodoc/type_comment.py +14 -10
- sphinx/ext/autodoc/typehints.py +7 -3
- sphinx/ext/autosectionlabel.py +6 -3
- sphinx/ext/autosummary/__init__.py +21 -15
- sphinx/ext/autosummary/generate.py +176 -126
- sphinx/ext/coverage.py +93 -8
- sphinx/ext/doctest.py +28 -17
- sphinx/ext/duration.py +19 -17
- sphinx/ext/extlinks.py +11 -6
- sphinx/ext/githubpages.py +8 -7
- sphinx/ext/graphviz.py +61 -17
- sphinx/ext/ifconfig.py +7 -4
- sphinx/ext/imgconverter.py +4 -2
- sphinx/ext/imgmath.py +29 -23
- sphinx/ext/inheritance_diagram.py +41 -27
- sphinx/ext/intersphinx.py +45 -38
- sphinx/ext/linkcode.py +8 -5
- sphinx/ext/mathjax.py +13 -9
- sphinx/ext/napoleon/__init__.py +3 -3
- sphinx/ext/napoleon/docstring.py +40 -31
- sphinx/ext/todo.py +10 -7
- sphinx/ext/viewcode.py +46 -25
- sphinx/extension.py +1 -1
- sphinx/highlighting.py +20 -12
- sphinx/io.py +5 -4
- sphinx/jinja2glue.py +24 -19
- sphinx/locale/__init__.py +8 -2
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +756 -740
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +768 -752
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +758 -742
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +759 -743
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +760 -744
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +759 -743
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +763 -747
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +768 -752
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +767 -751
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +762 -746
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +766 -750
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr/LC_MESSAGES/sphinx.po +768 -752
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/gl/LC_MESSAGES/sphinx.js +60 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +3695 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +763 -747
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +760 -744
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +759 -743
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +765 -749
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +760 -744
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +760 -744
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +767 -751
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +759 -743
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +767 -751
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +760 -744
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +762 -745
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +768 -752
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +759 -743
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +760 -744
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +765 -749
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/sphinx.pot +748 -740
- sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sq/LC_MESSAGES/sphinx.po +768 -752
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/sr@latin/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr@latin/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/sr_RS/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr_RS/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +755 -739
- sphinx/locale/ta/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ta/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +763 -747
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +760 -749
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +759 -748
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/zh_CN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +768 -752
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +754 -738
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +767 -751
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +754 -738
- sphinx/parsers.py +5 -4
- sphinx/project.py +52 -34
- sphinx/pycode/__init__.py +2 -1
- sphinx/pycode/ast.py +7 -13
- sphinx/pycode/parser.py +42 -38
- sphinx/registry.py +35 -29
- sphinx/roles.py +9 -4
- sphinx/search/__init__.py +5 -17
- sphinx/search/da.py +1 -1
- sphinx/search/de.py +1 -1
- sphinx/search/en.py +1 -1
- sphinx/search/es.py +1 -1
- sphinx/search/fi.py +1 -1
- sphinx/search/fr.py +1 -1
- sphinx/search/hu.py +1 -1
- sphinx/search/it.py +1 -1
- sphinx/search/ja.py +1 -1
- sphinx/search/nl.py +1 -1
- sphinx/search/no.py +1 -1
- sphinx/search/pt.py +1 -1
- sphinx/search/ro.py +1 -1
- sphinx/search/ru.py +1 -1
- sphinx/search/sv.py +1 -1
- sphinx/search/tr.py +1 -1
- sphinx/search/zh.py +1 -1
- sphinx/testing/fixtures.py +23 -30
- sphinx/testing/path.py +9 -0
- sphinx/testing/restructuredtext.py +13 -5
- sphinx/testing/util.py +20 -63
- sphinx/texinputs/sphinxlatexobjects.sty +15 -15
- sphinx/themes/agogo/static/agogo.css_t +10 -4
- sphinx/themes/basic/layout.html +1 -1
- sphinx/themes/basic/static/basic.css_t +4 -0
- sphinx/themes/basic/static/documentation_options.js_t +1 -2
- sphinx/themes/basic/static/searchtools.js +17 -9
- sphinx/themes/basic/static/sphinx_highlight.js +13 -3
- sphinx/themes/bizstyle/static/bizstyle.css_t +4 -0
- sphinx/themes/classic/theme.conf +1 -1
- sphinx/themes/epub/static/epub.css_t +6 -1
- sphinx/themes/haiku/theme.conf +1 -1
- sphinx/themes/nature/static/nature.css_t +4 -0
- sphinx/themes/nonav/static/nonav.css_t +6 -1
- sphinx/themes/pyramid/static/pyramid.css_t +4 -0
- sphinx/themes/scrolls/static/scrolls.css_t +4 -0
- sphinx/themes/scrolls/theme.conf +1 -1
- sphinx/themes/sphinxdoc/static/sphinxdoc.css_t +4 -0
- sphinx/theming.py +9 -7
- sphinx/transforms/__init__.py +79 -3
- sphinx/transforms/compact_bullet_list.py +6 -3
- sphinx/transforms/i18n.py +26 -10
- sphinx/transforms/post_transforms/__init__.py +21 -8
- sphinx/transforms/post_transforms/code.py +6 -3
- sphinx/transforms/post_transforms/images.py +13 -9
- sphinx/util/__init__.py +21 -92
- sphinx/util/cfamily.py +7 -4
- sphinx/util/display.py +3 -2
- sphinx/util/docfields.py +7 -6
- sphinx/util/docstrings.py +1 -1
- sphinx/util/docutils.py +41 -31
- sphinx/util/fileutil.py +9 -6
- sphinx/util/i18n.py +21 -18
- sphinx/util/images.py +2 -1
- sphinx/util/index_entries.py +27 -0
- sphinx/util/inspect.py +83 -67
- sphinx/util/inventory.py +4 -2
- sphinx/util/logging.py +9 -6
- sphinx/util/matching.py +5 -2
- sphinx/util/math.py +6 -3
- sphinx/util/nodes.py +70 -31
- sphinx/util/osutil.py +22 -40
- sphinx/util/parallel.py +4 -1
- sphinx/util/rst.py +7 -3
- sphinx/util/tags.py +11 -4
- sphinx/util/template.py +17 -14
- sphinx/util/typing.py +61 -20
- sphinx/versioning.py +6 -4
- sphinx/writers/html.py +1 -1
- sphinx/writers/html5.py +32 -24
- sphinx/writers/latex.py +67 -53
- sphinx/writers/manpage.py +9 -5
- sphinx/writers/texinfo.py +11 -9
- sphinx/writers/text.py +14 -9
- sphinx/writers/xml.py +3 -2
- {sphinx-7.1.2.dist-info → sphinx-7.2.0.dist-info}/METADATA +7 -5
- sphinx-7.2.0.dist-info/RECORD +568 -0
- sphinx/testing/comparer.py +0 -97
- sphinx-7.1.2.dist-info/RECORD +0 -564
- {sphinx-7.1.2.dist-info → sphinx-7.2.0.dist-info}/LICENSE +0 -0
- {sphinx-7.1.2.dist-info → sphinx-7.2.0.dist-info}/WHEEL +0 -0
- {sphinx-7.1.2.dist-info → sphinx-7.2.0.dist-info}/entry_points.txt +0 -0
sphinx/search/de.py
CHANGED
sphinx/search/en.py
CHANGED
sphinx/search/es.py
CHANGED
sphinx/search/fi.py
CHANGED
sphinx/search/fr.py
CHANGED
sphinx/search/hu.py
CHANGED
sphinx/search/it.py
CHANGED
sphinx/search/ja.py
CHANGED
sphinx/search/nl.py
CHANGED
sphinx/search/no.py
CHANGED
sphinx/search/pt.py
CHANGED
sphinx/search/ro.py
CHANGED
sphinx/search/ru.py
CHANGED
sphinx/search/sv.py
CHANGED
sphinx/search/tr.py
CHANGED
sphinx/search/zh.py
CHANGED
sphinx/testing/fixtures.py
CHANGED
|
@@ -2,17 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import shutil
|
|
5
6
|
import subprocess
|
|
6
7
|
import sys
|
|
7
8
|
from collections import namedtuple
|
|
8
9
|
from io import StringIO
|
|
9
|
-
from typing import Any, Callable
|
|
10
|
+
from typing import TYPE_CHECKING, Any, Callable
|
|
10
11
|
|
|
11
12
|
import pytest
|
|
12
13
|
|
|
13
|
-
from sphinx.testing import util
|
|
14
14
|
from sphinx.testing.util import SphinxTestApp, SphinxTestAppWrapperForSkipBuilding
|
|
15
15
|
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from collections.abc import Generator
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
16
20
|
DEFAULT_ENABLED_MARKERS = [
|
|
17
21
|
(
|
|
18
22
|
'sphinx(builder, testroot=None, freshenv=False, confoverrides=None, tags=None,'
|
|
@@ -57,7 +61,7 @@ class SharedResult:
|
|
|
57
61
|
|
|
58
62
|
@pytest.fixture()
|
|
59
63
|
def app_params(request: Any, test_params: dict, shared_result: SharedResult,
|
|
60
|
-
sphinx_test_tempdir: str, rootdir: str) ->
|
|
64
|
+
sphinx_test_tempdir: str, rootdir: str) -> _app_params:
|
|
61
65
|
"""
|
|
62
66
|
Parameters that are specified by 'pytest.mark.sphinx' for
|
|
63
67
|
sphinx.application.Sphinx initialization
|
|
@@ -79,8 +83,8 @@ def app_params(request: Any, test_params: dict, shared_result: SharedResult,
|
|
|
79
83
|
# ##### process pytest.mark.test_params
|
|
80
84
|
if test_params['shared_result']:
|
|
81
85
|
if 'srcdir' in kwargs:
|
|
82
|
-
|
|
83
|
-
|
|
86
|
+
msg = 'You can not specify shared_result and srcdir in same time.'
|
|
87
|
+
raise pytest.Exception(msg)
|
|
84
88
|
kwargs['srcdir'] = test_params['shared_result']
|
|
85
89
|
restore = shared_result.restore(test_params['shared_result'])
|
|
86
90
|
kwargs.update(restore)
|
|
@@ -93,9 +97,12 @@ def app_params(request: Any, test_params: dict, shared_result: SharedResult,
|
|
|
93
97
|
# special support for sphinx/tests
|
|
94
98
|
if rootdir and not srcdir.exists():
|
|
95
99
|
testroot_path = rootdir / ('test-' + testroot)
|
|
96
|
-
|
|
100
|
+
shutil.copytree(testroot_path, srcdir)
|
|
101
|
+
|
|
102
|
+
return _app_params(args, kwargs)
|
|
97
103
|
|
|
98
|
-
|
|
104
|
+
|
|
105
|
+
_app_params = namedtuple('_app_params', 'args,kwargs')
|
|
99
106
|
|
|
100
107
|
|
|
101
108
|
@pytest.fixture()
|
|
@@ -116,13 +123,13 @@ def test_params(request: Any) -> dict:
|
|
|
116
123
|
}
|
|
117
124
|
result.update(kwargs)
|
|
118
125
|
|
|
119
|
-
if
|
|
120
|
-
|
|
121
|
-
|
|
126
|
+
if result['shared_result'] and not isinstance(result['shared_result'], str):
|
|
127
|
+
msg = 'You can only provide a string type of value for "shared_result"'
|
|
128
|
+
raise pytest.Exception(msg)
|
|
122
129
|
return result
|
|
123
130
|
|
|
124
131
|
|
|
125
|
-
@pytest.fixture(
|
|
132
|
+
@pytest.fixture()
|
|
126
133
|
def app(test_params: dict, app_params: tuple[dict, dict], make_app: Callable,
|
|
127
134
|
shared_result: SharedResult) -> Generator[SphinxTestApp, None, None]:
|
|
128
135
|
"""
|
|
@@ -143,7 +150,7 @@ def app(test_params: dict, app_params: tuple[dict, dict], make_app: Callable,
|
|
|
143
150
|
shared_result.store(test_params['shared_result'], app_)
|
|
144
151
|
|
|
145
152
|
|
|
146
|
-
@pytest.fixture(
|
|
153
|
+
@pytest.fixture()
|
|
147
154
|
def status(app: SphinxTestApp) -> StringIO:
|
|
148
155
|
"""
|
|
149
156
|
Back-compatibility for testing with previous @with_app decorator
|
|
@@ -151,7 +158,7 @@ def status(app: SphinxTestApp) -> StringIO:
|
|
|
151
158
|
return app._status
|
|
152
159
|
|
|
153
160
|
|
|
154
|
-
@pytest.fixture(
|
|
161
|
+
@pytest.fixture()
|
|
155
162
|
def warning(app: SphinxTestApp) -> StringIO:
|
|
156
163
|
"""
|
|
157
164
|
Back-compatibility for testing with previous @with_app decorator
|
|
@@ -166,8 +173,6 @@ def make_app(test_params: dict, monkeypatch: Any) -> Generator[Callable, None, N
|
|
|
166
173
|
if you want to initialize 'app' in your test function. please use this
|
|
167
174
|
instead of using SphinxTestApp class directory.
|
|
168
175
|
"""
|
|
169
|
-
monkeypatch.setattr('sphinx.application.abspath', lambda x: x)
|
|
170
|
-
|
|
171
176
|
apps = []
|
|
172
177
|
syspath = sys.path[:]
|
|
173
178
|
|
|
@@ -215,21 +220,9 @@ def if_graphviz_found(app: SphinxTestApp) -> None: # NoQA: PT004
|
|
|
215
220
|
|
|
216
221
|
|
|
217
222
|
@pytest.fixture(scope='session')
|
|
218
|
-
def sphinx_test_tempdir(
|
|
219
|
-
"""
|
|
220
|
-
|
|
221
|
-
"""
|
|
222
|
-
tmpdir = tmpdir_factory.getbasetemp()
|
|
223
|
-
return util.path(tmpdir).abspath()
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
@pytest.fixture()
|
|
227
|
-
def tempdir(tmpdir: str) -> util.path:
|
|
228
|
-
"""
|
|
229
|
-
Temporary directory wrapped with `path` class.
|
|
230
|
-
This fixture is for back-compatibility with old test implementation.
|
|
231
|
-
"""
|
|
232
|
-
return util.path(tmpdir)
|
|
223
|
+
def sphinx_test_tempdir(tmp_path_factory: Any) -> Path:
|
|
224
|
+
"""Temporary directory."""
|
|
225
|
+
return tmp_path_factory.getbasetemp()
|
|
233
226
|
|
|
234
227
|
|
|
235
228
|
@pytest.fixture()
|
sphinx/testing/path.py
CHANGED
|
@@ -3,11 +3,18 @@ from __future__ import annotations
|
|
|
3
3
|
import os
|
|
4
4
|
import shutil
|
|
5
5
|
import sys
|
|
6
|
+
import warnings
|
|
6
7
|
from typing import IO, TYPE_CHECKING, Any, Callable
|
|
7
8
|
|
|
9
|
+
from sphinx.deprecation import RemovedInSphinx90Warning
|
|
10
|
+
|
|
8
11
|
if TYPE_CHECKING:
|
|
9
12
|
import builtins
|
|
10
13
|
|
|
14
|
+
warnings.warn("'sphinx.testing.path' is deprecated. "
|
|
15
|
+
"Use 'os.path' or 'pathlib' instead.",
|
|
16
|
+
RemovedInSphinx90Warning, stacklevel=2)
|
|
17
|
+
|
|
11
18
|
FILESYSTEMENCODING = sys.getfilesystemencoding() or sys.getdefaultencoding()
|
|
12
19
|
|
|
13
20
|
|
|
@@ -27,6 +34,8 @@ class path(str):
|
|
|
27
34
|
Represents a path which behaves like a string.
|
|
28
35
|
"""
|
|
29
36
|
|
|
37
|
+
__slots__ = ()
|
|
38
|
+
|
|
30
39
|
@property
|
|
31
40
|
def parent(self) -> path:
|
|
32
41
|
"""
|
|
@@ -18,10 +18,18 @@ def parse(app: Sphinx, text: str, docname: str = 'index') -> nodes.document:
|
|
|
18
18
|
parser = RSTParser()
|
|
19
19
|
parser.set_application(app)
|
|
20
20
|
with sphinx_domains(app.env):
|
|
21
|
-
return publish_doctree(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
return publish_doctree(
|
|
22
|
+
text,
|
|
23
|
+
path.join(app.srcdir, docname + '.rst'),
|
|
24
|
+
reader=reader,
|
|
25
|
+
parser=parser,
|
|
26
|
+
settings_overrides={
|
|
27
|
+
'env': app.env,
|
|
28
|
+
'gettext_compact': True,
|
|
29
|
+
'input_encoding': 'utf-8',
|
|
30
|
+
'output_encoding': 'unicode',
|
|
31
|
+
'traceback': True,
|
|
32
|
+
},
|
|
33
|
+
)
|
|
26
34
|
finally:
|
|
27
35
|
app.env.temp_data.pop('docname', None)
|
sphinx/testing/util.py
CHANGED
|
@@ -1,44 +1,27 @@
|
|
|
1
1
|
"""Sphinx test suite utilities"""
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import contextlib
|
|
5
5
|
import os
|
|
6
6
|
import re
|
|
7
7
|
import sys
|
|
8
8
|
import warnings
|
|
9
|
-
from typing import IO, TYPE_CHECKING, Any
|
|
9
|
+
from typing import IO, TYPE_CHECKING, Any
|
|
10
10
|
from xml.etree import ElementTree
|
|
11
11
|
|
|
12
12
|
from docutils import nodes
|
|
13
|
-
from docutils.nodes import Node
|
|
14
13
|
from docutils.parsers.rst import directives, roles
|
|
15
14
|
|
|
16
15
|
from sphinx import application, locale
|
|
17
16
|
from sphinx.pycode import ModuleAnalyzer
|
|
18
|
-
from sphinx.testing.path import path
|
|
19
|
-
from sphinx.util.osutil import relpath
|
|
20
17
|
|
|
21
18
|
if TYPE_CHECKING:
|
|
22
19
|
from io import StringIO
|
|
20
|
+
from pathlib import Path
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
'Struct', 'SphinxTestApp', 'SphinxTestAppWrapperForSkipBuilding',
|
|
26
|
-
]
|
|
22
|
+
from docutils.nodes import Node
|
|
27
23
|
|
|
28
|
-
|
|
29
|
-
def assert_re_search(regex: re.Pattern, text: str, flags: int = 0) -> None:
|
|
30
|
-
if not re.search(regex, text, flags):
|
|
31
|
-
raise AssertionError(f'{regex!r} did not match {text!r}')
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def assert_not_re_search(regex: re.Pattern, text: str, flags: int = 0) -> None:
|
|
35
|
-
if re.search(regex, text, flags):
|
|
36
|
-
raise AssertionError(f'{regex!r} did match {text!r}')
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def assert_startswith(thing: str, prefix: str) -> None:
|
|
40
|
-
if not thing.startswith(prefix):
|
|
41
|
-
raise AssertionError(f'{thing!r} does not start with {prefix!r}')
|
|
24
|
+
__all__ = 'SphinxTestApp', 'SphinxTestAppWrapperForSkipBuilding'
|
|
42
25
|
|
|
43
26
|
|
|
44
27
|
def assert_node(node: Node, cls: Any = None, xpath: str = "", **kwargs: Any) -> None:
|
|
@@ -73,8 +56,10 @@ def assert_node(node: Node, cls: Any = None, xpath: str = "", **kwargs: Any) ->
|
|
|
73
56
|
'The node%s does not have any attributes' % xpath
|
|
74
57
|
|
|
75
58
|
for key, value in kwargs.items():
|
|
76
|
-
|
|
77
|
-
|
|
59
|
+
if key not in node:
|
|
60
|
+
if (key := key.replace('_', '-')) not in node:
|
|
61
|
+
msg = f'The node{xpath} does not have {key!r} attribute: {node!r}'
|
|
62
|
+
raise AssertionError(msg)
|
|
78
63
|
assert node[key] == value, \
|
|
79
64
|
f'The node{xpath}[{key}] is not {value!r}: {node[key]!r}'
|
|
80
65
|
|
|
@@ -85,11 +70,6 @@ def etree_parse(path: str) -> Any:
|
|
|
85
70
|
return ElementTree.parse(path) # NoQA: S314 # using known data in tests
|
|
86
71
|
|
|
87
72
|
|
|
88
|
-
class Struct:
|
|
89
|
-
def __init__(self, **kwargs: Any) -> None:
|
|
90
|
-
self.__dict__.update(kwargs)
|
|
91
|
-
|
|
92
|
-
|
|
93
73
|
class SphinxTestApp(application.Sphinx):
|
|
94
74
|
"""
|
|
95
75
|
A subclass of :class:`Sphinx` that runs on the test root, with some
|
|
@@ -101,8 +81,8 @@ class SphinxTestApp(application.Sphinx):
|
|
|
101
81
|
def __init__(
|
|
102
82
|
self,
|
|
103
83
|
buildername: str = 'html',
|
|
104
|
-
srcdir:
|
|
105
|
-
builddir:
|
|
84
|
+
srcdir: Path | None = None,
|
|
85
|
+
builddir: Path | None = None,
|
|
106
86
|
freshenv: bool = False,
|
|
107
87
|
confoverrides: dict | None = None,
|
|
108
88
|
status: IO | None = None,
|
|
@@ -115,23 +95,23 @@ class SphinxTestApp(application.Sphinx):
|
|
|
115
95
|
|
|
116
96
|
self.docutils_conf_path = srcdir / 'docutils.conf'
|
|
117
97
|
if docutilsconf is not None:
|
|
118
|
-
self.docutils_conf_path.write_text(docutilsconf)
|
|
98
|
+
self.docutils_conf_path.write_text(docutilsconf, encoding='utf8')
|
|
119
99
|
|
|
120
100
|
if builddir is None:
|
|
121
101
|
builddir = srcdir / '_build'
|
|
122
102
|
|
|
123
103
|
confdir = srcdir
|
|
124
104
|
outdir = builddir.joinpath(buildername)
|
|
125
|
-
outdir.
|
|
105
|
+
outdir.mkdir(parents=True, exist_ok=True)
|
|
126
106
|
doctreedir = builddir.joinpath('doctrees')
|
|
127
|
-
doctreedir.
|
|
107
|
+
doctreedir.mkdir(parents=True, exist_ok=True)
|
|
128
108
|
if confoverrides is None:
|
|
129
109
|
confoverrides = {}
|
|
130
110
|
warningiserror = False
|
|
131
111
|
|
|
132
112
|
self._saved_path = sys.path[:]
|
|
133
|
-
self._saved_directives = directives._directives.copy() # type: ignore
|
|
134
|
-
self._saved_roles = roles._roles.copy() # type: ignore
|
|
113
|
+
self._saved_directives = directives._directives.copy() # type: ignore[attr-defined]
|
|
114
|
+
self._saved_roles = roles._roles.copy() # type: ignore[attr-defined]
|
|
135
115
|
|
|
136
116
|
self._saved_nodeclasses = {v for v in dir(nodes.GenericNodeVisitor)
|
|
137
117
|
if v.startswith('visit_')}
|
|
@@ -149,17 +129,15 @@ class SphinxTestApp(application.Sphinx):
|
|
|
149
129
|
locale.translators.clear()
|
|
150
130
|
sys.path[:] = self._saved_path
|
|
151
131
|
sys.modules.pop('autodoc_fodder', None)
|
|
152
|
-
directives._directives = self._saved_directives # type: ignore
|
|
153
|
-
roles._roles = self._saved_roles # type: ignore
|
|
132
|
+
directives._directives = self._saved_directives # type: ignore[attr-defined]
|
|
133
|
+
roles._roles = self._saved_roles # type: ignore[attr-defined]
|
|
154
134
|
for method in dir(nodes.GenericNodeVisitor):
|
|
155
135
|
if method.startswith('visit_') and \
|
|
156
136
|
method not in self._saved_nodeclasses:
|
|
157
137
|
delattr(nodes.GenericNodeVisitor, 'visit_' + method[6:])
|
|
158
138
|
delattr(nodes.GenericNodeVisitor, 'depart_' + method[6:])
|
|
159
|
-
|
|
139
|
+
with contextlib.suppress(FileNotFoundError):
|
|
160
140
|
os.remove(self.docutils_conf_path)
|
|
161
|
-
except FileNotFoundError:
|
|
162
|
-
pass
|
|
163
141
|
|
|
164
142
|
def __repr__(self) -> str:
|
|
165
143
|
return f'<{self.__class__.__name__} buildername={self.builder.name!r}>'
|
|
@@ -183,32 +161,11 @@ class SphinxTestAppWrapperForSkipBuilding:
|
|
|
183
161
|
return getattr(self.app, name)
|
|
184
162
|
|
|
185
163
|
def build(self, *args: Any, **kwargs: Any) -> None:
|
|
186
|
-
if not self.app.outdir
|
|
164
|
+
if not os.listdir(self.app.outdir):
|
|
187
165
|
# if listdir is empty, do build.
|
|
188
166
|
self.app.build(*args, **kwargs)
|
|
189
167
|
# otherwise, we can use built cache
|
|
190
168
|
|
|
191
169
|
|
|
192
|
-
_unicode_literals_re = re.compile(r'u(".*?")|u(\'.*?\')')
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
def find_files(root: str, suffix: str | None = None) -> Generator[str, None, None]:
|
|
196
|
-
for dirpath, _dirs, files in os.walk(root, followlinks=True):
|
|
197
|
-
dirpath = path(dirpath)
|
|
198
|
-
for f in [f for f in files if not suffix or f.endswith(suffix)]:
|
|
199
|
-
fpath = dirpath / f
|
|
200
|
-
yield relpath(fpath, root)
|
|
201
|
-
|
|
202
|
-
|
|
203
170
|
def strip_escseq(text: str) -> str:
|
|
204
171
|
return re.sub('\x1b.*?m', '', text)
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
def simple_decorator(f):
|
|
208
|
-
"""
|
|
209
|
-
A simple decorator that does nothing, for tests to use.
|
|
210
|
-
"""
|
|
211
|
-
@functools.wraps(f)
|
|
212
|
-
def wrapper(*args, **kwargs):
|
|
213
|
-
return f(*args, **kwargs)
|
|
214
|
-
return wrapper
|
|
@@ -310,22 +310,22 @@
|
|
|
310
310
|
\newcommand{\optionlistlabel}[1]{\normalfont\bfseries #1 \hfill}% \bf deprecated
|
|
311
311
|
\newenvironment{optionlist}[1]
|
|
312
312
|
{\begin{list}{}
|
|
313
|
-
{\setlength{\labelwidth}{#1}
|
|
314
|
-
\setlength{\rightmargin}{1cm}
|
|
315
|
-
\setlength{\leftmargin}{\rightmargin}
|
|
316
|
-
\addtolength{\leftmargin}{\labelwidth}
|
|
317
|
-
\addtolength{\leftmargin}{\labelsep}
|
|
318
|
-
\renewcommand{\makelabel}{\optionlistlabel}}
|
|
313
|
+
{\setlength{\labelwidth}{#1}%
|
|
314
|
+
\setlength{\rightmargin}{1cm}%
|
|
315
|
+
\setlength{\leftmargin}{\rightmargin}%
|
|
316
|
+
\addtolength{\leftmargin}{\labelwidth}%
|
|
317
|
+
\addtolength{\leftmargin}{\labelsep}%
|
|
318
|
+
\renewcommand{\makelabel}{\optionlistlabel}}%
|
|
319
319
|
}{\end{list}}
|
|
320
320
|
|
|
321
321
|
\newlength{\lineblockindentation}
|
|
322
322
|
\setlength{\lineblockindentation}{2.5em}
|
|
323
323
|
\newenvironment{lineblock}[1]
|
|
324
324
|
{\begin{list}{}
|
|
325
|
-
{\setlength{\partopsep}{\parskip}
|
|
326
|
-
\addtolength{\partopsep}{\baselineskip}
|
|
325
|
+
{\setlength{\partopsep}{\parskip}%
|
|
326
|
+
\addtolength{\partopsep}{\baselineskip}%
|
|
327
327
|
\topsep0pt\itemsep0.15\baselineskip\parsep0pt
|
|
328
|
-
\leftmargin#1\relax}
|
|
328
|
+
\leftmargin#1\relax}%
|
|
329
329
|
\raggedright}
|
|
330
330
|
{\end{list}}
|
|
331
331
|
|
|
@@ -351,12 +351,12 @@
|
|
|
351
351
|
\DUprovidelength{\DUlineblockindent}{2.5em}
|
|
352
352
|
\ifdefined\DUlineblock\else
|
|
353
353
|
\newenvironment{DUlineblock}[1]{%
|
|
354
|
-
\list{}{\setlength{\partopsep}{\parskip}
|
|
355
|
-
\addtolength{\partopsep}{\baselineskip}
|
|
356
|
-
\setlength{\topsep}{0pt}
|
|
357
|
-
\setlength{\itemsep}{0.15\baselineskip}
|
|
358
|
-
\setlength{\parsep}{0pt}
|
|
359
|
-
\setlength{\leftmargin}{#1}}
|
|
354
|
+
\list{}{\setlength{\partopsep}{\parskip}%
|
|
355
|
+
\addtolength{\partopsep}{\baselineskip}%
|
|
356
|
+
\setlength{\topsep}{0pt}%
|
|
357
|
+
\setlength{\itemsep}{0.15\baselineskip}%
|
|
358
|
+
\setlength{\parsep}{0pt}%
|
|
359
|
+
\setlength{\leftmargin}{#1}}%
|
|
360
360
|
\raggedright
|
|
361
361
|
}
|
|
362
362
|
{\endlist}
|
|
@@ -19,6 +19,10 @@ body {
|
|
|
19
19
|
line-height: 1.4em;
|
|
20
20
|
color: black;
|
|
21
21
|
background-color: {{ theme_bgcolor }};
|
|
22
|
+
|
|
23
|
+
/* fix for background colors breaking at horizontal
|
|
24
|
+
scrolling on smaller devices */
|
|
25
|
+
min-width: fit-content;
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
|
|
@@ -41,6 +45,10 @@ a {
|
|
|
41
45
|
color: {{ theme_linkcolor }};
|
|
42
46
|
}
|
|
43
47
|
|
|
48
|
+
a:visited {
|
|
49
|
+
color: #551a8b;
|
|
50
|
+
}
|
|
51
|
+
|
|
44
52
|
div.bodywrapper a, div.footer a {
|
|
45
53
|
text-decoration: underline;
|
|
46
54
|
}
|
|
@@ -127,8 +135,7 @@ dt:target, .highlighted {
|
|
|
127
135
|
/* Header */
|
|
128
136
|
|
|
129
137
|
div.header {
|
|
130
|
-
padding
|
|
131
|
-
padding-bottom: 10px;
|
|
138
|
+
padding: 1em;
|
|
132
139
|
}
|
|
133
140
|
|
|
134
141
|
div.header .headertitle {
|
|
@@ -165,8 +172,7 @@ img.logo {
|
|
|
165
172
|
/* Content */
|
|
166
173
|
div.content-wrapper {
|
|
167
174
|
background-color: white;
|
|
168
|
-
padding
|
|
169
|
-
padding-bottom: 20px;
|
|
175
|
+
padding: 1em;
|
|
170
176
|
}
|
|
171
177
|
|
|
172
178
|
div.document {
|
sphinx/themes/basic/layout.html
CHANGED
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
{%- if html_tag %}
|
|
103
103
|
{{ html_tag }}
|
|
104
104
|
{%- else %}
|
|
105
|
-
<html{% if language is not none %} lang="{{ language }}"{% endif %}>
|
|
105
|
+
<html{% if language is not none %} lang="{{ language }}"{% endif %} data-content_root="{{ content_root }}">
|
|
106
106
|
{%- endif %}
|
|
107
107
|
<head>
|
|
108
108
|
<meta charset="{{ encoding }}" />
|