Skip to content

Commit 3d92b58

Browse files
authored
Merge branch 'master' into typing-ext-overload
2 parents 654decc + 491999f commit 3d92b58

19 files changed

+186
-44
lines changed

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ Contributors
102102
* Slawek Figiel -- additional warning suppression
103103
* Stefan Seefeld -- toctree improvements
104104
* Stefan van der Walt -- autosummary extension
105+
* Steve Piercy -- documentation improvements
105106
* \T. Powers -- HTML output improvements
106107
* Taku Shimizu -- epub3 builder
107108
* Thomas Lamb -- linkcheck builder

doc/extdev/markupapi.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,9 @@ The methods are used as follows:
173173
def run(self) -> list[Node]:
174174
container = docutils.nodes.Element()
175175
# either
176-
nested_parse_with_titles(self.state, self.result, container)
176+
nested_parse_with_titles(self.state, self.result, container, self.content_offset)
177177
# or
178-
self.state.nested_parse(self.result, 0, container)
178+
self.state.nested_parse(self.result, self.content_offset, container)
179179
parsed = container.children
180180
return parsed
181181

doc/latex.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ Keys that don't need to be overridden unless in special cases are:
500500
.. hint::
501501

502502
If the key value is set to
503-
:code-tex:`r'\\newcommand\sphinxbackoftitlepage{<Extra
503+
:code-tex:`r'\\newcommand\\sphinxbackoftitlepage{<Extra
504504
material>}\\sphinxmaketitle'`, then ``<Extra material>`` will be
505505
typeset on back of title page (``'manual'`` docclass only).
506506

@@ -1694,7 +1694,7 @@ Macros
16941694
.. hint::
16951695

16961696
If adding to preamble the loading of ``tocloft`` package, also add to
1697-
preamble :code-tex:`\\renewcommand\sphinxtableofcontentshook{}` else it
1697+
preamble :code-tex:`\\renewcommand\\sphinxtableofcontentshook{}` else it
16981698
will reset :code-tex:`\\l@section` and :code-tex:`\\l@subsection`
16991699
cancelling ``tocloft`` customization.
17001700

doc/man/sphinx-build.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,13 +272,13 @@ Options
272272
From Sphinx 8.1, :option:`!--keep-going` is always enabled.
273273
Previously, it was only applicable whilst using :option:`--fail-on-warning`,
274274
which by default exited :program:`sphinx-build` on the first warning.
275-
Using :option:`!--keep-going` runs :program:`!sphinx-build` to completion
275+
Using :option:`!--keep-going` runs :program:`sphinx-build` to completion
276276
and exits with exit status 1 if errors are encountered.
277277

278278
.. versionadded:: 1.8
279279
.. versionchanged:: 8.1
280280
:program:`sphinx-build` no longer exits on the first warning,
281-
meaning that in effect :option:`!--fail-on-warning` is always enabled.
281+
meaning that in effect :option:`!--keep-going` is always enabled.
282282
The option is retained for compatibility, but may be removed at some
283283
later date.
284284

doc/usage/configuration.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3668,7 +3668,7 @@ and which failures and redirects it ignores.
36683668
.. versionadded:: 4.1
36693669

