Sphinx 7.4.7__py3-none-any.whl → 8.0.0rc1__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 +7 -7
- 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 +88 -58
- 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 +12 -12
- sphinx/deprecation.py +8 -8
- 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/math.py +1 -1
- sphinx/domains/python/_object.py +0 -1
- sphinx/domains/std/__init__.py +7 -8
- sphinx/environment/__init__.py +14 -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 +17 -63
- 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 +7 -6
- 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/project.py +23 -19
- 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/_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 +25 -20
- sphinx/util/i18n.py +9 -4
- sphinx/util/images.py +3 -2
- sphinx/util/inspect.py +28 -43
- 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 +29 -28
- sphinx/util/parallel.py +2 -2
- sphinx/util/requests.py +1 -1
- sphinx/util/template.py +3 -3
- sphinx/util/typing.py +36 -72
- 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.7.dist-info → sphinx-8.0.0rc1.dist-info}/METADATA +10 -9
- {sphinx-7.4.7.dist-info → sphinx-8.0.0rc1.dist-info}/RECORD +104 -106
- sphinx/templates/quickstart/Makefile.jinja +0 -98
- sphinx/templates/quickstart/make.bat.jinja +0 -110
- sphinx/util/_pathlib.py +0 -120
- {sphinx-7.4.7.dist-info → sphinx-8.0.0rc1.dist-info}/LICENSE.rst +0 -0
- {sphinx-7.4.7.dist-info → sphinx-8.0.0rc1.dist-info}/WHEEL +0 -0
- {sphinx-7.4.7.dist-info → sphinx-8.0.0rc1.dist-info}/entry_points.txt +0 -0
sphinx/util/inspect.py
CHANGED
|
@@ -17,19 +17,19 @@ from importlib import import_module
|
|
|
17
17
|
from inspect import Parameter, Signature
|
|
18
18
|
from io import StringIO
|
|
19
19
|
from types import ClassMethodDescriptorType, MethodDescriptorType, WrapperDescriptorType
|
|
20
|
-
from typing import TYPE_CHECKING, Any
|
|
20
|
+
from typing import TYPE_CHECKING, Any, ForwardRef
|
|
21
21
|
|
|
22
22
|
from sphinx.pycode.ast import unparse as ast_unparse
|
|
23
23
|
from sphinx.util import logging
|
|
24
|
-
from sphinx.util.typing import
|
|
24
|
+
from sphinx.util.typing import stringify_annotation
|
|
25
25
|
|
|
26
26
|
if TYPE_CHECKING:
|
|
27
27
|
from collections.abc import Callable, Sequence
|
|
28
28
|
from inspect import _ParameterKind
|
|
29
29
|
from types import MethodType, ModuleType
|
|
30
|
-
from typing import Final, Protocol,
|
|
30
|
+
from typing import Final, Protocol, TypeAlias
|
|
31
31
|
|
|
32
|
-
from typing_extensions import
|
|
32
|
+
from typing_extensions import TypeIs
|
|
33
33
|
|
|
34
34
|
class _SupportsGet(Protocol):
|
|
35
35
|
def __get__(self, __instance: Any, __owner: type | None = ...) -> Any: ... # NoQA: E704
|
|
@@ -42,21 +42,21 @@ if TYPE_CHECKING:
|
|
|
42
42
|
# instance is contravariant but we do not need that precision
|
|
43
43
|
def __delete__(self, __instance: Any) -> None: ... # NoQA: E704
|
|
44
44
|
|
|
45
|
-
_RoutineType: TypeAlias =
|
|
46
|
-
types.FunctionType
|
|
47
|
-
types.LambdaType
|
|
48
|
-
types.MethodType
|
|
49
|
-
types.BuiltinFunctionType
|
|
50
|
-
types.BuiltinMethodType
|
|
51
|
-
types.WrapperDescriptorType
|
|
52
|
-
types.MethodDescriptorType
|
|
53
|
-
types.ClassMethodDescriptorType
|
|
54
|
-
|
|
55
|
-
_SignatureType: TypeAlias =
|
|
56
|
-
Callable[..., Any]
|
|
57
|
-
staticmethod
|
|
58
|
-
classmethod
|
|
59
|
-
|
|
45
|
+
_RoutineType: TypeAlias = (
|
|
46
|
+
types.FunctionType
|
|
47
|
+
| types.LambdaType
|
|
48
|
+
| types.MethodType
|
|
49
|
+
| types.BuiltinFunctionType
|
|
50
|
+
| types.BuiltinMethodType
|
|
51
|
+
| types.WrapperDescriptorType
|
|
52
|
+
| types.MethodDescriptorType
|
|
53
|
+
| types.ClassMethodDescriptorType
|
|
54
|
+
)
|
|
55
|
+
_SignatureType: TypeAlias = (
|
|
56
|
+
Callable[..., Any]
|
|
57
|
+
| staticmethod
|
|
58
|
+
| classmethod
|
|
59
|
+
)
|
|
60
60
|
|
|
61
61
|
logger = logging.getLogger(__name__)
|
|
62
62
|
|
|
@@ -128,20 +128,14 @@ def getall(obj: Any) -> Sequence[str] | None:
|
|
|
128
128
|
__all__ = safe_getattr(obj, '__all__', None)
|
|
129
129
|
if __all__ is None:
|
|
130
130
|
return None
|
|
131
|
-
if isinstance(__all__,
|
|
131
|
+
if isinstance(__all__, list | tuple) and all(isinstance(e, str) for e in __all__):
|
|
132
132
|
return __all__
|
|
133
133
|
raise ValueError(__all__)
|
|
134
134
|
|
|
135
135
|
|
|
136
136
|
def getannotations(obj: Any) -> Mapping[str, Any]:
|
|
137
137
|
"""Safely get the ``__annotations__`` attribute of an object."""
|
|
138
|
-
|
|
139
|
-
__annotations__ = safe_getattr(obj, '__annotations__', None)
|
|
140
|
-
else:
|
|
141
|
-
# Workaround for bugfix not available until python 3.10 as recommended by docs
|
|
142
|
-
# https://docs.python.org/3.10/howto/annotations.html#accessing-the-annotations-dict-of-an-object-in-python-3-9-and-older
|
|
143
|
-
__dict__ = safe_getattr(obj, '__dict__', {})
|
|
144
|
-
__annotations__ = __dict__.get('__annotations__', None)
|
|
138
|
+
__annotations__ = safe_getattr(obj, '__annotations__', None)
|
|
145
139
|
if isinstance(__annotations__, Mapping):
|
|
146
140
|
return __annotations__
|
|
147
141
|
return {}
|
|
@@ -198,21 +192,12 @@ def getslots(obj: Any) -> dict[str, Any] | dict[str, None] | None:
|
|
|
198
192
|
return __slots__
|
|
199
193
|
elif isinstance(__slots__, str):
|
|
200
194
|
return {__slots__: None}
|
|
201
|
-
elif isinstance(__slots__,
|
|
195
|
+
elif isinstance(__slots__, list | tuple):
|
|
202
196
|
return dict.fromkeys(__slots__)
|
|
203
197
|
else:
|
|
204
198
|
raise ValueError
|
|
205
199
|
|
|
206
200
|
|
|
207
|
-
def isNewType(obj: Any) -> bool:
|
|
208
|
-
"""Check the if object is a kind of :class:`~typing.NewType`."""
|
|
209
|
-
if sys.version_info[:2] >= (3, 10):
|
|
210
|
-
return isinstance(obj, typing.NewType)
|
|
211
|
-
__module__ = safe_getattr(obj, '__module__', None)
|
|
212
|
-
__qualname__ = safe_getattr(obj, '__qualname__', None)
|
|
213
|
-
return __module__ == 'typing' and __qualname__ == 'NewType.<locals>.new_type'
|
|
214
|
-
|
|
215
|
-
|
|
216
201
|
def isenumclass(x: Any) -> TypeIs[type[enum.Enum]]:
|
|
217
202
|
"""Check if the object is an :class:`enumeration class <enum.Enum>`."""
|
|
218
203
|
return isclass(x) and issubclass(x, enum.Enum)
|
|
@@ -237,7 +222,7 @@ def unpartial(obj: Any) -> Any:
|
|
|
237
222
|
|
|
238
223
|
def ispartial(obj: Any) -> TypeIs[partial | partialmethod]:
|
|
239
224
|
"""Check if the object is a partial function or method."""
|
|
240
|
-
return isinstance(obj,
|
|
225
|
+
return isinstance(obj, partial | partialmethod)
|
|
241
226
|
|
|
242
227
|
|
|
243
228
|
def isclassmethod(
|
|
@@ -397,12 +382,12 @@ def _is_wrapped_coroutine(obj: Any) -> bool:
|
|
|
397
382
|
|
|
398
383
|
def isproperty(obj: Any) -> TypeIs[property | cached_property]:
|
|
399
384
|
"""Check if the object is property (possibly cached)."""
|
|
400
|
-
return isinstance(obj,
|
|
385
|
+
return isinstance(obj, property | cached_property)
|
|
401
386
|
|
|
402
387
|
|
|
403
388
|
def isgenericalias(obj: Any) -> TypeIs[types.GenericAlias]:
|
|
404
389
|
"""Check if the object is a generic alias."""
|
|
405
|
-
return isinstance(obj,
|
|
390
|
+
return isinstance(obj, types.GenericAlias | typing._BaseGenericAlias) # type: ignore[attr-defined]
|
|
406
391
|
|
|
407
392
|
|
|
408
393
|
def safe_getattr(obj: Any, name: str, *defargs: Any) -> Any:
|
|
@@ -852,11 +837,11 @@ def signature_from_ast(node: ast.FunctionDef, code: str = '') -> Signature:
|
|
|
852
837
|
params: list[Parameter] = []
|
|
853
838
|
|
|
854
839
|
# positional-only arguments (introduced in Python 3.8)
|
|
855
|
-
for arg, defexpr in zip(args.posonlyargs, defaults):
|
|
840
|
+
for arg, defexpr in zip(args.posonlyargs, defaults, strict=False):
|
|
856
841
|
params.append(_define(Parameter.POSITIONAL_ONLY, arg, code, defexpr=defexpr))
|
|
857
842
|
|
|
858
843
|
# normal arguments
|
|
859
|
-
for arg, defexpr in zip(args.args, defaults[pos_only_offset:]):
|
|
844
|
+
for arg, defexpr in zip(args.args, defaults[pos_only_offset:], strict=False):
|
|
860
845
|
params.append(_define(Parameter.POSITIONAL_OR_KEYWORD, arg, code, defexpr=defexpr))
|
|
861
846
|
|
|
862
847
|
# variadic positional argument (no possible default expression)
|
|
@@ -864,7 +849,7 @@ def signature_from_ast(node: ast.FunctionDef, code: str = '') -> Signature:
|
|
|
864
849
|
params.append(_define(Parameter.VAR_POSITIONAL, args.vararg, code, defexpr=None))
|
|
865
850
|
|
|
866
851
|
# keyword-only arguments
|
|
867
|
-
for arg, defexpr in zip(args.kwonlyargs, args.kw_defaults):
|
|
852
|
+
for arg, defexpr in zip(args.kwonlyargs, args.kw_defaults, strict=False):
|
|
868
853
|
params.append(_define(Parameter.KEYWORD_ONLY, arg, code, defexpr=defexpr))
|
|
869
854
|
|
|
870
855
|
# variadic keyword argument (no possible default expression)
|
sphinx/util/inventory.py
CHANGED
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
import os
|
|
5
5
|
import re
|
|
6
6
|
import zlib
|
|
7
|
-
from typing import IO, TYPE_CHECKING
|
|
7
|
+
from typing import IO, TYPE_CHECKING
|
|
8
8
|
|
|
9
9
|
from sphinx.locale import __
|
|
10
10
|
from sphinx.util import logging
|
|
@@ -13,7 +13,7 @@ BUFSIZE = 16 * 1024
|
|
|
13
13
|
logger = logging.getLogger(__name__)
|
|
14
14
|
|
|
15
15
|
if TYPE_CHECKING:
|
|
16
|
-
from collections.abc import Iterator
|
|
16
|
+
from collections.abc import Callable, Iterator
|
|
17
17
|
|
|
18
18
|
from sphinx.builders import Builder
|
|
19
19
|
from sphinx.environment import BuildEnvironment
|
sphinx/util/matching.py
CHANGED
|
@@ -4,12 +4,12 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import os.path
|
|
6
6
|
import re
|
|
7
|
-
from typing import TYPE_CHECKING
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
8
|
|
|
9
9
|
from sphinx.util.osutil import canon_path, path_stabilize
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
|
-
from collections.abc import Iterable, Iterator
|
|
12
|
+
from collections.abc import Callable, Iterable, Iterator
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def _translate_pattern(pat: str) -> str:
|
sphinx/util/math.py
CHANGED
|
@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
8
|
from docutils import nodes
|
|
9
9
|
|
|
10
|
-
from sphinx.
|
|
10
|
+
from sphinx.writers.html5 import HTML5Translator
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def get_node_equation_number(writer: HTML5Translator, node: nodes.math_block) -> str:
|
sphinx/util/nodes.py
CHANGED
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import contextlib
|
|
6
6
|
import re
|
|
7
7
|
import unicodedata
|
|
8
|
-
from typing import TYPE_CHECKING, Any,
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast
|
|
9
9
|
|
|
10
10
|
from docutils import nodes
|
|
11
11
|
from docutils.nodes import Node
|
|
@@ -16,7 +16,7 @@ from sphinx.util import logging
|
|
|
16
16
|
from sphinx.util.parsing import _fresh_title_style_context
|
|
17
17
|
|
|
18
18
|
if TYPE_CHECKING:
|
|
19
|
-
from collections.abc import Iterable, Iterator
|
|
19
|
+
from collections.abc import Callable, Iterable, Iterator
|
|
20
20
|
|
|
21
21
|
from docutils.nodes import Element
|
|
22
22
|
from docutils.parsers.rst import Directive
|
|
@@ -178,12 +178,12 @@ def apply_source_workaround(node: Element) -> None:
|
|
|
178
178
|
return
|
|
179
179
|
|
|
180
180
|
# workaround: some docutils nodes doesn't have source, line.
|
|
181
|
-
if
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
))
|
|
181
|
+
if isinstance(node, (
|
|
182
|
+
nodes.rubric # #1305 rubric directive
|
|
183
|
+
| nodes.line # #1477 line node
|
|
184
|
+
| nodes.image # #3093 image directive in substitution
|
|
185
|
+
| nodes.field_name # #3335 field list syntax
|
|
186
|
+
)):
|
|
187
187
|
logger.debug('[i18n] PATCH: %r to have source and line: %s',
|
|
188
188
|
get_full_module_name(node), repr_domxml(node))
|
|
189
189
|
try:
|
sphinx/util/osutil.py
CHANGED
|
@@ -13,10 +13,9 @@ from io import StringIO
|
|
|
13
13
|
from os import path
|
|
14
14
|
from typing import TYPE_CHECKING
|
|
15
15
|
|
|
16
|
-
from sphinx.
|
|
16
|
+
from sphinx.locale import __
|
|
17
17
|
|
|
18
18
|
if TYPE_CHECKING:
|
|
19
|
-
from collections.abc import Iterator
|
|
20
19
|
from pathlib import Path
|
|
21
20
|
from types import TracebackType
|
|
22
21
|
from typing import Any
|
|
@@ -51,7 +50,7 @@ def relative_uri(base: str, to: str) -> str:
|
|
|
51
50
|
b2 = base.split('#')[0].split(SEP)
|
|
52
51
|
t2 = to.split('#')[0].split(SEP)
|
|
53
52
|
# remove common segments (except the last segment)
|
|
54
|
-
for x, y in zip(b2[:-1], t2[:-1]):
|
|
53
|
+
for x, y in zip(b2[:-1], t2[:-1], strict=False):
|
|
55
54
|
if x != y:
|
|
56
55
|
break
|
|
57
56
|
b2.pop(0)
|
|
@@ -72,32 +71,38 @@ def ensuredir(file: str | os.PathLike[str]) -> None:
|
|
|
72
71
|
os.makedirs(file, exist_ok=True)
|
|
73
72
|
|
|
74
73
|
|
|
75
|
-
def
|
|
76
|
-
|
|
77
|
-
for root, _dirs, files in os.walk(dirname):
|
|
78
|
-
for sfile in files:
|
|
79
|
-
if sfile.endswith(suffix):
|
|
80
|
-
with contextlib.suppress(OSError):
|
|
81
|
-
yield path.getmtime(path.join(root, sfile))
|
|
74
|
+
def _last_modified_time(source: str | os.PathLike[str], /) -> int:
|
|
75
|
+
"""Return the last modified time of ``filename``.
|
|
82
76
|
|
|
77
|
+
The time is returned as integer microseconds.
|
|
78
|
+
The lowest common denominator of modern file-systems seems to be
|
|
79
|
+
microsecond-level precision.
|
|
83
80
|
|
|
84
|
-
|
|
81
|
+
We prefer to err on the side of re-rendering a file,
|
|
82
|
+
so we round up to the nearest microsecond.
|
|
83
|
+
"""
|
|
84
|
+
st = source.stat() if isinstance(source, os.DirEntry) else os.stat(source)
|
|
85
|
+
# upside-down floor division to get the ceiling
|
|
86
|
+
return -(st.st_mtime_ns // -1_000)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _copy_times(source: str | os.PathLike[str], dest: str | os.PathLike[str]) -> None:
|
|
85
90
|
"""Copy a file's modification times."""
|
|
86
|
-
st = os.stat(source)
|
|
87
|
-
|
|
88
|
-
os.utime(dest, (st.st_atime, st.st_mtime))
|
|
91
|
+
st = source.stat() if isinstance(source, os.DirEntry) else os.stat(source)
|
|
92
|
+
os.utime(dest, ns=(st.st_atime_ns, st.st_mtime_ns))
|
|
89
93
|
|
|
90
94
|
|
|
91
95
|
def copyfile(
|
|
92
96
|
source: str | os.PathLike[str],
|
|
93
97
|
dest: str | os.PathLike[str],
|
|
94
98
|
*,
|
|
95
|
-
|
|
99
|
+
force: bool = False,
|
|
96
100
|
) -> None:
|
|
97
101
|
"""Copy a file and its modification times, if possible.
|
|
98
102
|
|
|
99
103
|
:param source: An existing source to copy.
|
|
100
104
|
:param dest: The destination path.
|
|
105
|
+
:param bool force: Overwrite the destination file even if it exists.
|
|
101
106
|
:raise FileNotFoundError: The *source* does not exist.
|
|
102
107
|
|
|
103
108
|
.. note:: :func:`copyfile` is a no-op if *source* and *dest* are identical.
|
|
@@ -112,22 +117,22 @@ def copyfile(
|
|
|
112
117
|
# two different files might have the same size
|
|
113
118
|
not filecmp.cmp(source, dest, shallow=False)
|
|
114
119
|
):
|
|
115
|
-
if
|
|
120
|
+
if not force and dest_exists:
|
|
116
121
|
# sphinx.util.logging imports sphinx.util.osutil,
|
|
117
122
|
# so use a local import to avoid circular imports
|
|
118
123
|
from sphinx.util import logging
|
|
119
124
|
logger = logging.getLogger(__name__)
|
|
120
125
|
|
|
121
|
-
msg = ('
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
+
msg = __('Aborted attempted copy from %s to %s '
|
|
127
|
+
'(the destination path has existing data).')
|
|
128
|
+
logger.warning(msg, os.fsdecode(source), os.fsdecode(dest),
|
|
129
|
+
type='misc', subtype='copy_overwrite')
|
|
130
|
+
return
|
|
126
131
|
|
|
127
132
|
shutil.copyfile(source, dest)
|
|
128
133
|
with contextlib.suppress(OSError):
|
|
129
134
|
# don't do full copystat because the source may be read-only
|
|
130
|
-
|
|
135
|
+
_copy_times(source, dest)
|
|
131
136
|
|
|
132
137
|
|
|
133
138
|
_no_fn_re = re.compile(r'[^a-zA-Z0-9_-]')
|
|
@@ -183,12 +188,8 @@ class _chdir:
|
|
|
183
188
|
os.chdir(self._dirs.pop())
|
|
184
189
|
|
|
185
190
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if sys.version_info[:2] >= (3, 11):
|
|
189
|
-
_deprecation_warning(__name__, 'cd', 'contextlib.chdir', remove=(8, 0))
|
|
190
|
-
with _chdir(target_dir):
|
|
191
|
-
yield
|
|
191
|
+
if sys.version_info[:2] < (3, 11):
|
|
192
|
+
cd = _chdir
|
|
192
193
|
|
|
193
194
|
|
|
194
195
|
class FileAvoidWrite:
|
sphinx/util/parallel.py
CHANGED
|
@@ -6,7 +6,7 @@ import os
|
|
|
6
6
|
import time
|
|
7
7
|
import traceback
|
|
8
8
|
from math import sqrt
|
|
9
|
-
from typing import TYPE_CHECKING, Any
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
10
10
|
|
|
11
11
|
try:
|
|
12
12
|
import multiprocessing
|
|
@@ -18,7 +18,7 @@ from sphinx.errors import SphinxParallelError
|
|
|
18
18
|
from sphinx.util import logging
|
|
19
19
|
|
|
20
20
|
if TYPE_CHECKING:
|
|
21
|
-
from collections.abc import Sequence
|
|
21
|
+
from collections.abc import Callable, Sequence
|
|
22
22
|
|
|
23
23
|
logger = logging.getLogger(__name__)
|
|
24
24
|
|
sphinx/util/requests.py
CHANGED
|
@@ -19,7 +19,7 @@ def _get_tls_cacert(url: str, certs: str | dict[str, str] | None) -> str | bool:
|
|
|
19
19
|
"""Get additional CA cert for a specific URL."""
|
|
20
20
|
if not certs:
|
|
21
21
|
return True
|
|
22
|
-
elif isinstance(certs,
|
|
22
|
+
elif isinstance(certs, str | tuple):
|
|
23
23
|
return certs
|
|
24
24
|
else:
|
|
25
25
|
hostname = urlsplit(url).netloc
|
sphinx/util/template.py
CHANGED
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import os
|
|
6
6
|
from functools import partial
|
|
7
7
|
from os import path
|
|
8
|
-
from typing import TYPE_CHECKING, Any
|
|
8
|
+
from typing import TYPE_CHECKING, Any
|
|
9
9
|
|
|
10
10
|
from jinja2 import TemplateNotFound
|
|
11
11
|
from jinja2.loaders import BaseLoader
|
|
@@ -17,7 +17,7 @@ from sphinx.locale import get_translator
|
|
|
17
17
|
from sphinx.util import rst, texescape
|
|
18
18
|
|
|
19
19
|
if TYPE_CHECKING:
|
|
20
|
-
from collections.abc import Sequence
|
|
20
|
+
from collections.abc import Callable, Sequence
|
|
21
21
|
|
|
22
22
|
from jinja2.environment import Environment
|
|
23
23
|
|
|
@@ -38,7 +38,7 @@ class BaseRenderer:
|
|
|
38
38
|
|
|
39
39
|
class FileRenderer(BaseRenderer):
|
|
40
40
|
def __init__(self, search_path: Sequence[str | os.PathLike[str]]) -> None:
|
|
41
|
-
if isinstance(search_path,
|
|
41
|
+
if isinstance(search_path, str | os.PathLike):
|
|
42
42
|
search_path = [search_path]
|
|
43
43
|
else:
|
|
44
44
|
# filter "None" paths
|