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
|
@@ -4,19 +4,22 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
6
|
import re
|
|
7
|
+
from hashlib import sha1
|
|
7
8
|
from math import ceil
|
|
8
|
-
from typing import Any
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
9
10
|
|
|
10
11
|
from docutils import nodes
|
|
11
12
|
|
|
12
|
-
from sphinx.application import Sphinx
|
|
13
13
|
from sphinx.locale import __
|
|
14
14
|
from sphinx.transforms import SphinxTransform
|
|
15
|
-
from sphinx.util import logging, requests
|
|
15
|
+
from sphinx.util import logging, requests
|
|
16
16
|
from sphinx.util.http_date import epoch_to_rfc1123, rfc1123_to_epoch
|
|
17
17
|
from sphinx.util.images import get_image_extension, guess_mimetype, parse_data_uri
|
|
18
18
|
from sphinx.util.osutil import ensuredir
|
|
19
19
|
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from sphinx.application import Sphinx
|
|
22
|
+
|
|
20
23
|
logger = logging.getLogger(__name__)
|
|
21
24
|
|
|
22
25
|
MAX_FILENAME_LEN = 32
|
|
@@ -57,13 +60,13 @@ class ImageDownloader(BaseImageConverter):
|
|
|
57
60
|
basename = basename.split('?')[0]
|
|
58
61
|
if basename == '' or len(basename) > MAX_FILENAME_LEN:
|
|
59
62
|
filename, ext = os.path.splitext(node['uri'])
|
|
60
|
-
basename = sha1(filename.encode()).hexdigest() + ext
|
|
63
|
+
basename = sha1(filename.encode(), usedforsecurity=False).hexdigest() + ext
|
|
61
64
|
basename = re.sub(CRITICAL_PATH_CHAR_RE, "_", basename)
|
|
62
65
|
|
|
63
66
|
dirname = node['uri'].replace('://', '/').translate({ord("?"): "/",
|
|
64
67
|
ord("&"): "/"})
|
|
65
68
|
if len(dirname) > MAX_FILENAME_LEN:
|
|
66
|
-
dirname = sha1(dirname.encode()).hexdigest()
|
|
69
|
+
dirname = sha1(dirname.encode(), usedforsecurity=False).hexdigest()
|
|
67
70
|
ensuredir(os.path.join(self.imagedir, dirname))
|
|
68
71
|
path = os.path.join(self.imagedir, dirname, basename)
|
|
69
72
|
|
|
@@ -125,7 +128,7 @@ class DataURIExtractor(BaseImageConverter):
|
|
|
125
128
|
return
|
|
126
129
|
|
|
127
130
|
ensuredir(os.path.join(self.imagedir, 'embeded'))
|
|
128
|
-
digest = sha1(image.data).hexdigest()
|
|
131
|
+
digest = sha1(image.data, usedforsecurity=False).hexdigest()
|
|
129
132
|
path = os.path.join(self.imagedir, 'embeded', digest + ext)
|
|
130
133
|
self.app.env.original_image_uri[path] = node['uri']
|
|
131
134
|
|
|
@@ -217,11 +220,12 @@ class ImageConverter(BaseImageConverter):
|
|
|
217
220
|
if rule in self.conversion_rules:
|
|
218
221
|
return rule
|
|
219
222
|
|
|
220
|
-
|
|
223
|
+
msg = 'No conversion rule found'
|
|
224
|
+
raise ValueError(msg)
|
|
221
225
|
|
|
222
226
|
def is_available(self) -> bool:
|
|
223
227
|
"""Return the image converter is available or not."""
|
|
224
|
-
raise NotImplementedError
|
|
228
|
+
raise NotImplementedError
|
|
225
229
|
|
|
226
230
|
def guess_mimetypes(self, node: nodes.image) -> list[str]:
|
|
227
231
|
if '?' in node['candidates']:
|
|
@@ -262,7 +266,7 @@ class ImageConverter(BaseImageConverter):
|
|
|
262
266
|
*_from* is a path of the source image file, and *_to* is a path
|
|
263
267
|
of the destination file.
|
|
264
268
|
"""
|
|
265
|
-
raise NotImplementedError
|
|
269
|
+
raise NotImplementedError
|
|
266
270
|
|
|
267
271
|
|
|
268
272
|
def setup(app: Sphinx) -> dict[str, Any]:
|
sphinx/util/__init__.py
CHANGED
|
@@ -6,7 +6,6 @@ import hashlib
|
|
|
6
6
|
import os
|
|
7
7
|
import posixpath
|
|
8
8
|
import re
|
|
9
|
-
import sys
|
|
10
9
|
from importlib import import_module
|
|
11
10
|
from os import path
|
|
12
11
|
from typing import IO, Any
|
|
@@ -17,6 +16,7 @@ from sphinx.locale import __
|
|
|
17
16
|
from sphinx.util import display as _display
|
|
18
17
|
from sphinx.util import exceptions as _exceptions
|
|
19
18
|
from sphinx.util import http_date as _http_date
|
|
19
|
+
from sphinx.util import index_entries as _index_entries
|
|
20
20
|
from sphinx.util import logging
|
|
21
21
|
from sphinx.util import osutil as _osutil
|
|
22
22
|
from sphinx.util.console import strip_colors # NoQA: F401
|
|
@@ -51,8 +51,7 @@ url_re: re.Pattern[str] = re.compile(r'(?P<schema>.+)://.*')
|
|
|
51
51
|
# High-level utility functions.
|
|
52
52
|
|
|
53
53
|
def docname_join(basedocname: str, docname: str) -> str:
|
|
54
|
-
return posixpath.normpath(
|
|
55
|
-
posixpath.join('/' + basedocname, '..', docname))[1:]
|
|
54
|
+
return posixpath.normpath(posixpath.join('/' + basedocname, '..', docname))[1:]
|
|
56
55
|
|
|
57
56
|
|
|
58
57
|
def get_filetype(source_suffix: dict[str, str], filename: str) -> str:
|
|
@@ -105,26 +104,20 @@ class FilenameUniqDict(dict):
|
|
|
105
104
|
self._existing = state
|
|
106
105
|
|
|
107
106
|
|
|
108
|
-
def
|
|
109
|
-
"""
|
|
107
|
+
def _md5(data=b'', **_kw):
|
|
108
|
+
"""Deprecated wrapper around hashlib.md5
|
|
110
109
|
|
|
111
|
-
|
|
110
|
+
To be removed in Sphinx 9.0
|
|
112
111
|
"""
|
|
112
|
+
return hashlib.md5(data, usedforsecurity=False)
|
|
113
113
|
|
|
114
|
-
if sys.version_info[:2] > (3, 8):
|
|
115
|
-
return hashlib.md5(data, usedforsecurity=False)
|
|
116
|
-
return hashlib.md5(data, **kwargs)
|
|
117
114
|
|
|
115
|
+
def _sha1(data=b'', **_kw):
|
|
116
|
+
"""Deprecated wrapper around hashlib.sha1
|
|
118
117
|
|
|
119
|
-
|
|
120
|
-
"""Wrapper around hashlib.sha1
|
|
121
|
-
|
|
122
|
-
Attempt call with 'usedforsecurity=False' if supported.
|
|
118
|
+
To be removed in Sphinx 9.0
|
|
123
119
|
"""
|
|
124
|
-
|
|
125
|
-
if sys.version_info[:2] > (3, 8):
|
|
126
|
-
return hashlib.sha1(data, usedforsecurity=False)
|
|
127
|
-
return hashlib.sha1(data, **kwargs)
|
|
120
|
+
return hashlib.sha1(data, usedforsecurity=False)
|
|
128
121
|
|
|
129
122
|
|
|
130
123
|
class DownloadFiles(dict):
|
|
@@ -136,7 +129,7 @@ class DownloadFiles(dict):
|
|
|
136
129
|
|
|
137
130
|
def add_file(self, docname: str, filename: str) -> str:
|
|
138
131
|
if filename not in self:
|
|
139
|
-
digest = md5(filename.encode()).hexdigest()
|
|
132
|
+
digest = hashlib.md5(filename.encode(), usedforsecurity=False).hexdigest()
|
|
140
133
|
dest = f'{digest}/{os.path.basename(filename)}'
|
|
141
134
|
self[filename] = (set(), dest)
|
|
142
135
|
|
|
@@ -155,23 +148,6 @@ class DownloadFiles(dict):
|
|
|
155
148
|
self.add_file(docname, filename)
|
|
156
149
|
|
|
157
150
|
|
|
158
|
-
def get_full_modname(modname: str, attribute: str) -> str | None:
|
|
159
|
-
if modname is None:
|
|
160
|
-
# Prevents a TypeError: if the last getattr() call will return None
|
|
161
|
-
# then it's better to return it directly
|
|
162
|
-
return None
|
|
163
|
-
module = import_module(modname)
|
|
164
|
-
|
|
165
|
-
# Allow an attribute to have multiple parts and incidentally allow
|
|
166
|
-
# repeated .s in the attribute.
|
|
167
|
-
value = module
|
|
168
|
-
for attr in attribute.split('.'):
|
|
169
|
-
if attr:
|
|
170
|
-
value = getattr(value, attr)
|
|
171
|
-
|
|
172
|
-
return getattr(value, '__module__', None)
|
|
173
|
-
|
|
174
|
-
|
|
175
151
|
# a regex to recognize coding cookies
|
|
176
152
|
_coding_re = re.compile(r'coding[:=]\s*([-\w.]+)')
|
|
177
153
|
|
|
@@ -238,36 +214,13 @@ def parselinenos(spec: str, total: int) -> list[int]:
|
|
|
238
214
|
items.extend(range(start - 1, end))
|
|
239
215
|
else:
|
|
240
216
|
raise ValueError
|
|
241
|
-
except
|
|
242
|
-
|
|
217
|
+
except ValueError as exc:
|
|
218
|
+
msg = f'invalid line number spec: {spec!r}'
|
|
219
|
+
raise ValueError(msg) from exc
|
|
243
220
|
|
|
244
221
|
return items
|
|
245
222
|
|
|
246
223
|
|
|
247
|
-
def split_into(n: int, type: str, value: str) -> list[str]:
|
|
248
|
-
"""Split an index entry into a given number of parts at semicolons."""
|
|
249
|
-
parts = [x.strip() for x in value.split(';', n - 1)]
|
|
250
|
-
if len(list(filter(None, parts))) < n:
|
|
251
|
-
raise ValueError(f'invalid {type} index entry {value!r}')
|
|
252
|
-
return parts
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
def split_index_msg(entry_type: str, value: str) -> list[str]:
|
|
256
|
-
# new entry types must be listed in util/nodes.py!
|
|
257
|
-
if entry_type == 'single':
|
|
258
|
-
try:
|
|
259
|
-
return split_into(2, 'single', value)
|
|
260
|
-
except ValueError:
|
|
261
|
-
return split_into(1, 'single', value)
|
|
262
|
-
if entry_type == 'pair':
|
|
263
|
-
return split_into(2, 'pair', value)
|
|
264
|
-
if entry_type == 'triple':
|
|
265
|
-
return split_into(3, 'triple', value)
|
|
266
|
-
if entry_type in {'see', 'seealso'}:
|
|
267
|
-
return split_into(2, 'see', value)
|
|
268
|
-
raise ValueError(f'invalid {entry_type} index entry {value!r}')
|
|
269
|
-
|
|
270
|
-
|
|
271
224
|
def import_object(objname: str, source: str | None = None) -> Any:
|
|
272
225
|
"""Import python object by qualname."""
|
|
273
226
|
try:
|
|
@@ -289,36 +242,6 @@ def import_object(objname: str, source: str | None = None) -> Any:
|
|
|
289
242
|
raise ExtensionError('Could not import %s' % objname, exc) from exc
|
|
290
243
|
|
|
291
244
|
|
|
292
|
-
def split_full_qualified_name(name: str) -> tuple[str | None, str]:
|
|
293
|
-
"""Split full qualified name to a pair of modname and qualname.
|
|
294
|
-
|
|
295
|
-
A qualname is an abbreviation for "Qualified name" introduced at PEP-3155
|
|
296
|
-
(https://peps.python.org/pep-3155/). It is a dotted path name
|
|
297
|
-
from the module top-level.
|
|
298
|
-
|
|
299
|
-
A "full" qualified name means a string containing both module name and
|
|
300
|
-
qualified name.
|
|
301
|
-
|
|
302
|
-
.. note:: This function actually imports the module to check its existence.
|
|
303
|
-
Therefore you need to mock 3rd party modules if needed before
|
|
304
|
-
calling this function.
|
|
305
|
-
"""
|
|
306
|
-
parts = name.split('.')
|
|
307
|
-
for i, _part in enumerate(parts, 1):
|
|
308
|
-
try:
|
|
309
|
-
modname = ".".join(parts[:i])
|
|
310
|
-
import_module(modname)
|
|
311
|
-
except ImportError:
|
|
312
|
-
if parts[:i - 1]:
|
|
313
|
-
return ".".join(parts[:i - 1]), ".".join(parts[i - 1:])
|
|
314
|
-
else:
|
|
315
|
-
return None, ".".join(parts)
|
|
316
|
-
except IndexError:
|
|
317
|
-
pass
|
|
318
|
-
|
|
319
|
-
return name, ""
|
|
320
|
-
|
|
321
|
-
|
|
322
245
|
def encode_uri(uri: str) -> str:
|
|
323
246
|
split = list(urlsplit(uri))
|
|
324
247
|
split[1] = split[1].encode('idna').decode('ascii')
|
|
@@ -354,12 +277,18 @@ _DEPRECATED_OBJECTS = {
|
|
|
354
277
|
'format_exception_cut_frames': (_exceptions.format_exception_cut_frames,
|
|
355
278
|
'sphinx.exceptions.format_exception_cut_frames'),
|
|
356
279
|
'xmlname_checker': (_xml_name_checker, 'sphinx.builders.epub3._XML_NAME_PATTERN'),
|
|
280
|
+
'split_index_msg': (_index_entries.split_index_msg,
|
|
281
|
+
'sphinx.util.index_entries.split_index_msg'),
|
|
282
|
+
'split_into': (_index_entries.split_index_msg, 'sphinx.util.index_entries.split_into'),
|
|
283
|
+
'md5': (_md5, ''),
|
|
284
|
+
'sha1': (_sha1, ''),
|
|
357
285
|
}
|
|
358
286
|
|
|
359
287
|
|
|
360
288
|
def __getattr__(name):
|
|
361
289
|
if name not in _DEPRECATED_OBJECTS:
|
|
362
|
-
|
|
290
|
+
msg = f'module {__name__!r} has no attribute {name!r}'
|
|
291
|
+
raise AttributeError(msg)
|
|
363
292
|
|
|
364
293
|
from sphinx.deprecation import _deprecation_warning
|
|
365
294
|
|
sphinx/util/cfamily.py
CHANGED
|
@@ -4,15 +4,18 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import re
|
|
6
6
|
from copy import deepcopy
|
|
7
|
-
from typing import Any, Callable
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Callable
|
|
8
8
|
|
|
9
9
|
from docutils import nodes
|
|
10
|
-
from docutils.nodes import TextElement
|
|
11
10
|
|
|
12
11
|
from sphinx import addnodes
|
|
13
|
-
from sphinx.config import Config
|
|
14
12
|
from sphinx.util import logging
|
|
15
13
|
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from docutils.nodes import TextElement
|
|
16
|
+
|
|
17
|
+
from sphinx.config import Config
|
|
18
|
+
|
|
16
19
|
logger = logging.getLogger(__name__)
|
|
17
20
|
|
|
18
21
|
StringifyTransform = Callable[[Any], str]
|
|
@@ -281,7 +284,7 @@ class BaseParser:
|
|
|
281
284
|
def status(self, msg: str) -> None:
|
|
282
285
|
# for debugging
|
|
283
286
|
indicator = '-' * self.pos + '^'
|
|
284
|
-
|
|
287
|
+
logger.debug(f"{msg}\n{self.definition}\n{indicator}") # NoQA: G004
|
|
285
288
|
|
|
286
289
|
def fail(self, msg: str) -> None:
|
|
287
290
|
errors = []
|
sphinx/util/display.py
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import functools
|
|
4
|
-
from typing import Any, Callable,
|
|
4
|
+
from typing import Any, Callable, TypeVar
|
|
5
5
|
|
|
6
6
|
from sphinx.locale import __
|
|
7
7
|
from sphinx.util import logging
|
|
8
|
-
from sphinx.util.console import bold # type: ignore
|
|
8
|
+
from sphinx.util.console import bold # type: ignore[attr-defined]
|
|
9
9
|
|
|
10
10
|
if False:
|
|
11
|
+
from collections.abc import Iterable, Iterator
|
|
11
12
|
from types import TracebackType
|
|
12
13
|
|
|
13
14
|
logger = logging.getLogger(__name__)
|
sphinx/util/docfields.py
CHANGED
|
@@ -6,21 +6,22 @@ be domain-specifically transformed to a more appealing presentation.
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
8
|
import contextlib
|
|
9
|
-
from typing import TYPE_CHECKING, Any,
|
|
9
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
10
10
|
|
|
11
11
|
from docutils import nodes
|
|
12
12
|
from docutils.nodes import Element, Node
|
|
13
|
-
from docutils.parsers.rst.states import Inliner
|
|
14
13
|
|
|
15
14
|
from sphinx import addnodes
|
|
16
|
-
from sphinx.environment import BuildEnvironment
|
|
17
15
|
from sphinx.locale import __
|
|
18
16
|
from sphinx.util import logging
|
|
19
17
|
from sphinx.util.nodes import get_node_line
|
|
20
|
-
from sphinx.util.typing import TextlikeNode
|
|
21
18
|
|
|
22
19
|
if TYPE_CHECKING:
|
|
20
|
+
from docutils.parsers.rst.states import Inliner
|
|
21
|
+
|
|
23
22
|
from sphinx.directives import ObjectDescription
|
|
23
|
+
from sphinx.environment import BuildEnvironment
|
|
24
|
+
from sphinx.util.typing import TextlikeNode
|
|
24
25
|
|
|
25
26
|
logger = logging.getLogger(__name__)
|
|
26
27
|
|
|
@@ -294,7 +295,7 @@ class DocFieldTransformer:
|
|
|
294
295
|
types: dict[str, dict] = {}
|
|
295
296
|
|
|
296
297
|
# step 1: traverse all fields and collect field types and content
|
|
297
|
-
for field in cast(
|
|
298
|
+
for field in cast(list[nodes.field], node):
|
|
298
299
|
assert len(field) == 2
|
|
299
300
|
field_name = cast(nodes.field_name, field[0])
|
|
300
301
|
field_body = cast(nodes.field_body, field[1])
|
|
@@ -378,7 +379,7 @@ class DocFieldTransformer:
|
|
|
378
379
|
# get one entry per field
|
|
379
380
|
if typedesc.is_grouped:
|
|
380
381
|
if typename in groupindices:
|
|
381
|
-
group = cast(
|
|
382
|
+
group = cast(tuple[Field, list, Node], entries[groupindices[typename]])
|
|
382
383
|
else:
|
|
383
384
|
groupindices[typename] = len(entries)
|
|
384
385
|
group = (typedesc, [], field)
|
sphinx/util/docstrings.py
CHANGED
|
@@ -10,7 +10,7 @@ from docutils.parsers.rst.states import Body
|
|
|
10
10
|
field_list_item_re = re.compile(Body.patterns['field_marker'])
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def separate_metadata(s: str) -> tuple[str, dict[str, str]]:
|
|
13
|
+
def separate_metadata(s: str | None) -> tuple[str | None, dict[str, str]]:
|
|
14
14
|
"""Separate docstring into metadata and others."""
|
|
15
15
|
in_other_element = False
|
|
16
16
|
metadata: dict[str, str] = {}
|
sphinx/util/docutils.py
CHANGED
|
@@ -4,17 +4,17 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
6
|
import re
|
|
7
|
+
from collections.abc import Sequence # NoQA: TCH003
|
|
7
8
|
from contextlib import contextmanager
|
|
8
9
|
from copy import copy
|
|
9
10
|
from os import path
|
|
10
|
-
from typing import IO, TYPE_CHECKING, Any, Callable,
|
|
11
|
+
from typing import IO, TYPE_CHECKING, Any, Callable, cast
|
|
11
12
|
|
|
12
13
|
import docutils
|
|
13
14
|
from docutils import nodes
|
|
14
15
|
from docutils.io import FileOutput
|
|
15
|
-
from docutils.nodes import Element, Node, system_message
|
|
16
16
|
from docutils.parsers.rst import Directive, directives, roles
|
|
17
|
-
from docutils.parsers.rst.states import Inliner
|
|
17
|
+
from docutils.parsers.rst.states import Inliner # NoQA: TCH002
|
|
18
18
|
from docutils.statemachine import State, StateMachine, StringList
|
|
19
19
|
from docutils.utils import Reporter, unescape
|
|
20
20
|
from docutils.writers._html_base import HTMLTranslator
|
|
@@ -22,19 +22,21 @@ from docutils.writers._html_base import HTMLTranslator
|
|
|
22
22
|
from sphinx.errors import SphinxError
|
|
23
23
|
from sphinx.locale import _, __
|
|
24
24
|
from sphinx.util import logging
|
|
25
|
-
from sphinx.util.typing import RoleFunction
|
|
26
25
|
|
|
27
26
|
logger = logging.getLogger(__name__)
|
|
28
27
|
report_re = re.compile('^(.+?:(?:\\d+)?): \\((DEBUG|INFO|WARNING|ERROR|SEVERE)/(\\d+)?\\) ')
|
|
29
28
|
|
|
30
29
|
if TYPE_CHECKING:
|
|
30
|
+
from collections.abc import Generator
|
|
31
31
|
from types import ModuleType
|
|
32
32
|
|
|
33
33
|
from docutils.frontend import Values
|
|
34
|
+
from docutils.nodes import Element, Node, system_message
|
|
34
35
|
|
|
35
36
|
from sphinx.builders import Builder
|
|
36
37
|
from sphinx.config import Config
|
|
37
38
|
from sphinx.environment import BuildEnvironment
|
|
39
|
+
from sphinx.util.typing import RoleFunction
|
|
38
40
|
|
|
39
41
|
# deprecated name -> (object to return, canonical path or empty string)
|
|
40
42
|
_DEPRECATED_OBJECTS = {
|
|
@@ -44,7 +46,8 @@ _DEPRECATED_OBJECTS = {
|
|
|
44
46
|
|
|
45
47
|
def __getattr__(name):
|
|
46
48
|
if name not in _DEPRECATED_OBJECTS:
|
|
47
|
-
|
|
49
|
+
msg = f'module {__name__!r} has no attribute {name!r}'
|
|
50
|
+
raise AttributeError(msg)
|
|
48
51
|
|
|
49
52
|
from sphinx.deprecation import _deprecation_warning
|
|
50
53
|
|
|
@@ -60,13 +63,13 @@ additional_nodes: set[type[Element]] = set()
|
|
|
60
63
|
def docutils_namespace() -> Generator[None, None, None]:
|
|
61
64
|
"""Create namespace for reST parsers."""
|
|
62
65
|
try:
|
|
63
|
-
_directives = copy(directives._directives) # type: ignore
|
|
64
|
-
_roles = copy(roles._roles) # type: ignore
|
|
66
|
+
_directives = copy(directives._directives) # type: ignore[attr-defined]
|
|
67
|
+
_roles = copy(roles._roles) # type: ignore[attr-defined]
|
|
65
68
|
|
|
66
69
|
yield
|
|
67
70
|
finally:
|
|
68
|
-
directives._directives = _directives # type: ignore
|
|
69
|
-
roles._roles = _roles # type: ignore
|
|
71
|
+
directives._directives = _directives # type: ignore[attr-defined]
|
|
72
|
+
roles._roles = _roles # type: ignore[attr-defined]
|
|
70
73
|
|
|
71
74
|
for node in list(additional_nodes):
|
|
72
75
|
unregister_node(node)
|
|
@@ -75,7 +78,7 @@ def docutils_namespace() -> Generator[None, None, None]:
|
|
|
75
78
|
|
|
76
79
|
def is_directive_registered(name: str) -> bool:
|
|
77
80
|
"""Check the *name* directive is already registered."""
|
|
78
|
-
return name in directives._directives # type: ignore
|
|
81
|
+
return name in directives._directives # type: ignore[attr-defined]
|
|
79
82
|
|
|
80
83
|
|
|
81
84
|
def register_directive(name: str, directive: type[Directive]) -> None:
|
|
@@ -89,7 +92,7 @@ def register_directive(name: str, directive: type[Directive]) -> None:
|
|
|
89
92
|
|
|
90
93
|
def is_role_registered(name: str) -> bool:
|
|
91
94
|
"""Check the *name* role is already registered."""
|
|
92
|
-
return name in roles._roles # type: ignore
|
|
95
|
+
return name in roles._roles # type: ignore[attr-defined]
|
|
93
96
|
|
|
94
97
|
|
|
95
98
|
def register_role(name: str, role: RoleFunction) -> None:
|
|
@@ -103,7 +106,7 @@ def register_role(name: str, role: RoleFunction) -> None:
|
|
|
103
106
|
|
|
104
107
|
def unregister_role(name: str) -> None:
|
|
105
108
|
"""Unregister a role from docutils."""
|
|
106
|
-
roles._roles.pop(name, None) # type: ignore
|
|
109
|
+
roles._roles.pop(name, None) # type: ignore[attr-defined]
|
|
107
110
|
|
|
108
111
|
|
|
109
112
|
def is_node_registered(node: type[Element]) -> bool:
|
|
@@ -118,7 +121,7 @@ def register_node(node: type[Element]) -> None:
|
|
|
118
121
|
inside ``docutils_namespace()`` to prevent side-effects.
|
|
119
122
|
"""
|
|
120
123
|
if not hasattr(nodes.GenericNodeVisitor, 'visit_' + node.__name__):
|
|
121
|
-
nodes._add_node_class_names([node.__name__]) # type: ignore
|
|
124
|
+
nodes._add_node_class_names([node.__name__]) # type: ignore[attr-defined]
|
|
122
125
|
additional_nodes.add(node)
|
|
123
126
|
|
|
124
127
|
|
|
@@ -275,7 +278,8 @@ class CustomReSTDispatcher:
|
|
|
275
278
|
def role(
|
|
276
279
|
self, role_name: str, language_module: ModuleType, lineno: int, reporter: Reporter,
|
|
277
280
|
) -> tuple[RoleFunction, list[system_message]]:
|
|
278
|
-
return self.role_func(role_name, language_module,
|
|
281
|
+
return self.role_func(role_name, language_module, # type: ignore[return-value]
|
|
282
|
+
lineno, reporter)
|
|
279
283
|
|
|
280
284
|
|
|
281
285
|
class ElementLookupError(Exception):
|
|
@@ -375,17 +379,17 @@ def switch_source_input(state: State, content: StringList) -> Generator[None, No
|
|
|
375
379
|
"""Switch current source input of state temporarily."""
|
|
376
380
|
try:
|
|
377
381
|
# remember the original ``get_source_and_line()`` method
|
|
378
|
-
|
|
382
|
+
gsal = state.memo.reporter.get_source_and_line # type: ignore[attr-defined]
|
|
379
383
|
|
|
380
384
|
# replace it by new one
|
|
381
385
|
state_machine = StateMachine([], None) # type: ignore[arg-type]
|
|
382
386
|
state_machine.input_lines = content
|
|
383
|
-
state.memo.reporter.get_source_and_line = state_machine.get_source_and_line # type: ignore # noqa: E501
|
|
387
|
+
state.memo.reporter.get_source_and_line = state_machine.get_source_and_line # type: ignore[attr-defined] # noqa: E501
|
|
384
388
|
|
|
385
389
|
yield
|
|
386
390
|
finally:
|
|
387
391
|
# restore the method
|
|
388
|
-
state.memo.reporter.get_source_and_line =
|
|
392
|
+
state.memo.reporter.get_source_and_line = gsal # type: ignore[attr-defined]
|
|
389
393
|
|
|
390
394
|
|
|
391
395
|
class SphinxFileOutput(FileOutput):
|
|
@@ -447,24 +451,26 @@ class SphinxRole:
|
|
|
447
451
|
.. note:: The subclasses of this class might not work with docutils.
|
|
448
452
|
This class is strongly coupled with Sphinx.
|
|
449
453
|
"""
|
|
450
|
-
name: str
|
|
451
|
-
rawtext: str
|
|
452
|
-
text: str
|
|
453
|
-
lineno: int
|
|
454
|
-
inliner: Inliner
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
454
|
+
name: str #: The role name actually used in the document.
|
|
455
|
+
rawtext: str #: A string containing the entire interpreted text input.
|
|
456
|
+
text: str #: The interpreted text content.
|
|
457
|
+
lineno: int #: The line number where the interpreted text begins.
|
|
458
|
+
inliner: Inliner #: The ``docutils.parsers.rst.states.Inliner`` object.
|
|
459
|
+
#: A dictionary of directive options for customisation
|
|
460
|
+
#: (from the "role" directive).
|
|
461
|
+
options: dict[str, Any]
|
|
462
|
+
#: A list of strings, the directive content for customisation
|
|
463
|
+
#: (from the "role" directive).
|
|
464
|
+
content: Sequence[str]
|
|
459
465
|
|
|
460
466
|
def __call__(self, name: str, rawtext: str, text: str, lineno: int,
|
|
461
|
-
inliner: Inliner, options: dict =
|
|
467
|
+
inliner: Inliner, options: dict | None = None, content: Sequence[str] = (),
|
|
462
468
|
) -> tuple[list[Node], list[system_message]]:
|
|
463
469
|
self.rawtext = rawtext
|
|
464
470
|
self.text = unescape(text)
|
|
465
471
|
self.lineno = lineno
|
|
466
472
|
self.inliner = inliner
|
|
467
|
-
self.options = options
|
|
473
|
+
self.options = options if options is not None else {}
|
|
468
474
|
self.content = content
|
|
469
475
|
|
|
470
476
|
# guess role type
|
|
@@ -475,7 +481,8 @@ class SphinxRole:
|
|
|
475
481
|
if not self.name:
|
|
476
482
|
self.name = self.env.config.default_role
|
|
477
483
|
if not self.name:
|
|
478
|
-
|
|
484
|
+
msg = 'cannot determine default role!'
|
|
485
|
+
raise SphinxError(msg)
|
|
479
486
|
|
|
480
487
|
return self.run()
|
|
481
488
|
|
|
@@ -495,7 +502,7 @@ class SphinxRole:
|
|
|
495
502
|
def get_source_info(self, lineno: int | None = None) -> tuple[str, int]:
|
|
496
503
|
if lineno is None:
|
|
497
504
|
lineno = self.lineno
|
|
498
|
-
return self.inliner.reporter.get_source_and_line(lineno) # type: ignore
|
|
505
|
+
return self.inliner.reporter.get_source_and_line(lineno) # type: ignore[attr-defined]
|
|
499
506
|
|
|
500
507
|
def set_source_info(self, node: Node, lineno: int | None = None) -> None:
|
|
501
508
|
node.source, node.line = self.get_source_info(lineno)
|
|
@@ -521,8 +528,11 @@ class ReferenceRole(SphinxRole):
|
|
|
521
528
|
explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<(.*?)>$', re.DOTALL)
|
|
522
529
|
|
|
523
530
|
def __call__(self, name: str, rawtext: str, text: str, lineno: int,
|
|
524
|
-
inliner: Inliner, options: dict =
|
|
531
|
+
inliner: Inliner, options: dict | None = None, content: Sequence[str] = (),
|
|
525
532
|
) -> tuple[list[Node], list[system_message]]:
|
|
533
|
+
if options is None:
|
|
534
|
+
options = {}
|
|
535
|
+
|
|
526
536
|
# if the first character is a bang, don't cross-reference at all
|
|
527
537
|
self.disabled = text.startswith('!')
|
|
528
538
|
|
sphinx/util/fileutil.py
CHANGED
|
@@ -9,13 +9,13 @@ from typing import TYPE_CHECKING, Callable
|
|
|
9
9
|
from docutils.utils import relative_path
|
|
10
10
|
|
|
11
11
|
from sphinx.util.osutil import copyfile, ensuredir
|
|
12
|
-
from sphinx.util.typing import PathMatcher
|
|
13
12
|
|
|
14
13
|
if TYPE_CHECKING:
|
|
15
14
|
from sphinx.util.template import BaseRenderer
|
|
15
|
+
from sphinx.util.typing import PathMatcher
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def copy_asset_file(source: str, destination: str,
|
|
18
|
+
def copy_asset_file(source: str | os.PathLike[str], destination: str | os.PathLike[str],
|
|
19
19
|
context: dict | None = None,
|
|
20
20
|
renderer: BaseRenderer | None = None) -> None:
|
|
21
21
|
"""Copy an asset file to destination.
|
|
@@ -34,14 +34,16 @@ def copy_asset_file(source: str, destination: str,
|
|
|
34
34
|
if os.path.isdir(destination):
|
|
35
35
|
# Use source filename if destination points a directory
|
|
36
36
|
destination = os.path.join(destination, os.path.basename(source))
|
|
37
|
+
else:
|
|
38
|
+
destination = str(destination)
|
|
37
39
|
|
|
38
|
-
if
|
|
40
|
+
if os.path.basename(source).endswith(('_t', '_T')) and context is not None:
|
|
39
41
|
if renderer is None:
|
|
40
42
|
from sphinx.util.template import SphinxRenderer
|
|
41
43
|
renderer = SphinxRenderer()
|
|
42
44
|
|
|
43
45
|
with open(source, encoding='utf-8') as fsrc:
|
|
44
|
-
if destination.
|
|
46
|
+
if destination.endswith(('_t', '_T')):
|
|
45
47
|
destination = destination[:-2]
|
|
46
48
|
with open(destination, 'w', encoding='utf-8') as fdst:
|
|
47
49
|
fdst.write(renderer.render_string(fsrc.read(), context))
|
|
@@ -49,7 +51,8 @@ def copy_asset_file(source: str, destination: str,
|
|
|
49
51
|
copyfile(source, destination)
|
|
50
52
|
|
|
51
53
|
|
|
52
|
-
def copy_asset(source: str
|
|
54
|
+
def copy_asset(source: str | os.PathLike[str], destination: str | os.PathLike[str],
|
|
55
|
+
excluded: PathMatcher = lambda path: False,
|
|
53
56
|
context: dict | None = None, renderer: BaseRenderer | None = None,
|
|
54
57
|
onerror: Callable[[str, Exception], None] | None = None) -> None:
|
|
55
58
|
"""Copy asset files to destination recursively.
|
|
@@ -77,7 +80,7 @@ def copy_asset(source: str, destination: str, excluded: PathMatcher = lambda pat
|
|
|
77
80
|
return
|
|
78
81
|
|
|
79
82
|
for root, dirs, files in os.walk(source, followlinks=True):
|
|
80
|
-
reldir = relative_path(source, root)
|
|
83
|
+
reldir = relative_path(source, root) # type: ignore[arg-type]
|
|
81
84
|
for dir in dirs[:]:
|
|
82
85
|
if excluded(posixpath.join(reldir, dir)):
|
|
83
86
|
dirs.remove(dir)
|