36703670
.. versionchanged:: 8.3
3671-
Setting :confval:`!linkcheck_allowed_redirects` to the empty directory
3671+
Setting :confval:`!linkcheck_allowed_redirects` to an empty dictionary
36723672
may now be used to warn on all redirects encountered
36733673
by the *linkcheck* builder.
36743674

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ docs = [
9292
"sphinxcontrib-websupport",
9393
]
9494
lint = [
95-
"ruff==0.11.7",
95+
"ruff==0.11.9",
9696
"mypy==1.15.0",
9797
"sphinx-lint>=0.9",
9898
"types-colorama==0.4.15.20240311",
@@ -135,7 +135,7 @@ docs = [
135135
"sphinxcontrib-websupport",
136136
]
137137
lint = [
138-
"ruff==0.11.7",
138+
"ruff==0.11.9",
139139
"sphinx-lint>=0.9",
140140
]
141141
package = [
@@ -290,7 +290,6 @@ module = [
290290
"tests.test_util.test_util",
291291
"tests.test_util.test_util_display",
292292
"tests.test_util.test_util_docutils",
293-
"tests.test_util.test_util_images",
294293
"tests.test_util.test_util_inventory",
295294
# tests/test_writers
296295
"tests.test_writers.test_docutilsconf",

sphinx/directives/other.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from pathlib import Path
66
from typing import TYPE_CHECKING, cast
77

8+
import docutils
89
from docutils import nodes
910
from docutils.parsers.rst import directives
1011
from docutils.parsers.rst.directives.misc import Class
@@ -21,14 +22,15 @@
2122

2223
if TYPE_CHECKING:
2324
from collections.abc import Sequence
24-
from typing import Any, ClassVar
25+
from typing import Any, ClassVar, Final
2526

2627
from docutils.nodes import Element, Node
2728

2829
from sphinx.application import Sphinx
2930
from sphinx.util.typing import ExtensionMetadata, OptionSpec
3031

3132

33+
DU_22_PLUS: Final = docutils.__version_info__ >= (0, 22, 0, 'alpha', 0)
3234
glob_re = re.compile(r'.*[*?\[].*')
3335
logger = logging.getLogger(__name__)
3436

@@ -330,6 +332,14 @@ def run(self) -> list[Node]:
330332
surrounding_section_level = memo.section_level
331333
memo.title_styles = []
332334
memo.section_level = 0
335+
if DU_22_PLUS:
336+
# https://github.com/sphinx-doc/sphinx/issues/13539
337+
# https://sourceforge.net/p/docutils/code/10093/
338+
# https://sourceforge.net/p/docutils/patches/213/
339+
surrounding_section_parents = memo.section_parents
340+
memo.section_parents = []
341+
else:
342+
surrounding_section_parents = []
333343
try:
334344
self.state.nested_parse(
335345
self.content, self.content_offset, node, match_titles=True
@@ -365,6 +375,8 @@ def run(self) -> list[Node]:
365375
return []
366376
finally:
367377
memo.title_styles = surrounding_title_styles
378+
if DU_22_PLUS:
379+
memo.section_parents = surrounding_section_parents
368380
memo.section_level = surrounding_section_level
369381

370382

sphinx/domains/javascript.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,9 @@ def handle_signature(self, sig: str, signode: desc_signature) -> tuple[str, str]
137137
_pseudo_parse_arglist(
138138
signode,
139139
arglist,
140-
multi_line_parameter_list,
141-
trailing_comma,
140+
multi_line_parameter_list=multi_line_parameter_list,
141+
trailing_comma=trailing_comma,
142+
env=self.env,
142143
)
143144
return fullname, prefix
144145

sphinx/domains/python/_annotations.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -552,15 +552,18 @@ def _keyword_only_separator() -> addnodes.desc_parameter:
552552
def _pseudo_parse_arglist(
553553
signode: desc_signature,
554554
arglist: str,
555+
*,
555556
multi_line_parameter_list: bool = False,
556557
trailing_comma: bool = True,
558+
env: BuildEnvironment,
557559
) -> None:
558560
"""'Parse' a list of arguments separated by commas.
559561
560562
Arguments can have "optional" annotations given by enclosing them in
561563
brackets. Currently, this will split at any comma, even if it's inside a
562564
string literal (e.g. default argument value).
563565
"""
566+
# TODO: decompose 'env' parameter into only the required bits
564567
paramlist = addnodes.desc_parameterlist()
565568
paramlist['multi_line_parameter_list'] = multi_line_parameter_list
566569
paramlist['multi_line_trailing_comma'] = trailing_comma
@@ -583,9 +586,30 @@ def _pseudo_parse_arglist(
583586
ends_open += 1
584587
argument = argument[:-1].strip()
585588
if argument:
586-
stack[-1] += addnodes.desc_parameter(
587-
'', '', addnodes.desc_sig_name(argument, argument)
588-
)
589+
param_with_annotation, _, default_value = argument.partition('=')
590+
param_name, _, annotation = param_with_annotation.partition(':')
591+
del param_with_annotation
592+
593+
node = addnodes.desc_parameter()
594+
node += addnodes.desc_sig_name('', param_name.strip())
595+
if annotation:
596+
children = _parse_annotation(annotation.strip(), env=env)
597+
node += addnodes.desc_sig_punctuation('', ':')
598+
node += addnodes.desc_sig_space()
599+
node += addnodes.desc_sig_name('', '', *children) # type: ignore[arg-type]
600+
if default_value:
601+
if annotation:
602+
node += addnodes.desc_sig_space()
603+
node += addnodes.desc_sig_operator('', '=')
604+
if annotation:
605+
node += addnodes.desc_sig_space()
606+
node += nodes.inline(
607+
'',
608+
default_value.strip(),
609+
classes=['default_value'],
610+
support_smartquotes=False,
611+
)
612+
stack[-1] += node
589613
while ends_open:
590614
stack.append(addnodes.desc_optional())
591615
stack[-2] += stack[-1]

sphinx/domains/python/_object.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,9 @@ def handle_signature(self, sig: str, signode: desc_signature) -> tuple[str, str]
363363
_pseudo_parse_arglist(
364364
signode,
365365
arglist,
366-
multi_line_parameter_list,
367-
trailing_comma,
366+
multi_line_parameter_list=multi_line_parameter_list,
367+
trailing_comma=trailing_comma,
368+
env=self.env,
368369
)
369370
except (NotImplementedError, ValueError) as exc:
370371
# duplicated parameter names raise ValueError and not a SyntaxError
@@ -374,8 +375,9 @@ def handle_signature(self, sig: str, signode: desc_signature) -> tuple[str, str]
374375
_pseudo_parse_arglist(
375376
signode,
376377
arglist,
377-
multi_line_parameter_list,
378-
trailing_comma,
378+
multi_line_parameter_list=multi_line_parameter_list,
379+
trailing_comma=trailing_comma,
380+
env=self.env,
379381
)
380382
else:
381383
if self.needs_arglist():

sphinx/util/parsing.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,19 @@
55
import contextlib
66
from typing import TYPE_CHECKING
77

8+
import docutils
89
from docutils.nodes import Element
910
from docutils.statemachine import StringList, string2lines
1011

1112
if TYPE_CHECKING:
1213
from collections.abc import Iterator
14+
from typing import Final
1315

1416
from docutils.nodes import Node
1517
from docutils.parsers.rst.states import RSTState
1618

19+
DU_22_PLUS: Final = docutils.__version_info__ >= (0, 22, 0, 'alpha', 0)
20+
1721

1822
def nested_parse_to_nodes(
1923
state: RSTState,
@@ -75,15 +79,23 @@ def _fresh_title_style_context(state: RSTState) -> Iterator[None]:
7579
memo = state.memo
7680
surrounding_title_styles: list[str | tuple[str, str]] = memo.title_styles
7781
surrounding_section_level: int = memo.section_level
82+
if DU_22_PLUS:
83+
surrounding_section_parents = memo.section_parents
84+
else:
85+
surrounding_section_parents = []
7886
# clear current title styles
7987
memo.title_styles = []
8088
memo.section_level = 0
89+
if DU_22_PLUS:
90+
memo.section_parents = []
8191
try:
8292
yield
8393
finally:
8494
# reset title styles
8595
memo.title_styles = surrounding_title_styles
8696
memo.section_level = surrounding_section_level
97+
if DU_22_PLUS:
98+
memo.section_parents = surrounding_section_parents
8799

88100

89101
def _text_to_string_list(

tests/roots/test-ext-autodoc/target/need_mocks.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import missing_module
22
import missing_package1.missing_module1
3+
import sphinx.missing_module4
34
from missing_module import missing_name
45
from missing_package2 import missing_module2
56
from missing_package3.missing_module3 import missing_name # NoQA: F811
6-
7-
import sphinx.missing_module4
87
from sphinx.missing_module4 import missing_name2
98

109

tests/test_builders/test_build_linkcheck.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,12 @@ def test_too_many_requests_retry_after_HTTP_date(tz, app, monkeypatch, capsys):
11271127
) as address:
11281128
app.build()
11291129

1130+
# Undo side-effects: the monkeypatch context manager clears the TZ environment
1131+
# variable, but we also need to reset Python's internal notion of the current
1132+
# timezone.
1133+
if sys.platform != 'win32':
1134+
time.tzset()
1135+
11301136
content = (app.outdir / 'output.json').read_text(encoding='utf8')
11311137
assert json.loads(content) == {
11321138
'filename': 'index.rst',

tests/test_domains/test_domain_py.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,25 @@
3838
from sphinx.testing.util import assert_node
3939
from sphinx.writers.text import STDINDENT
4040

41+
TYPE_CHECKING = False
42+
if TYPE_CHECKING:
43+
from sphinx.application import Sphinx
44+
from sphinx.environment import BuildEnvironment
4145

42-
def parse(sig):
46+
47+
def parse(sig: str, *, env: BuildEnvironment) -> str:
4348
m = py_sig_re.match(sig)
4449
if m is None:
4550
raise ValueError
4651
_name_prefix, _tp_list, _name, arglist, _retann = m.groups()
4752
signode = addnodes.desc_signature(sig, '')
48-
_pseudo_parse_arglist(signode, arglist)
53+
_pseudo_parse_arglist(signode, arglist, env=env)
4954
return signode.astext()
5055

5156

52-
def test_function_signatures() -> None:
53-
rv = parse("compile(source : string, filename, symbol='file')")
54-
assert rv == "(source : string, filename, symbol='file')"
57+
def test_function_signatures(app: Sphinx) -> None:
58+
rv = parse("compile(source : string, filename, symbol='file')", env=app.env)
59+
assert rv == "(source: string, filename, symbol='file')"
5560

5661
for params, expect in [
5762
('(a=1)', '(a=1)'),
@@ -60,17 +65,17 @@ def test_function_signatures() -> None:
6065
('(a=1[, b=None])', '(a=1, [b=None])'),
6166
('(a=[], [b=None])', '(a=[], [b=None])'),
6267
('(a=[][, b=None])', '(a=[], [b=None])'),
63-
('(a: Foo[Bar]=[][, b=None])', '(a: Foo[Bar]=[], [b=None])'),
68+
('(a: Foo[Bar]=[][, b=None])', '(a: Foo[Bar] = [], [b=None])'),
6469
]:
65-
rv = parse(f'func{params}')
70+
rv = parse(f'func{params}', env=app.env)
6671
assert rv == expect
6772

6873
# Note: 'def f[Foo[Bar]]()' is not valid Python but people might write
6974
# it in a reST document to convene the intent of a higher-kinded type
7075
# variable.
7176
for tparams in ['', '[Foo]', '[Foo[Bar]]']:
7277
for retann in ['', '-> Foo', '-> Foo[Bar]', '-> anything else']:
73-
rv = parse(f'func{tparams}{params} {retann}'.rstrip())
78+
rv = parse(f'func{tparams}{params} {retann}'.rstrip(), env=app.env)
7479
assert rv == expect
7580

7681

0 commit comments

Comments
 (0)