Sphinx 7.4.6__py3-none-any.whl → 8.0.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 +2 -2
- sphinx/_cli/__init__.py +4 -4
- sphinx/application.py +2 -2
- sphinx/builders/__init__.py +2 -3
- sphinx/builders/_epub_base.py +33 -12
- sphinx/builders/changes.py +13 -5
- sphinx/builders/epub3.py +6 -2
- sphinx/builders/html/__init__.py +90 -59
- sphinx/builders/latex/__init__.py +38 -12
- sphinx/builders/latex/transforms.py +1 -1
- sphinx/builders/linkcheck.py +8 -49
- sphinx/builders/texinfo.py +12 -6
- sphinx/builders/text.py +7 -3
- sphinx/builders/xml.py +7 -3
- sphinx/cmd/quickstart.py +10 -20
- sphinx/config.py +13 -13
- sphinx/deprecation.py +8 -8
- sphinx/directives/__init__.py +14 -9
- sphinx/directives/other.py +2 -3
- sphinx/directives/patches.py +2 -2
- sphinx/domains/__init__.py +4 -2
- sphinx/domains/c/__init__.py +2 -2
- sphinx/domains/c/_ast.py +3 -2
- sphinx/domains/c/_parser.py +4 -3
- sphinx/domains/cpp/__init__.py +2 -2
- sphinx/domains/cpp/_ast.py +1 -2
- sphinx/domains/cpp/_parser.py +2 -2
- sphinx/domains/cpp/_symbol.py +2 -2
- sphinx/domains/javascript.py +1 -1
- sphinx/domains/math.py +1 -1
- sphinx/domains/python/__init__.py +1 -1
- sphinx/domains/python/_annotations.py +23 -1
- sphinx/domains/python/_object.py +0 -1
- sphinx/domains/std/__init__.py +7 -8
- sphinx/environment/__init__.py +15 -32
- sphinx/environment/adapters/indexentries.py +4 -6
- sphinx/environment/adapters/toctree.py +4 -4
- sphinx/environment/collectors/title.py +1 -1
- sphinx/environment/collectors/toctree.py +1 -1
- sphinx/events.py +3 -1
- sphinx/ext/autodoc/__init__.py +25 -67
- sphinx/ext/autodoc/directive.py +7 -5
- sphinx/ext/autodoc/importer.py +2 -1
- sphinx/ext/autodoc/preserve_defaults.py +2 -2
- sphinx/ext/autosummary/__init__.py +15 -7
- sphinx/ext/autosummary/generate.py +5 -4
- sphinx/ext/doctest.py +5 -5
- sphinx/ext/graphviz.py +1 -1
- sphinx/ext/imgmath.py +1 -1
- sphinx/ext/inheritance_diagram.py +1 -1
- sphinx/ext/intersphinx/__init__.py +25 -5
- sphinx/ext/intersphinx/_cli.py +7 -6
- sphinx/ext/intersphinx/_load.py +240 -115
- sphinx/ext/intersphinx/_resolve.py +12 -11
- sphinx/ext/intersphinx/_shared.py +102 -9
- sphinx/ext/mathjax.py +1 -1
- sphinx/ext/napoleon/docstring.py +2 -2
- sphinx/ext/todo.py +2 -2
- sphinx/ext/viewcode.py +2 -1
- sphinx/highlighting.py +3 -3
- sphinx/io.py +2 -2
- sphinx/jinja2glue.py +13 -6
- sphinx/locale/__init__.py +4 -3
- sphinx/locale/ar/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ar/LC_MESSAGES/sphinx.po +2383 -2186
- sphinx/locale/bg/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bg/LC_MESSAGES/sphinx.po +2249 -2052
- sphinx/locale/bn/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/bn/LC_MESSAGES/sphinx.po +2412 -2215
- sphinx/locale/ca/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ca/LC_MESSAGES/sphinx.po +3029 -2832
- sphinx/locale/cak/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cak/LC_MESSAGES/sphinx.po +2308 -2111
- sphinx/locale/cs/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cs/LC_MESSAGES/sphinx.po +2469 -2272
- sphinx/locale/cy/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/cy/LC_MESSAGES/sphinx.po +2393 -2196
- sphinx/locale/da/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/da/LC_MESSAGES/sphinx.po +2532 -2335
- sphinx/locale/de/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de/LC_MESSAGES/sphinx.po +2492 -2295
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/de_DE/LC_MESSAGES/sphinx.po +2250 -2053
- sphinx/locale/el/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/el/LC_MESSAGES/sphinx.po +2879 -2682
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_DE/LC_MESSAGES/sphinx.po +2250 -2053
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_FR/LC_MESSAGES/sphinx.po +2250 -2053
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_GB/LC_MESSAGES/sphinx.po +2989 -2792
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/en_HK/LC_MESSAGES/sphinx.po +2250 -2053
- sphinx/locale/eo/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eo/LC_MESSAGES/sphinx.po +2297 -2100
- sphinx/locale/es/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es/LC_MESSAGES/sphinx.po +3017 -2820
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/es_CO/LC_MESSAGES/sphinx.po +2250 -2053
- sphinx/locale/et/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/et/LC_MESSAGES/sphinx.po +2748 -2551
- sphinx/locale/eu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/eu/LC_MESSAGES/sphinx.po +2459 -2262
- sphinx/locale/fa/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fa/LC_MESSAGES/sphinx.po +2957 -2760
- sphinx/locale/fi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fi/LC_MESSAGES/sphinx.po +2321 -2124
- sphinx/locale/fr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr/LC_MESSAGES/sphinx.po +2977 -2780
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/fr_FR/LC_MESSAGES/sphinx.po +2250 -2053
- sphinx/locale/gl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/gl/LC_MESSAGES/sphinx.po +2992 -2795
- sphinx/locale/he/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/he/LC_MESSAGES/sphinx.po +2375 -2178
- sphinx/locale/hi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi/LC_MESSAGES/sphinx.po +2937 -2740
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hi_IN/LC_MESSAGES/sphinx.po +2250 -2053
- sphinx/locale/hr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hr/LC_MESSAGES/sphinx.po +2532 -2335
- sphinx/locale/hu/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/hu/LC_MESSAGES/sphinx.po +2505 -2308
- sphinx/locale/id/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/id/LC_MESSAGES/sphinx.po +2925 -2728
- sphinx/locale/is/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/is/LC_MESSAGES/sphinx.po +2307 -2110
- sphinx/locale/it/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/it/LC_MESSAGES/sphinx.po +2514 -2317
- sphinx/locale/ja/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ja/LC_MESSAGES/sphinx.po +2970 -2773
- sphinx/locale/ka/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ka/LC_MESSAGES/sphinx.po +2868 -2671
- sphinx/locale/ko/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ko/LC_MESSAGES/sphinx.po +3016 -2819
- sphinx/locale/lt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lt/LC_MESSAGES/sphinx.po +2476 -2279
- sphinx/locale/lv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/lv/LC_MESSAGES/sphinx.po +2477 -2280
- sphinx/locale/mk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/mk/LC_MESSAGES/sphinx.po +2292 -2095
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nb_NO/LC_MESSAGES/sphinx.po +2479 -2282
- sphinx/locale/ne/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ne/LC_MESSAGES/sphinx.po +2481 -2284
- sphinx/locale/nl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/nl/LC_MESSAGES/sphinx.po +2557 -2360
- sphinx/locale/pl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pl/LC_MESSAGES/sphinx.po +2696 -2499
- sphinx/locale/pt/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt/LC_MESSAGES/sphinx.po +2250 -2053
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_BR/LC_MESSAGES/sphinx.po +2979 -2782
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/pt_PT/LC_MESSAGES/sphinx.po +2469 -2272
- sphinx/locale/ro/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ro/LC_MESSAGES/sphinx.po +2473 -2276
- sphinx/locale/ru/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ru/LC_MESSAGES/sphinx.po +2746 -2549
- sphinx/locale/si/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/si/LC_MESSAGES/sphinx.po +2331 -2134
- sphinx/locale/sk/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sk/LC_MESSAGES/sphinx.po +2966 -2769
- sphinx/locale/sl/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sl/LC_MESSAGES/sphinx.po +2404 -2207
- sphinx/locale/sphinx.pot +2262 -2065
- sphinx/locale/sq/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sq/LC_MESSAGES/sphinx.po +2972 -2775
- sphinx/locale/sr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sr/LC_MESSAGES/sphinx.po +2440 -2243
- sphinx/locale/sv/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/sv/LC_MESSAGES/sphinx.po +2483 -2286
- sphinx/locale/ta/LC_MESSAGES/sphinx.js +54 -54
- sphinx/locale/ta/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ta/LC_MESSAGES/sphinx.po +1578 -1843
- sphinx/locale/te/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/te/LC_MESSAGES/sphinx.po +2250 -2053
- sphinx/locale/tr/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/tr/LC_MESSAGES/sphinx.po +2892 -2695
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/uk_UA/LC_MESSAGES/sphinx.po +2400 -2203
- sphinx/locale/ur/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/ur/LC_MESSAGES/sphinx.po +2250 -2053
- sphinx/locale/vi/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/vi/LC_MESSAGES/sphinx.po +2422 -2225
- sphinx/locale/yue/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/yue/LC_MESSAGES/sphinx.po +2250 -2053
- sphinx/locale/zh_CN/LC_MESSAGES/sphinx.po +496 -704
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_HK/LC_MESSAGES/sphinx.po +2250 -2053
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW/LC_MESSAGES/sphinx.po +3028 -2831
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.mo +0 -0
- sphinx/locale/zh_TW.Big5/LC_MESSAGES/sphinx.po +2250 -2053
- sphinx/project.py +25 -20
- sphinx/pycode/ast.py +2 -2
- sphinx/pycode/parser.py +2 -2
- sphinx/pygments_styles.py +3 -3
- sphinx/registry.py +3 -8
- sphinx/search/__init__.py +1 -1
- sphinx/testing/path.py +2 -1
- sphinx/testing/util.py +1 -1
- sphinx/texinputs/Makefile.jinja +2 -1
- sphinx/texinputs_win/Makefile.jinja +2 -1
- sphinx/theming.py +3 -12
- sphinx/transforms/__init__.py +5 -5
- sphinx/transforms/references.py +1 -1
- sphinx/util/__init__.py +11 -35
- sphinx/util/_pathlib.py +31 -19
- sphinx/util/_timestamps.py +12 -0
- sphinx/util/cfamily.py +5 -5
- sphinx/util/console.py +4 -3
- sphinx/util/display.py +3 -3
- sphinx/util/docfields.py +1 -1
- sphinx/util/docutils.py +44 -10
- sphinx/util/fileutil.py +41 -9
- sphinx/util/i18n.py +9 -4
- sphinx/util/images.py +3 -2
- sphinx/util/inspect.py +29 -44
- sphinx/util/inventory.py +2 -2
- sphinx/util/matching.py +2 -2
- sphinx/util/math.py +1 -1
- sphinx/util/nodes.py +8 -8
- sphinx/util/osutil.py +52 -26
- sphinx/util/parallel.py +2 -2
- sphinx/util/requests.py +1 -1
- sphinx/util/template.py +3 -3
- sphinx/util/typing.py +67 -70
- sphinx/writers/html.py +1 -1
- sphinx/writers/html5.py +1 -1
- sphinx/writers/latex.py +4 -4
- sphinx/writers/manpage.py +2 -2
- sphinx/writers/texinfo.py +5 -5
- sphinx/writers/text.py +4 -4
- sphinx/writers/xml.py +2 -2
- {sphinx-7.4.6.dist-info → sphinx-8.0.0.dist-info}/METADATA +11 -10
- {sphinx-7.4.6.dist-info → sphinx-8.0.0.dist-info}/RECORD +240 -241
- sphinx/templates/quickstart/Makefile.jinja +0 -98
- sphinx/templates/quickstart/make.bat.jinja +0 -110
- {sphinx-7.4.6.dist-info → sphinx-8.0.0.dist-info}/LICENSE.rst +0 -0
- {sphinx-7.4.6.dist-info → sphinx-8.0.0.dist-info}/WHEEL +0 -0
- {sphinx-7.4.6.dist-info → sphinx-8.0.0.dist-info}/entry_points.txt +0 -0
sphinx/project.py
CHANGED
|
@@ -4,13 +4,14 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import contextlib
|
|
6
6
|
import os
|
|
7
|
-
from
|
|
7
|
+
from pathlib import Path
|
|
8
8
|
from typing import TYPE_CHECKING
|
|
9
9
|
|
|
10
10
|
from sphinx.locale import __
|
|
11
11
|
from sphinx.util import logging
|
|
12
|
+
from sphinx.util._pathlib import _StrPath
|
|
12
13
|
from sphinx.util.matching import get_matching_files
|
|
13
|
-
from sphinx.util.osutil import path_stabilize
|
|
14
|
+
from sphinx.util.osutil import path_stabilize
|
|
14
15
|
|
|
15
16
|
if TYPE_CHECKING:
|
|
16
17
|
from collections.abc import Iterable
|
|
@@ -24,7 +25,7 @@ class Project:
|
|
|
24
25
|
|
|
25
26
|
def __init__(self, srcdir: str | os.PathLike[str], source_suffix: Iterable[str]) -> None:
|
|
26
27
|
#: Source directory.
|
|
27
|
-
self.srcdir = srcdir
|
|
28
|
+
self.srcdir = _StrPath(srcdir)
|
|
28
29
|
|
|
29
30
|
#: source_suffix. Same as :confval:`source_suffix`.
|
|
30
31
|
self.source_suffix = tuple(source_suffix)
|
|
@@ -34,8 +35,8 @@ class Project:
|
|
|
34
35
|
self.docnames: set[str] = set()
|
|
35
36
|
|
|
36
37
|
# Bijective mapping between docnames and (srcdir relative) paths.
|
|
37
|
-
self._path_to_docname: dict[
|
|
38
|
-
self._docname_to_path: dict[str,
|
|
38
|
+
self._path_to_docname: dict[Path, str] = {}
|
|
39
|
+
self._docname_to_path: dict[str, Path] = {}
|
|
39
40
|
|
|
40
41
|
def restore(self, other: Project) -> None:
|
|
41
42
|
"""Take over a result of last build."""
|
|
@@ -60,22 +61,25 @@ class Project:
|
|
|
60
61
|
):
|
|
61
62
|
if docname := self.path2doc(filename):
|
|
62
63
|
if docname in self.docnames:
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
files = [
|
|
65
|
+
str(f.relative_to(self.srcdir))
|
|
66
|
+
for f in self.srcdir.glob(f'{docname}.*')
|
|
67
|
+
]
|
|
65
68
|
logger.warning(
|
|
66
69
|
__(
|
|
67
|
-
'multiple files found for the document "%s": %
|
|
70
|
+
'multiple files found for the document "%s": %s\n'
|
|
68
71
|
'Use %r for the build.'
|
|
69
72
|
),
|
|
70
73
|
docname,
|
|
71
|
-
files,
|
|
74
|
+
', '.join(files),
|
|
72
75
|
self.doc2path(docname, absolute=True),
|
|
73
76
|
once=True,
|
|
74
77
|
)
|
|
75
|
-
elif os.access(
|
|
78
|
+
elif os.access(self.srcdir / filename, os.R_OK):
|
|
76
79
|
self.docnames.add(docname)
|
|
77
|
-
|
|
78
|
-
self.
|
|
80
|
+
path = Path(filename)
|
|
81
|
+
self._path_to_docname[path] = docname
|
|
82
|
+
self._docname_to_path[docname] = path
|
|
79
83
|
else:
|
|
80
84
|
logger.warning(
|
|
81
85
|
__('Ignored unreadable document %r.'), filename, location=docname
|
|
@@ -91,18 +95,19 @@ class Project:
|
|
|
91
95
|
try:
|
|
92
96
|
return self._path_to_docname[filename] # type: ignore[index]
|
|
93
97
|
except KeyError:
|
|
94
|
-
|
|
98
|
+
path = Path(filename)
|
|
99
|
+
if path.is_absolute():
|
|
95
100
|
with contextlib.suppress(ValueError):
|
|
96
|
-
|
|
101
|
+
path = path.relative_to(self.srcdir)
|
|
97
102
|
|
|
98
103
|
for suffix in self.source_suffix:
|
|
99
|
-
if
|
|
100
|
-
return path_stabilize(
|
|
104
|
+
if path.name.endswith(suffix):
|
|
105
|
+
return path_stabilize(path).removesuffix(suffix)
|
|
101
106
|
|
|
102
107
|
# the file does not have a docname
|
|
103
108
|
return None
|
|
104
109
|
|
|
105
|
-
def doc2path(self, docname: str, absolute: bool) ->
|
|
110
|
+
def doc2path(self, docname: str, absolute: bool) -> _StrPath:
|
|
106
111
|
"""Return the filename for the document name.
|
|
107
112
|
|
|
108
113
|
If *absolute* is True, return as an absolute path.
|
|
@@ -112,8 +117,8 @@ class Project:
|
|
|
112
117
|
filename = self._docname_to_path[docname]
|
|
113
118
|
except KeyError:
|
|
114
119
|
# Backwards compatibility: the document does not exist
|
|
115
|
-
filename = docname + self._first_source_suffix
|
|
120
|
+
filename = Path(docname + self._first_source_suffix)
|
|
116
121
|
|
|
117
122
|
if absolute:
|
|
118
|
-
return
|
|
119
|
-
return filename
|
|
123
|
+
return _StrPath(self.srcdir / filename)
|
|
124
|
+
return _StrPath(filename)
|
sphinx/pycode/ast.py
CHANGED
|
@@ -130,7 +130,7 @@ class _UnparseVisitor(ast.NodeVisitor):
|
|
|
130
130
|
def visit_Constant(self, node: ast.Constant) -> str:
|
|
131
131
|
if node.value is Ellipsis:
|
|
132
132
|
return "..."
|
|
133
|
-
elif isinstance(node.value,
|
|
133
|
+
elif isinstance(node.value, int | float | complex):
|
|
134
134
|
if self.code:
|
|
135
135
|
return ast.get_source_segment(self.code, node) or repr(node.value)
|
|
136
136
|
else:
|
|
@@ -141,7 +141,7 @@ class _UnparseVisitor(ast.NodeVisitor):
|
|
|
141
141
|
def visit_Dict(self, node: ast.Dict) -> str:
|
|
142
142
|
keys = (self.visit(k) for k in node.keys if k is not None)
|
|
143
143
|
values = (self.visit(v) for v in node.values)
|
|
144
|
-
items = (k + ": " + v for k, v in zip(keys, values))
|
|
144
|
+
items = (k + ": " + v for k, v in zip(keys, values, strict=True))
|
|
145
145
|
return "{" + ", ".join(items) + "}"
|
|
146
146
|
|
|
147
147
|
def visit_Lambda(self, node: ast.Lambda) -> str:
|
sphinx/pycode/parser.py
CHANGED
|
@@ -108,7 +108,7 @@ class Token:
|
|
|
108
108
|
return self.kind == other
|
|
109
109
|
elif isinstance(other, str):
|
|
110
110
|
return self.value == other
|
|
111
|
-
elif isinstance(other,
|
|
111
|
+
elif isinstance(other, list | tuple):
|
|
112
112
|
return [self.kind, self.value] == list(other)
|
|
113
113
|
elif other is None:
|
|
114
114
|
return False
|
|
@@ -404,7 +404,7 @@ class VariableCommentPicker(ast.NodeVisitor):
|
|
|
404
404
|
|
|
405
405
|
def visit_Expr(self, node: ast.Expr) -> None:
|
|
406
406
|
"""Handles Expr node and pick up a comment if string."""
|
|
407
|
-
if (isinstance(self.previous,
|
|
407
|
+
if (isinstance(self.previous, ast.Assign | ast.AnnAssign) and
|
|
408
408
|
isinstance(node.value, ast.Constant) and isinstance(node.value.value, str)):
|
|
409
409
|
try:
|
|
410
410
|
targets = get_assign_targets(self.previous)
|
sphinx/pygments_styles.py
CHANGED
|
@@ -28,12 +28,12 @@ class SphinxStyle(Style):
|
|
|
28
28
|
background_color = '#eeffcc'
|
|
29
29
|
default_style = ''
|
|
30
30
|
|
|
31
|
-
styles =
|
|
32
|
-
|
|
31
|
+
styles = {
|
|
32
|
+
**FriendlyStyle.styles,
|
|
33
33
|
Generic.Output: '#333',
|
|
34
34
|
Comment: 'italic #408090',
|
|
35
35
|
Number: '#208050',
|
|
36
|
-
}
|
|
36
|
+
}
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
class PyramidStyle(Style):
|
sphinx/registry.py
CHANGED
|
@@ -2,16 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import sys
|
|
6
5
|
import traceback
|
|
7
6
|
from importlib import import_module
|
|
7
|
+
from importlib.metadata import entry_points
|
|
8
8
|
from types import MethodType
|
|
9
|
-
from typing import TYPE_CHECKING, Any
|
|
10
|
-
|
|
11
|
-
if sys.version_info >= (3, 10):
|
|
12
|
-
from importlib.metadata import entry_points
|
|
13
|
-
else:
|
|
14
|
-
from importlib_metadata import entry_points
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
15
10
|
|
|
16
11
|
from sphinx.domains import Domain, Index, ObjType
|
|
17
12
|
from sphinx.domains.std import GenericObject, Target
|
|
@@ -25,7 +20,7 @@ from sphinx.util import logging
|
|
|
25
20
|
from sphinx.util.logging import prefixed_warnings
|
|
26
21
|
|
|
27
22
|
if TYPE_CHECKING:
|
|
28
|
-
from collections.abc import Iterator, Sequence
|
|
23
|
+
from collections.abc import Callable, Iterator, Sequence
|
|
29
24
|
|
|
30
25
|
from docutils import nodes
|
|
31
26
|
from docutils.core import Publisher
|
sphinx/search/__init__.py
CHANGED
|
@@ -487,7 +487,7 @@ class IndexBuilder:
|
|
|
487
487
|
self._index_entries[docname] = sorted(_index_entries)
|
|
488
488
|
|
|
489
489
|
def _word_collector(self, doctree: nodes.document) -> WordStore:
|
|
490
|
-
def _visit_nodes(node):
|
|
490
|
+
def _visit_nodes(node: nodes.Node) -> None:
|
|
491
491
|
if isinstance(node, nodes.comment):
|
|
492
492
|
return
|
|
493
493
|
elif isinstance(node, nodes.raw):
|
sphinx/testing/path.py
CHANGED
|
@@ -4,12 +4,13 @@ import os
|
|
|
4
4
|
import shutil
|
|
5
5
|
import sys
|
|
6
6
|
import warnings
|
|
7
|
-
from typing import IO, TYPE_CHECKING, Any
|
|
7
|
+
from typing import IO, TYPE_CHECKING, Any
|
|
8
8
|
|
|
9
9
|
from sphinx.deprecation import RemovedInSphinx90Warning
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
12
|
import builtins
|
|
13
|
+
from collections.abc import Callable
|
|
13
14
|
|
|
14
15
|
warnings.warn("'sphinx.testing.path' is deprecated. "
|
|
15
16
|
"Use 'os.path' or 'pathlib' instead.",
|
sphinx/testing/util.py
CHANGED
|
@@ -43,7 +43,7 @@ def assert_node(node: Node, cls: Any = None, xpath: str = "", **kwargs: Any) ->
|
|
|
43
43
|
'The node%s has %d child nodes, not one' % (xpath, len(node))
|
|
44
44
|
assert_node(node[0], cls[1:], xpath=xpath + "[0]", **kwargs)
|
|
45
45
|
elif isinstance(cls, tuple):
|
|
46
|
-
assert isinstance(node,
|
|
46
|
+
assert isinstance(node, list | nodes.Element), \
|
|
47
47
|
'The node%s does not have any items' % xpath
|
|
48
48
|
assert len(node) == len(cls), \
|
|
49
49
|
'The node%s has %d child nodes, not %r' % (xpath, len(node), len(cls))
|
sphinx/texinputs/Makefile.jinja
CHANGED
|
@@ -77,7 +77,8 @@ tar: all-$(FMT)
|
|
|
77
77
|
rm -r $(ARCHIVEPREFIX)docs-$(FMT)
|
|
78
78
|
|
|
79
79
|
gz: tar
|
|
80
|
-
|
|
80
|
+
# -n to omit mtime from gzip headers
|
|
81
|
+
gzip -n -9 < $(ARCHIVEPREFIX)docs-$(FMT).tar > $(ARCHIVEPREFIX)docs-$(FMT).tar.gz
|
|
81
82
|
|
|
82
83
|
bz2: tar
|
|
83
84
|
bzip2 -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar
|
|
@@ -49,7 +49,8 @@ tar: all-$(FMT)
|
|
|
49
49
|
rm -r $(ARCHIVEPREFIX)docs-$(FMT)
|
|
50
50
|
|
|
51
51
|
gz: tar
|
|
52
|
-
|
|
52
|
+
# -n to omit mtime from gzip headers
|
|
53
|
+
gzip -n -9 < $(ARCHIVEPREFIX)docs-$(FMT).tar > $(ARCHIVEPREFIX)docs-$(FMT).tar.gz
|
|
53
54
|
|
|
54
55
|
bz2: tar
|
|
55
56
|
bzip2 -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar
|
sphinx/theming.py
CHANGED
|
@@ -10,6 +10,7 @@ import os
|
|
|
10
10
|
import shutil
|
|
11
11
|
import sys
|
|
12
12
|
import tempfile
|
|
13
|
+
from importlib.metadata import entry_points
|
|
13
14
|
from os import path
|
|
14
15
|
from typing import TYPE_CHECKING, Any
|
|
15
16
|
from zipfile import ZipFile
|
|
@@ -26,10 +27,6 @@ if sys.version_info >= (3, 11):
|
|
|
26
27
|
else:
|
|
27
28
|
import tomli as tomllib
|
|
28
29
|
|
|
29
|
-
if sys.version_info >= (3, 10):
|
|
30
|
-
from importlib.metadata import entry_points
|
|
31
|
-
else:
|
|
32
|
-
from importlib_metadata import entry_points
|
|
33
30
|
|
|
34
31
|
if TYPE_CHECKING:
|
|
35
32
|
from collections.abc import Callable
|
|
@@ -121,17 +118,11 @@ class Theme:
|
|
|
121
118
|
elif section == 'options':
|
|
122
119
|
value = self._options.get(name, default)
|
|
123
120
|
else:
|
|
124
|
-
# https://github.com/sphinx-doc/sphinx/issues/12305
|
|
125
|
-
# For backwards compatibility when attempting to read a value
|
|
126
|
-
# from an unsupported configuration section.
|
|
127
|
-
# xref: RemovedInSphinx80Warning
|
|
128
121
|
msg = __(
|
|
129
122
|
'Theme configuration sections other than [theme] and [options] '
|
|
130
|
-
'are not supported
|
|
131
|
-
'(tried to get a value from %r)'
|
|
123
|
+
'are not supported (tried to get a value from %r).'
|
|
132
124
|
)
|
|
133
|
-
|
|
134
|
-
value = default
|
|
125
|
+
raise ThemeError(msg)
|
|
135
126
|
if value is _NO_DEFAULT:
|
|
136
127
|
msg = __('setting %s.%s occurs in none of the searched theme configs') % (
|
|
137
128
|
section,
|
sphinx/transforms/__init__.py
CHANGED
|
@@ -22,10 +22,10 @@ from sphinx.util.nodes import apply_source_workaround, is_smartquotable
|
|
|
22
22
|
|
|
23
23
|
if TYPE_CHECKING:
|
|
24
24
|
from collections.abc import Iterator
|
|
25
|
-
from typing import Literal
|
|
25
|
+
from typing import Literal, TypeAlias
|
|
26
26
|
|
|
27
27
|
from docutils.nodes import Node, Text
|
|
28
|
-
from typing_extensions import
|
|
28
|
+
from typing_extensions import TypeIs
|
|
29
29
|
|
|
30
30
|
from sphinx.application import Sphinx
|
|
31
31
|
from sphinx.config import Config
|
|
@@ -247,7 +247,7 @@ class ApplySourceWorkaround(SphinxTransform):
|
|
|
247
247
|
|
|
248
248
|
def apply(self, **kwargs: Any) -> None:
|
|
249
249
|
for node in self.document.findall(): # type: Node
|
|
250
|
-
if isinstance(node,
|
|
250
|
+
if isinstance(node, nodes.TextElement | nodes.image | nodes.topic):
|
|
251
251
|
apply_source_workaround(node)
|
|
252
252
|
|
|
253
253
|
|
|
@@ -364,7 +364,7 @@ class SphinxSmartQuotes(SmartQuotes, SphinxTransform):
|
|
|
364
364
|
# override default settings with :confval:`smartquotes_action`
|
|
365
365
|
self.smartquotes_action = self.config.smartquotes_action
|
|
366
366
|
|
|
367
|
-
super().apply()
|
|
367
|
+
super().apply() # type: ignore[no-untyped-call]
|
|
368
368
|
|
|
369
369
|
def is_available(self) -> bool:
|
|
370
370
|
builders = self.config.smartquotes_excludes.get('builders', [])
|
|
@@ -477,7 +477,7 @@ def _reorder_index_target_nodes(start_node: nodes.target) -> None:
|
|
|
477
477
|
# as we want *consecutive* target & index nodes.
|
|
478
478
|
node: nodes.Node
|
|
479
479
|
for node in start_node.findall(descend=False, siblings=True):
|
|
480
|
-
if isinstance(node,
|
|
480
|
+
if isinstance(node, nodes.target | addnodes.index):
|
|
481
481
|
nodes_to_reorder.append(node)
|
|
482
482
|
continue
|
|
483
483
|
break # must be a consecutive run of target or index nodes
|
sphinx/transforms/references.py
CHANGED
|
@@ -23,7 +23,7 @@ class SphinxDanglingReferences(DanglingReferences):
|
|
|
23
23
|
|
|
24
24
|
# suppress INFO level messages for a while
|
|
25
25
|
reporter.report_level = max(reporter.WARNING_LEVEL, reporter.report_level)
|
|
26
|
-
super().apply()
|
|
26
|
+
super().apply() # type: ignore[no-untyped-call]
|
|
27
27
|
finally:
|
|
28
28
|
reporter.report_level = report_level
|
|
29
29
|
|
sphinx/util/__init__.py
CHANGED
|
@@ -13,12 +13,8 @@ from urllib.parse import parse_qsl, quote_plus, urlencode, urlsplit, urlunsplit
|
|
|
13
13
|
|
|
14
14
|
from sphinx.errors import ExtensionError, FiletypeNotFoundError
|
|
15
15
|
from sphinx.locale import __
|
|
16
|
-
from sphinx.util import display as _display
|
|
17
|
-
from sphinx.util import exceptions as _exceptions
|
|
18
|
-
from sphinx.util import http_date as _http_date
|
|
19
16
|
from sphinx.util import index_entries as _index_entries
|
|
20
17
|
from sphinx.util import logging
|
|
21
|
-
from sphinx.util import osutil as _osutil
|
|
22
18
|
from sphinx.util.console import strip_colors # NoQA: F401
|
|
23
19
|
from sphinx.util.matching import patfilter # NoQA: F401
|
|
24
20
|
from sphinx.util.nodes import ( # NoQA: F401
|
|
@@ -33,10 +29,8 @@ from sphinx.util.nodes import ( # NoQA: F401
|
|
|
33
29
|
from sphinx.util.osutil import ( # NoQA: F401
|
|
34
30
|
SEP,
|
|
35
31
|
copyfile,
|
|
36
|
-
copytimes,
|
|
37
32
|
ensuredir,
|
|
38
33
|
make_filename,
|
|
39
|
-
mtimes_of_files,
|
|
40
34
|
os_path,
|
|
41
35
|
relative_uri,
|
|
42
36
|
)
|
|
@@ -54,9 +48,9 @@ def docname_join(basedocname: str, docname: str) -> str:
|
|
|
54
48
|
return posixpath.normpath(posixpath.join('/' + basedocname, '..', docname))[1:]
|
|
55
49
|
|
|
56
50
|
|
|
57
|
-
def get_filetype(source_suffix: dict[str, str], filename: str) -> str:
|
|
51
|
+
def get_filetype(source_suffix: dict[str, str], filename: str | os.PathLike) -> str:
|
|
58
52
|
for suffix, filetype in source_suffix.items():
|
|
59
|
-
if filename.endswith(suffix):
|
|
53
|
+
if os.fspath(filename).endswith(suffix):
|
|
60
54
|
# If default filetype (None), considered as restructuredtext.
|
|
61
55
|
return filetype or 'restructuredtext'
|
|
62
56
|
raise FiletypeNotFoundError
|
|
@@ -258,32 +252,16 @@ def isurl(url: str) -> bool:
|
|
|
258
252
|
return bool(url) and '://' in url
|
|
259
253
|
|
|
260
254
|
|
|
261
|
-
def _xml_name_checker() -> re.Pattern[str]:
|
|
262
|
-
# to prevent import cycles
|
|
263
|
-
from sphinx.builders.epub3 import _XML_NAME_PATTERN
|
|
264
|
-
|
|
265
|
-
return _XML_NAME_PATTERN
|
|
266
|
-
|
|
267
|
-
|
|
268
255
|
# deprecated name -> (object to return, canonical path or empty string)
|
|
269
|
-
_DEPRECATED_OBJECTS: dict[str, tuple[Any, str
|
|
270
|
-
'path_stabilize': (_osutil.path_stabilize, 'sphinx.util.osutil.path_stabilize'),
|
|
271
|
-
'display_chunk': (_display.display_chunk, 'sphinx.util.display.display_chunk'),
|
|
272
|
-
'status_iterator': (_display.status_iterator, 'sphinx.util.display.status_iterator'),
|
|
273
|
-
'SkipProgressMessage': (_display.SkipProgressMessage,
|
|
274
|
-
'sphinx.util.display.SkipProgressMessage'),
|
|
275
|
-
'progress_message': (_display.progress_message, 'sphinx.util.display.progress_message'),
|
|
276
|
-
'epoch_to_rfc1123': (_http_date.epoch_to_rfc1123, 'sphinx.http_date.epoch_to_rfc1123'),
|
|
277
|
-
'rfc1123_to_epoch': (_http_date.rfc1123_to_epoch, 'sphinx.http_date.rfc1123_to_epoch'),
|
|
278
|
-
'save_traceback': (_exceptions.save_traceback, 'sphinx.exceptions.save_traceback'),
|
|
279
|
-
'format_exception_cut_frames': (_exceptions.format_exception_cut_frames,
|
|
280
|
-
'sphinx.exceptions.format_exception_cut_frames'),
|
|
281
|
-
'xmlname_checker': (_xml_name_checker, 'sphinx.builders.epub3._XML_NAME_PATTERN'),
|
|
256
|
+
_DEPRECATED_OBJECTS: dict[str, tuple[Any, str, tuple[int, int]]] = {
|
|
282
257
|
'split_index_msg': (_index_entries.split_index_msg,
|
|
283
|
-
'sphinx.util.index_entries.split_index_msg'
|
|
284
|
-
|
|
285
|
-
'
|
|
286
|
-
|
|
258
|
+
'sphinx.util.index_entries.split_index_msg',
|
|
259
|
+
(9, 0)),
|
|
260
|
+
'split_into': (_index_entries.split_index_msg,
|
|
261
|
+
'sphinx.util.index_entries.split_into',
|
|
262
|
+
(9, 0)),
|
|
263
|
+
'md5': (_md5, '', (9, 0)),
|
|
264
|
+
'sha1': (_sha1, '', (9, 0)),
|
|
287
265
|
}
|
|
288
266
|
|
|
289
267
|
|
|
@@ -294,8 +272,6 @@ def __getattr__(name: str) -> Any:
|
|
|
294
272
|
|
|
295
273
|
from sphinx.deprecation import _deprecation_warning
|
|
296
274
|
|
|
297
|
-
|
|
298
|
-
deprecated_object, canonical_name = info[:2]
|
|
299
|
-
remove = info[2] if len(info) == 3 else (8, 0)
|
|
275
|
+
deprecated_object, canonical_name, remove = _DEPRECATED_OBJECTS[name]
|
|
300
276
|
_deprecation_warning(__name__, name, canonical_name, remove=remove)
|
|
301
277
|
return deprecated_object
|
sphinx/util/_pathlib.py
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
"""What follows is awful and will be gone in Sphinx
|
|
1
|
+
"""What follows is awful and will be gone in Sphinx 9.
|
|
2
|
+
|
|
3
|
+
Instances of _StrPath should not be constructed except in Sphinx itself.
|
|
4
|
+
Consumers of Sphinx APIs should prefer using ``pathlib.Path`` objects
|
|
5
|
+
where possible. _StrPath objects can be treated as equivalent to ``Path``,
|
|
6
|
+
save that ``_StrPath.replace`` is overriden with ``str.replace``.
|
|
7
|
+
|
|
8
|
+
To continue treating path-like objects as strings, use ``os.fspath``,
|
|
9
|
+
or explicit string coercion.
|
|
10
|
+
|
|
11
|
+
In Sphinx 9, ``Path`` objects will be expected and returned in all instances
|
|
12
|
+
that ``_StrPath`` is currently used.
|
|
13
|
+
"""
|
|
2
14
|
|
|
3
15
|
from __future__ import annotations
|
|
4
16
|
|
|
@@ -7,13 +19,13 @@ import warnings
|
|
|
7
19
|
from pathlib import Path, PosixPath, PurePath, WindowsPath
|
|
8
20
|
from typing import Any
|
|
9
21
|
|
|
10
|
-
from sphinx.deprecation import
|
|
22
|
+
from sphinx.deprecation import RemovedInSphinx90Warning
|
|
11
23
|
|
|
12
24
|
_STR_METHODS = frozenset(str.__dict__)
|
|
13
25
|
_PATH_NAME = Path().__class__.__name__
|
|
14
26
|
|
|
15
27
|
_MSG = (
|
|
16
|
-
'Sphinx
|
|
28
|
+
'Sphinx 9 will drop support for representing paths as strings. '
|
|
17
29
|
'Use "pathlib.Path" or "os.fspath" instead.'
|
|
18
30
|
)
|
|
19
31
|
|
|
@@ -27,35 +39,35 @@ if sys.platform == 'win32':
|
|
|
27
39
|
) -> str:
|
|
28
40
|
# replace exists in both Path and str;
|
|
29
41
|
# in Path it makes filesystem changes, so we use the safer str version
|
|
30
|
-
warnings.warn(_MSG,
|
|
42
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
31
43
|
return self.__str__().replace(old, new, count) # NoQA: PLC2801
|
|
32
44
|
|
|
33
45
|
def __getattr__(self, item: str) -> Any:
|
|
34
46
|
if item in _STR_METHODS:
|
|
35
|
-
warnings.warn(_MSG,
|
|
47
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
36
48
|
return getattr(self.__str__(), item)
|
|
37
49
|
msg = f'{_PATH_NAME!r} has no attribute {item!r}'
|
|
38
50
|
raise AttributeError(msg)
|
|
39
51
|
|
|
40
52
|
def __add__(self, other: str) -> str:
|
|
41
|
-
warnings.warn(_MSG,
|
|
53
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
42
54
|
return self.__str__() + other
|
|
43
55
|
|
|
44
56
|
def __bool__(self) -> bool:
|
|
45
57
|
if not self.__str__():
|
|
46
|
-
warnings.warn(_MSG,
|
|
58
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
47
59
|
return False
|
|
48
60
|
return True
|
|
49
61
|
|
|
50
62
|
def __contains__(self, item: str) -> bool:
|
|
51
|
-
warnings.warn(_MSG,
|
|
63
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
52
64
|
return item in self.__str__()
|
|
53
65
|
|
|
54
66
|
def __eq__(self, other: object) -> bool:
|
|
55
67
|
if isinstance(other, PurePath):
|
|
56
68
|
return super().__eq__(other)
|
|
57
69
|
if isinstance(other, str):
|
|
58
|
-
warnings.warn(_MSG,
|
|
70
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
59
71
|
return self.__str__() == other
|
|
60
72
|
return NotImplemented
|
|
61
73
|
|
|
@@ -63,11 +75,11 @@ if sys.platform == 'win32':
|
|
|
63
75
|
return super().__hash__()
|
|
64
76
|
|
|
65
77
|
def __getitem__(self, item: int | slice) -> str:
|
|
66
|
-
warnings.warn(_MSG,
|
|
78
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
67
79
|
return self.__str__()[item]
|
|
68
80
|
|
|
69
81
|
def __len__(self) -> int:
|
|
70
|
-
warnings.warn(_MSG,
|
|
82
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
71
83
|
return len(self.__str__())
|
|
72
84
|
else:
|
|
73
85
|
class _StrPath(PosixPath):
|
|
@@ -76,35 +88,35 @@ else:
|
|
|
76
88
|
) -> str:
|
|
77
89
|
# replace exists in both Path and str;
|
|
78
90
|
# in Path it makes filesystem changes, so we use the safer str version
|
|
79
|
-
warnings.warn(_MSG,
|
|
91
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
80
92
|
return self.__str__().replace(old, new, count) # NoQA: PLC2801
|
|
81
93
|
|
|
82
94
|
def __getattr__(self, item: str) -> Any:
|
|
83
95
|
if item in _STR_METHODS:
|
|
84
|
-
warnings.warn(_MSG,
|
|
96
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
85
97
|
return getattr(self.__str__(), item)
|
|
86
98
|
msg = f'{_PATH_NAME!r} has no attribute {item!r}'
|
|
87
99
|
raise AttributeError(msg)
|
|
88
100
|
|
|
89
101
|
def __add__(self, other: str) -> str:
|
|
90
|
-
warnings.warn(_MSG,
|
|
102
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
91
103
|
return self.__str__() + other
|
|
92
104
|
|
|
93
105
|
def __bool__(self) -> bool:
|
|
94
106
|
if not self.__str__():
|
|
95
|
-
warnings.warn(_MSG,
|
|
107
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
96
108
|
return False
|
|
97
109
|
return True
|
|
98
110
|
|
|
99
111
|
def __contains__(self, item: str) -> bool:
|
|
100
|
-
warnings.warn(_MSG,
|
|
112
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
101
113
|
return item in self.__str__()
|
|
102
114
|
|
|
103
115
|
def __eq__(self, other: object) -> bool:
|
|
104
116
|
if isinstance(other, PurePath):
|
|
105
117
|
return super().__eq__(other)
|
|
106
118
|
if isinstance(other, str):
|
|
107
|
-
warnings.warn(_MSG,
|
|
119
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
108
120
|
return self.__str__() == other
|
|
109
121
|
return NotImplemented
|
|
110
122
|
|
|
@@ -112,9 +124,9 @@ else:
|
|
|
112
124
|
return super().__hash__()
|
|
113
125
|
|
|
114
126
|
def __getitem__(self, item: int | slice) -> str:
|
|
115
|
-
warnings.warn(_MSG,
|
|
127
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
116
128
|
return self.__str__()[item]
|
|
117
129
|
|
|
118
130
|
def __len__(self) -> int:
|
|
119
|
-
warnings.warn(_MSG,
|
|
131
|
+
warnings.warn(_MSG, RemovedInSphinx90Warning, stacklevel=2)
|
|
120
132
|
return len(self.__str__())
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _format_rfc3339_microseconds(timestamp: int, /) -> str:
|
|
7
|
+
"""Return an RFC 3339 formatted string representing the given timestamp.
|
|
8
|
+
|
|
9
|
+
:param timestamp: The timestamp to format, in microseconds.
|
|
10
|
+
"""
|
|
11
|
+
seconds, fraction = divmod(timestamp, 10**6)
|
|
12
|
+
return time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(seconds)) + f'.{fraction // 1_000}'
|
sphinx/util/cfamily.py
CHANGED
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import re
|
|
6
6
|
from copy import deepcopy
|
|
7
|
-
from typing import TYPE_CHECKING
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
8
|
|
|
9
9
|
from docutils import nodes
|
|
10
10
|
|
|
@@ -12,16 +12,16 @@ from sphinx import addnodes
|
|
|
12
12
|
from sphinx.util import logging
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
|
-
from collections.abc import Sequence
|
|
15
|
+
from collections.abc import Callable, Sequence
|
|
16
|
+
from typing import Any, TypeAlias
|
|
16
17
|
|
|
17
18
|
from docutils.nodes import TextElement
|
|
18
19
|
|
|
19
20
|
from sphinx.config import Config
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
StringifyTransform = Callable[[Any], str]
|
|
22
|
+
StringifyTransform: TypeAlias = Callable[[Any], str]
|
|
24
23
|
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
25
|
|
|
26
26
|
_whitespace_re = re.compile(r'\s+')
|
|
27
27
|
anon_identifier_re = re.compile(r'(@[a-zA-Z0-9_])[a-zA-Z0-9_]*\b')
|
sphinx/util/console.py
CHANGED
|
@@ -41,8 +41,9 @@ if TYPE_CHECKING:
|
|
|
41
41
|
try:
|
|
42
42
|
# check if colorama is installed to support color on Windows
|
|
43
43
|
import colorama
|
|
44
|
+
COLORAMA_AVAILABLE = True
|
|
44
45
|
except ImportError:
|
|
45
|
-
|
|
46
|
+
COLORAMA_AVAILABLE = False
|
|
46
47
|
|
|
47
48
|
_CSI: Final[str] = re.escape('\x1b[') # 'ESC [': Control Sequence Introducer
|
|
48
49
|
|
|
@@ -92,7 +93,7 @@ def term_width_line(text: str) -> str:
|
|
|
92
93
|
def color_terminal() -> bool:
|
|
93
94
|
if 'NO_COLOR' in os.environ:
|
|
94
95
|
return False
|
|
95
|
-
if sys.platform == 'win32' and
|
|
96
|
+
if sys.platform == 'win32' and COLORAMA_AVAILABLE:
|
|
96
97
|
colorama.just_fix_windows_console()
|
|
97
98
|
return True
|
|
98
99
|
if 'FORCE_COLOR' in os.environ:
|
|
@@ -108,7 +109,7 @@ def color_terminal() -> bool:
|
|
|
108
109
|
|
|
109
110
|
|
|
110
111
|
def nocolor() -> None:
|
|
111
|
-
if sys.platform == 'win32' and
|
|
112
|
+
if sys.platform == 'win32' and COLORAMA_AVAILABLE:
|
|
112
113
|
colorama.deinit()
|
|
113
114
|
codes.clear()
|
|
114
115
|
|
sphinx/util/display.py
CHANGED
|
@@ -7,9 +7,9 @@ from sphinx.util import logging
|
|
|
7
7
|
from sphinx.util.console import bold, color_terminal
|
|
8
8
|
|
|
9
9
|
if False:
|
|
10
|
-
from collections.abc import Iterable, Iterator
|
|
10
|
+
from collections.abc import Callable, Iterable, Iterator
|
|
11
11
|
from types import TracebackType
|
|
12
|
-
from typing import Any,
|
|
12
|
+
from typing import Any, TypeVar
|
|
13
13
|
|
|
14
14
|
from typing_extensions import ParamSpec
|
|
15
15
|
|
|
@@ -21,7 +21,7 @@ logger = logging.getLogger(__name__)
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def display_chunk(chunk: Any) -> str:
|
|
24
|
-
if isinstance(chunk,
|
|
24
|
+
if isinstance(chunk, list | tuple):
|
|
25
25
|
if len(chunk) == 1:
|
|
26
26
|
return str(chunk[0])
|
|
27
27
|
return f'{chunk[0]} .. {chunk[-1]}'
|