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.

Files changed (107) hide show
  1. sphinx/__init__.py +2 -2
  2. sphinx/_cli/__init__.py +4 -4
  3. sphinx/application.py +7 -7
  4. sphinx/builders/__init__.py +2 -3
  5. sphinx/builders/_epub_base.py +33 -12
  6. sphinx/builders/changes.py +13 -5
  7. sphinx/builders/epub3.py +6 -2
  8. sphinx/builders/html/__init__.py +88 -58
  9. sphinx/builders/latex/__init__.py +38 -12
  10. sphinx/builders/latex/transforms.py +1 -1
  11. sphinx/builders/linkcheck.py +8 -49
  12. sphinx/builders/texinfo.py +12 -6
  13. sphinx/builders/text.py +7 -3
  14. sphinx/builders/xml.py +7 -3
  15. sphinx/cmd/quickstart.py +10 -20
  16. sphinx/config.py +12 -12
  17. sphinx/deprecation.py +8 -8
  18. sphinx/directives/other.py +2 -3
  19. sphinx/directives/patches.py +2 -2
  20. sphinx/domains/__init__.py +4 -2
  21. sphinx/domains/c/__init__.py +2 -2
  22. sphinx/domains/c/_ast.py +3 -2
  23. sphinx/domains/c/_parser.py +4 -3
  24. sphinx/domains/cpp/__init__.py +2 -2
  25. sphinx/domains/cpp/_ast.py +1 -2
  26. sphinx/domains/cpp/_parser.py +2 -2
  27. sphinx/domains/cpp/_symbol.py +2 -2
  28. sphinx/domains/math.py +1 -1
  29. sphinx/domains/python/_object.py +0 -1
  30. sphinx/domains/std/__init__.py +7 -8
  31. sphinx/environment/__init__.py +14 -32
  32. sphinx/environment/adapters/indexentries.py +4 -6
  33. sphinx/environment/adapters/toctree.py +4 -4
  34. sphinx/environment/collectors/title.py +1 -1
  35. sphinx/environment/collectors/toctree.py +1 -1
  36. sphinx/events.py +3 -1
  37. sphinx/ext/autodoc/__init__.py +17 -63
  38. sphinx/ext/autodoc/directive.py +7 -5
  39. sphinx/ext/autodoc/importer.py +2 -1
  40. sphinx/ext/autodoc/preserve_defaults.py +2 -2
  41. sphinx/ext/autosummary/__init__.py +7 -6
  42. sphinx/ext/autosummary/generate.py +5 -4
  43. sphinx/ext/doctest.py +5 -5
  44. sphinx/ext/graphviz.py +1 -1
  45. sphinx/ext/imgmath.py +1 -1
  46. sphinx/ext/inheritance_diagram.py +1 -1
  47. sphinx/ext/intersphinx/__init__.py +25 -5
  48. sphinx/ext/intersphinx/_cli.py +7 -6
  49. sphinx/ext/intersphinx/_load.py +240 -115
  50. sphinx/ext/intersphinx/_resolve.py +12 -11
  51. sphinx/ext/intersphinx/_shared.py +102 -9
  52. sphinx/ext/mathjax.py +1 -1
  53. sphinx/ext/napoleon/docstring.py +2 -2
  54. sphinx/ext/todo.py +2 -2
  55. sphinx/ext/viewcode.py +2 -1
  56. sphinx/highlighting.py +3 -3
  57. sphinx/io.py +2 -2
  58. sphinx/jinja2glue.py +13 -6
  59. sphinx/locale/__init__.py +4 -3
  60. sphinx/project.py +23 -19
  61. sphinx/pycode/ast.py +2 -2
  62. sphinx/pycode/parser.py +2 -2
  63. sphinx/pygments_styles.py +3 -3
  64. sphinx/registry.py +3 -8
  65. sphinx/search/__init__.py +1 -1
  66. sphinx/testing/path.py +2 -1
  67. sphinx/testing/util.py +1 -1
  68. sphinx/texinputs/Makefile.jinja +2 -1
  69. sphinx/texinputs_win/Makefile.jinja +2 -1
  70. sphinx/theming.py +3 -12
  71. sphinx/transforms/__init__.py +5 -5
  72. sphinx/transforms/references.py +1 -1
  73. sphinx/util/__init__.py +11 -35
  74. sphinx/util/_timestamps.py +12 -0
  75. sphinx/util/cfamily.py +5 -5
  76. sphinx/util/console.py +4 -3
  77. sphinx/util/display.py +3 -3
  78. sphinx/util/docfields.py +1 -1
  79. sphinx/util/docutils.py +44 -10
  80. sphinx/util/fileutil.py +25 -20
  81. sphinx/util/i18n.py +9 -4
  82. sphinx/util/images.py +3 -2
  83. sphinx/util/inspect.py +28 -43
  84. sphinx/util/inventory.py +2 -2
  85. sphinx/util/matching.py +2 -2
  86. sphinx/util/math.py +1 -1
  87. sphinx/util/nodes.py +8 -8
  88. sphinx/util/osutil.py +29 -28
  89. sphinx/util/parallel.py +2 -2
  90. sphinx/util/requests.py +1 -1
  91. sphinx/util/template.py +3 -3
  92. sphinx/util/typing.py +36 -72
  93. sphinx/writers/html.py +1 -1
  94. sphinx/writers/html5.py +1 -1
  95. sphinx/writers/latex.py +4 -4
  96. sphinx/writers/manpage.py +2 -2
  97. sphinx/writers/texinfo.py +5 -5
  98. sphinx/writers/text.py +4 -4
  99. sphinx/writers/xml.py +2 -2
  100. {sphinx-7.4.7.dist-info → sphinx-8.0.0rc1.dist-info}/METADATA +10 -9
  101. {sphinx-7.4.7.dist-info → sphinx-8.0.0rc1.dist-info}/RECORD +104 -106
  102. sphinx/templates/quickstart/Makefile.jinja +0 -98
  103. sphinx/templates/quickstart/make.bat.jinja +0 -110
  104. sphinx/util/_pathlib.py +0 -120
  105. {sphinx-7.4.7.dist-info → sphinx-8.0.0rc1.dist-info}/LICENSE.rst +0 -0
  106. {sphinx-7.4.7.dist-info → sphinx-8.0.0rc1.dist-info}/WHEEL +0 -0
  107. {sphinx-7.4.7.dist-info → sphinx-8.0.0rc1.dist-info}/entry_points.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Any, Callable
3
+ from typing import TYPE_CHECKING, Any
4
4
 
5
5
  from sphinx.domains.c._ast import (
6
6
  ASTAlignofExpr,
@@ -53,7 +53,6 @@ from sphinx.domains.c._ast import (
53
53
  ASTTypeWithInit,
54
54
  ASTUnaryOpExpr,
55
55
  ASTUnion,
56
- DeclarationType,
57
56
  )
58
57
  from sphinx.domains.c._ids import (
59
58
  _expression_assignment_ops,
@@ -80,7 +79,9 @@ from sphinx.util.cfamily import (
80
79
  )
81
80
 
82
81
  if TYPE_CHECKING:
83
- from collections.abc import Sequence
82
+ from collections.abc import Callable, Sequence
83
+
84
+ from sphinx.domains.c._ast import DeclarationType
84
85
 
85
86
 
86
87
  class DefinitionParser(BaseParser):
@@ -23,7 +23,7 @@ from sphinx.domains.cpp._parser import DefinitionParser
23
23
  from sphinx.domains.cpp._symbol import Symbol, _DuplicateSymbolError
24
24
  from sphinx.errors import NoUri
25
25
  from sphinx.locale import _, __
26
- from sphinx.roles import SphinxRole, XRefRole
26
+ from sphinx.roles import XRefRole
27
27
  from sphinx.transforms import SphinxTransform
28
28
  from sphinx.transforms.post_transforms import ReferencesResolver
29
29
  from sphinx.util import logging
@@ -33,7 +33,7 @@ from sphinx.util.cfamily import (
33
33
  anon_identifier_re,
34
34
  )
35
35
  from sphinx.util.docfields import Field, GroupedField
36
- from sphinx.util.docutils import SphinxDirective
36
+ from sphinx.util.docutils import SphinxDirective, SphinxRole
37
37
  from sphinx.util.nodes import make_refnode
38
38
 
39
39
  if TYPE_CHECKING:
@@ -24,18 +24,17 @@ from sphinx.util.cfamily import (
24
24
  ASTBaseBase,
25
25
  ASTBaseParenExprList,
26
26
  NoOldIdError,
27
- StringifyTransform,
28
27
  UnsupportedMultiCharacterCharLiteral,
29
28
  verify_description_mode,
30
29
  )
31
30
 
32
31
  if TYPE_CHECKING:
33
-
34
32
  from docutils.nodes import Element, TextElement
35
33
 
36
34
  from sphinx.addnodes import desc_signature
37
35
  from sphinx.domains.cpp._symbol import Symbol
38
36
  from sphinx.environment import BuildEnvironment
37
+ from sphinx.util.cfamily import StringifyTransform
39
38
 
40
39
 
41
40
  class ASTBase(ASTBaseBase):
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import re
4
- from typing import TYPE_CHECKING, Any, Callable
4
+ from typing import TYPE_CHECKING, Any
5
5
 
6
6
  from sphinx.domains.cpp._ast import (
7
7
  ASTAlignofExpr,
@@ -127,7 +127,7 @@ from sphinx.util.cfamily import (
127
127
  )
128
128
 
129
129
  if TYPE_CHECKING:
130
- from collections.abc import Sequence
130
+ from collections.abc import Callable, Sequence
131
131
 
132
132
  logger = logging.getLogger(__name__)
133
133
 
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Any, Callable, NoReturn
3
+ from typing import TYPE_CHECKING, Any, NoReturn
4
4
 
5
5
  from sphinx.domains.cpp._ast import (
6
6
  ASTDeclaration,
@@ -17,7 +17,7 @@ from sphinx.locale import __
17
17
  from sphinx.util import logging
18
18
 
19
19
  if TYPE_CHECKING:
20
- from collections.abc import Iterator
20
+ from collections.abc import Callable, Iterator
21
21
 
22
22
  from sphinx.environment import BuildEnvironment
23
23
 
sphinx/domains/math.py CHANGED
@@ -74,7 +74,7 @@ class MathDomain(Domain):
74
74
  def process_doc(self, env: BuildEnvironment, docname: str,
75
75
  document: nodes.document) -> None:
76
76
  def math_node(node: Node) -> bool:
77
- return isinstance(node, (nodes.math, nodes.math_block))
77
+ return isinstance(node, nodes.math | nodes.math_block)
78
78
 
79
79
  self.data['has_equations'][docname] = any(document.findall(math_node))
80
80
 
@@ -25,7 +25,6 @@ from sphinx.util.nodes import (
25
25
  )
26
26
 
27
27
  if TYPE_CHECKING:
28
-
29
28
  from docutils.nodes import Node
30
29
  from docutils.parsers.rst.states import Inliner
31
30
 
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import re
6
6
  from copy import copy
7
- from typing import TYPE_CHECKING, Any, Callable, ClassVar, Final, cast
7
+ from typing import TYPE_CHECKING, Any, ClassVar, Final, cast
8
8
 
9
9
  from docutils import nodes
10
10
  from docutils.nodes import Element, Node, system_message
@@ -23,7 +23,7 @@ from sphinx.util.nodes import clean_astext, make_id, make_refnode
23
23
  from sphinx.util.parsing import nested_parse_to_nodes
24
24
 
25
25
  if TYPE_CHECKING:
26
- from collections.abc import Iterable, Iterator
26
+ from collections.abc import Callable, Iterable, Iterator
27
27
 
28
28
  from sphinx.application import Sphinx
29
29
  from sphinx.builders import Builder
@@ -402,7 +402,7 @@ class Glossary(SphinxDirective):
402
402
  in_comment = False
403
403
  was_empty = True
404
404
  messages: list[Node] = []
405
- for line, (source, lineno) in zip(self.content, self.content.items):
405
+ for line, (source, lineno) in zip(self.content, self.content.items, strict=True):
406
406
  # empty line -> add to last definition
407
407
  if not line:
408
408
  if in_definition and entries:
@@ -814,13 +814,12 @@ class StandardDomain(Domain):
814
814
  if not sectname:
815
815
  continue
816
816
  else:
817
- if (isinstance(node, (nodes.definition_list,
818
- nodes.field_list)) and
817
+ if (isinstance(node, nodes.definition_list | nodes.field_list) and
819
818
  node.children):
820
819
  node = cast(nodes.Element, node.children[0])
821
- if isinstance(node, (nodes.field, nodes.definition_list_item)):
820
+ if isinstance(node, nodes.field | nodes.definition_list_item):
822
821
  node = cast(nodes.Element, node.children[0])
823
- if isinstance(node, (nodes.term, nodes.field_name)):
822
+ if isinstance(node, nodes.term | nodes.field_name):
824
823
  sectname = clean_astext(node)
825
824
  else:
826
825
  toctree = next(node.findall(addnodes.toctree), None)
@@ -1114,7 +1113,7 @@ class StandardDomain(Domain):
1114
1113
  return title_getter(elem)
1115
1114
  else:
1116
1115
  for subnode in elem:
1117
- if isinstance(subnode, (nodes.caption, nodes.title)):
1116
+ if isinstance(subnode, nodes.caption | nodes.title):
1118
1117
  return clean_astext(subnode)
1119
1118
 
1120
1119
  return None
@@ -5,11 +5,10 @@ from __future__ import annotations
5
5
  import functools
6
6
  import os
7
7
  import pickle
8
- import time
9
8
  from collections import defaultdict
10
9
  from copy import copy
11
10
  from os import path
12
- from typing import TYPE_CHECKING, Any, Callable, NoReturn
11
+ from typing import TYPE_CHECKING, Any, NoReturn
13
12
 
14
13
  from sphinx import addnodes
15
14
  from sphinx.environment.adapters import toctree as toctree_adapters
@@ -17,13 +16,14 @@ from sphinx.errors import BuildEnvironmentError, DocumentError, ExtensionError,
17
16
  from sphinx.locale import __
18
17
  from sphinx.transforms import SphinxTransformer
19
18
  from sphinx.util import DownloadFiles, FilenameUniqDict, logging
19
+ from sphinx.util._timestamps import _format_rfc3339_microseconds
20
20
  from sphinx.util.docutils import LoggingReporter
21
21
  from sphinx.util.i18n import CatalogRepository, docname_to_domain
22
22
  from sphinx.util.nodes import is_translatable
23
- from sphinx.util.osutil import canon_path, os_path
23
+ from sphinx.util.osutil import _last_modified_time, canon_path, os_path
24
24
 
25
25
  if TYPE_CHECKING:
26
- from collections.abc import Iterator
26
+ from collections.abc import Callable, Iterator
27
27
  from pathlib import Path
28
28
 
29
29
  from docutils import nodes
@@ -59,7 +59,7 @@ default_settings: dict[str, Any] = {
59
59
 
60
60
  # This is increased every time an environment attribute is added
61
61
  # or changed to properly invalidate pickle files.
62
- ENV_VERSION = 62
62
+ ENV_VERSION = 63
63
63
 
64
64
  # config status
65
65
  CONFIG_UNSET = -1
@@ -124,7 +124,7 @@ if TYPE_CHECKING:
124
124
  def __getitem__(self, key: Literal["todo"]) -> TodoDomain: ... # NoQA: E704
125
125
  @overload
126
126
  def __getitem__(self, key: str) -> Domain: ... # NoQA: E704
127
- def __getitem__(self, key): raise NotImplementedError # NoQA: E704
127
+ def __getitem__(self, _key: str) -> Domain: raise NotImplementedError # NoQA: E704
128
128
  def __setitem__( # NoQA: E301,E704
129
129
  self, key: str, value: Domain,
130
130
  ) -> NoReturn: raise NotImplementedError
@@ -413,13 +413,13 @@ class BuildEnvironment:
413
413
  """
414
414
  return self.project.path2doc(filename)
415
415
 
416
- def doc2path(self, docname: str, base: bool = True) -> str:
416
+ def doc2path(self, docname: str, base: bool = True) -> Path:
417
417
  """Return the filename for the document name.
418
418
 
419
419
  If *base* is True, return absolute path under self.srcdir.
420
420
  If *base* is False, return relative path to self.srcdir.
421
421
  """
422
- return self.project.doc2path(docname, base)
422
+ return self.project.doc2path(docname, absolute=base)
423
423
 
424
424
  def relfn2path(self, filename: str, docname: str | None = None) -> tuple[str, str]:
425
425
  """Return paths to a file referenced from a document, relative to
@@ -508,7 +508,8 @@ class BuildEnvironment:
508
508
  if newmtime > mtime:
509
509
  logger.debug('[build target] outdated %r: %s -> %s',
510
510
  docname,
511
- _format_modified_time(mtime), _format_modified_time(newmtime))
511
+ _format_rfc3339_microseconds(mtime),
512
+ _format_rfc3339_microseconds(newmtime))
512
513
  changed.add(docname)
513
514
  continue
514
515
  # finally, check the mtime of dependencies
@@ -528,7 +529,8 @@ class BuildEnvironment:
528
529
  logger.debug(
529
530
  '[build target] outdated %r from dependency %r: %s -> %s',
530
531
  docname, deppath,
531
- _format_modified_time(mtime), _format_modified_time(depmtime),
532
+ _format_rfc3339_microseconds(mtime),
533
+ _format_rfc3339_microseconds(depmtime),
532
534
  )
533
535
  changed.add(docname)
534
536
  break
@@ -628,7 +630,7 @@ class BuildEnvironment:
628
630
 
629
631
  doctree = pickle.loads(serialised)
630
632
  doctree.settings.env = self
631
- doctree.reporter = LoggingReporter(self.doc2path(docname))
633
+ doctree.reporter = LoggingReporter(str(self.doc2path(docname)))
632
634
  return doctree
633
635
 
634
636
  @functools.cached_property
@@ -650,7 +652,7 @@ class BuildEnvironment:
650
652
  try:
651
653
  doctree = self._write_doc_doctree_cache.pop(docname)
652
654
  doctree.settings.env = self
653
- doctree.reporter = LoggingReporter(self.doc2path(docname))
655
+ doctree.reporter = LoggingReporter(str(self.doc2path(docname)))
654
656
  except KeyError:
655
657
  doctree = self.get_doctree(docname)
656
658
 
@@ -756,26 +758,6 @@ class BuildEnvironment:
756
758
  self.events.emit('env-check-consistency', self)
757
759
 
758
760
 
759
- def _last_modified_time(filename: str | os.PathLike[str]) -> int:
760
- """Return the last modified time of ``filename``.
761
-
762
- The time is returned as integer microseconds.
763
- The lowest common denominator of modern file-systems seems to be
764
- microsecond-level precision.
765
-
766
- We prefer to err on the side of re-rendering a file,
767
- so we round up to the nearest microsecond.
768
- """
769
- # upside-down floor division to get the ceiling
770
- return -(os.stat(filename).st_mtime_ns // -1_000)
771
-
772
-
773
- def _format_modified_time(timestamp: int) -> str:
774
- """Return an RFC 3339 formatted string representing the given timestamp."""
775
- seconds, fraction = divmod(timestamp, 10**6)
776
- return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(seconds)) + f'.{fraction // 1_000}'
777
-
778
-
779
761
  def _traverse_toctree(
780
762
  traversed: set[str],
781
763
  parent: str | None,
@@ -13,16 +13,14 @@ from sphinx.util import logging
13
13
  from sphinx.util.index_entries import _split_into
14
14
 
15
15
  if TYPE_CHECKING:
16
- from typing import Literal, Optional, Union
17
-
18
- from typing_extensions import TypeAlias
16
+ from typing import Literal, TypeAlias
19
17
 
20
18
  from sphinx.builders import Builder
21
19
  from sphinx.environment import BuildEnvironment
22
20
 
23
- _IndexEntryTarget: TypeAlias = tuple[Optional[str], Union[str, Literal[False]]]
21
+ _IndexEntryTarget: TypeAlias = tuple[str | None, str | Literal[False]]
24
22
  _IndexEntryTargets: TypeAlias = list[_IndexEntryTarget]
25
- _IndexEntryCategoryKey: TypeAlias = Optional[str]
23
+ _IndexEntryCategoryKey: TypeAlias = str | None
26
24
  _IndexEntrySubItems: TypeAlias = dict[
27
25
  str,
28
26
  tuple[_IndexEntryTargets, _IndexEntryCategoryKey],
@@ -32,7 +30,7 @@ if TYPE_CHECKING:
32
30
  _IndexEntrySubItems,
33
31
  _IndexEntryCategoryKey,
34
32
  ]
35
- _IndexEntryMap = dict[str, _IndexEntry]
33
+ _IndexEntryMap: TypeAlias = dict[str, _IndexEntry]
36
34
  _Index: TypeAlias = list[
37
35
  tuple[
38
36
  str,
@@ -319,7 +319,7 @@ def _toctree_entry(
319
319
  ref, location=toctreenode, type='toc', subtype='no_title')
320
320
  except KeyError:
321
321
  # this is raised if the included file does not exist
322
- ref_path = env.doc2path(ref, False)
322
+ ref_path = str(env.doc2path(ref, False))
323
323
  if excluded(ref_path):
324
324
  message = __('toctree contains reference to excluded document %r')
325
325
  elif not included(ref_path):
@@ -404,7 +404,7 @@ def _toctree_standard_entry(
404
404
  def _toctree_add_classes(node: Element, depth: int, docname: str) -> None:
405
405
  """Add 'toctree-l%d' and 'current' classes to the toctree."""
406
406
  for subnode in node.children:
407
- if isinstance(subnode, (addnodes.compact_paragraph, nodes.list_item)):
407
+ if isinstance(subnode, addnodes.compact_paragraph | nodes.list_item):
408
408
  # for <p> and <li>, indicate the depth level and recurse
409
409
  subnode['classes'].append(f'toctree-l{depth - 1}')
410
410
  _toctree_add_classes(subnode, depth, docname)
@@ -442,7 +442,7 @@ def _toctree_copy(node: ET, depth: int, maxdepth: int, collapse: bool, tags: Tag
442
442
 
443
443
  copy = node.copy()
444
444
  for subnode in node.children:
445
- if isinstance(subnode, (addnodes.compact_paragraph, nodes.list_item)):
445
+ if isinstance(subnode, addnodes.compact_paragraph | nodes.list_item):
446
446
  # for <p> and <li>, just recurse
447
447
  copy.append(_toctree_copy(subnode, depth, maxdepth, collapse, tags))
448
448
  elif isinstance(subnode, nodes.bullet_list):
@@ -462,7 +462,7 @@ def _toctree_copy(node: ET, depth: int, maxdepth: int, collapse: bool, tags: Tag
462
462
  copy.append(_toctree_copy(
463
463
  child, depth, maxdepth, collapse, tags, # type: ignore[type-var]
464
464
  ))
465
- elif isinstance(subnode, (nodes.reference, nodes.title)):
465
+ elif isinstance(subnode, nodes.reference | nodes.title):
466
466
  # deep copy references and captions
467
467
  sub_node_copy = subnode.copy()
468
468
  sub_node_copy.children = [child.deepcopy() for child in subnode.children]
@@ -43,7 +43,7 @@ class TitleCollector(EnvironmentCollector):
43
43
  for node in doctree.findall(nodes.section):
44
44
  visitor = SphinxContentsFilter(doctree)
45
45
  node[0].walkabout(visitor)
46
- titlenode += visitor.get_entry_text()
46
+ titlenode += visitor.get_entry_text() # type: ignore[no-untyped-call]
47
47
  break
48
48
  else:
49
49
  # document has no title
@@ -78,7 +78,7 @@ class TocTreeCollector(EnvironmentCollector):
78
78
  # and unnecessary stuff
79
79
  visitor = SphinxContentsFilter(doctree)
80
80
  title.walkabout(visitor)
81
- nodetext = visitor.get_entry_text()
81
+ nodetext = visitor.get_entry_text() # type: ignore[no-untyped-call]
82
82
  anchorname = _make_anchor_name(sectionnode['ids'], numentries)
83
83
  # make these nodes:
84
84
  # list_item -> compact_paragraph -> reference
sphinx/events.py CHANGED
@@ -8,7 +8,7 @@ from __future__ import annotations
8
8
  import contextlib
9
9
  from collections import defaultdict
10
10
  from operator import attrgetter
11
- from typing import TYPE_CHECKING, Any, Callable, NamedTuple
11
+ from typing import TYPE_CHECKING, Any, NamedTuple
12
12
 
13
13
  from sphinx.errors import ExtensionError, SphinxError
14
14
  from sphinx.locale import __
@@ -16,6 +16,8 @@ from sphinx.util import logging
16
16
  from sphinx.util.inspect import safe_getattr
17
17
 
18
18
  if TYPE_CHECKING:
19
+ from collections.abc import Callable
20
+
19
21
  from sphinx.application import Sphinx
20
22
 
21
23
 
@@ -10,20 +10,18 @@ from __future__ import annotations
10
10
  import functools
11
11
  import operator
12
12
  import re
13
- import sys
14
- import warnings
15
13
  from inspect import Parameter, Signature
16
- from typing import TYPE_CHECKING, Any, Callable, ClassVar, TypeVar
14
+ from typing import TYPE_CHECKING, Any, ClassVar, NewType, TypeVar
17
15
 
18
16
  from docutils.statemachine import StringList
19
17
 
20
18
  import sphinx
21
19
  from sphinx.config import ENUM, Config
22
- from sphinx.deprecation import RemovedInSphinx80Warning
20
+ from sphinx.errors import PycodeError
23
21
  from sphinx.ext.autodoc.importer import get_class_members, import_module, import_object
24
22
  from sphinx.ext.autodoc.mock import ismock, mock, undecorate
25
23
  from sphinx.locale import _, __
26
- from sphinx.pycode import ModuleAnalyzer, PycodeError
24
+ from sphinx.pycode import ModuleAnalyzer
27
25
  from sphinx.util import inspect, logging
28
26
  from sphinx.util.docstrings import prepare_docstring, separate_metadata
29
27
  from sphinx.util.inspect import (
@@ -42,7 +40,7 @@ from sphinx.util.typing import (
42
40
  )
43
41
 
44
42
  if TYPE_CHECKING:
45
- from collections.abc import Iterator, Sequence
43
+ from collections.abc import Callable, Iterator, Sequence
46
44
  from types import ModuleType
47
45
 
48
46
  from sphinx.application import Sphinx
@@ -267,13 +265,6 @@ class ObjectMember:
267
265
 
268
266
  This is used for the result of `Documenter.get_module_members()` to
269
267
  represent each member of the object.
270
-
271
- .. Note::
272
-
273
- An instance of this class behaves as a tuple of (name, object)
274
- for compatibility to old Sphinx. The behavior will be dropped
275
- in the future. Therefore extensions should not use the tuple
276
- interface.
277
268
  """
278
269
 
279
270
  def __init__(self, name: str, obj: Any, *, docstring: str | None = None,
@@ -284,12 +275,6 @@ class ObjectMember:
284
275
  self.skipped = skipped
285
276
  self.class_ = class_
286
277
 
287
- def __getitem__(self, index: int) -> Any:
288
- warnings.warn('The tuple interface of ObjectMember is deprecated. '
289
- 'Use (obj.__name__, obj.object) instead.',
290
- RemovedInSphinx80Warning, stacklevel=2)
291
- return (self.__name__, self.object)[index]
292
-
293
278
 
294
279
  class Documenter:
295
280
  """
@@ -627,7 +612,7 @@ class Documenter:
627
612
 
628
613
  # add additional content (e.g. from document), if present
629
614
  if more_content:
630
- for line, src in zip(more_content.data, more_content.items):
615
+ for line, src in zip(more_content.data, more_content.items, strict=True):
631
616
  self.add_line(line, src[0], src[1])
632
617
 
633
618
  def get_object_members(self, want_all: bool) -> tuple[bool, list[ObjectMember]]:
@@ -684,21 +669,8 @@ class Documenter:
684
669
 
685
670
  # process members and determine which to skip
686
671
  for obj in members:
687
- try:
688
- membername = obj.__name__
689
- member = obj.object
690
- except AttributeError:
691
- if isinstance(obj, ObjectMember):
692
- raise
693
- # To be removed, retained for compatibility.
694
- # See https://github.com/sphinx-doc/sphinx/issues/11631
695
- membername, member = obj
696
- warnings.warn(
697
- 'Returning tuples of (name, object) as '
698
- 'the second return value from get_object_members() is deprecated. '
699
- 'Return ObjectMember(name, object) instances instead.',
700
- RemovedInSphinx80Warning, stacklevel=2,
701
- )
672
+ membername = obj.__name__
673
+ member = obj.object
702
674
 
703
675
  # if isattr is True, the member is documented as an attribute
704
676
  isattr = member is INSTANCEATTR or (namespace, membername) in attr_docs
@@ -1003,7 +975,7 @@ class ModuleDocumenter(Documenter):
1003
975
  super().add_content(None)
1004
976
  self.indent = old_indent
1005
977
  if more_content:
1006
- for line, src in zip(more_content.data, more_content.items):
978
+ for line, src in zip(more_content.data, more_content.items, strict=True):
1007
979
  self.add_line(line, src[0], src[1])
1008
980
 
1009
981
  @classmethod
@@ -1410,7 +1382,7 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
1410
1382
  if len(sig.parameters) == 0:
1411
1383
  return None
1412
1384
 
1413
- def dummy(): # NoQA: ANN202
1385
+ def dummy(): # type: ignore[no-untyped-def] # NoQA: ANN202
1414
1386
  pass
1415
1387
 
1416
1388
  params = list(sig.parameters.values())
@@ -1478,7 +1450,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1478
1450
 
1479
1451
  # Must be higher than FunctionDocumenter, ClassDocumenter, and
1480
1452
  # AttributeDocumenter as NewType can be an attribute and is a class
1481
- # after Python 3.10. Before 3.10 it is a kind of function object
1453
+ # after Python 3.10.
1482
1454
  priority = 15
1483
1455
 
1484
1456
  _signature_class: Any = None
@@ -1504,7 +1476,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1504
1476
  cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any,
1505
1477
  ) -> bool:
1506
1478
  return isinstance(member, type) or (
1507
- isattr and (inspect.isNewType(member) or isinstance(member, TypeVar)))
1479
+ isattr and isinstance(member, NewType | TypeVar))
1508
1480
 
1509
1481
  def import_object(self, raiseerror: bool = False) -> bool:
1510
1482
  ret = super().import_object(raiseerror)
@@ -1515,7 +1487,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1515
1487
  self.doc_as_attr = (self.objpath[-1] != self.object.__name__)
1516
1488
  else:
1517
1489
  self.doc_as_attr = True
1518
- if inspect.isNewType(self.object) or isinstance(self.object, TypeVar):
1490
+ if isinstance(self.object, NewType | TypeVar):
1519
1491
  modname = getattr(self.object, '__module__', self.modname)
1520
1492
  if modname != self.modname and self.modname.startswith(modname):
1521
1493
  bases = self.modname[len(modname):].strip('.').split('.')
@@ -1524,7 +1496,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1524
1496
  return ret
1525
1497
 
1526
1498
  def _get_signature(self) -> tuple[Any | None, str | None, Signature | None]:
1527
- if inspect.isNewType(self.object) or isinstance(self.object, TypeVar):
1499
+ if isinstance(self.object, NewType | TypeVar):
1528
1500
  # Suppress signature
1529
1501
  return None, None, None
1530
1502
 
@@ -1709,14 +1681,14 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1709
1681
  self.directivetype = 'attribute'
1710
1682
  super().add_directive_header(sig)
1711
1683
 
1712
- if inspect.isNewType(self.object) or isinstance(self.object, TypeVar):
1684
+ if isinstance(self.object, NewType | TypeVar):
1713
1685
  return
1714
1686
 
1715
1687
  if self.analyzer and '.'.join(self.objpath) in self.analyzer.finals:
1716
1688
  self.add_line(' :final:', sourcename)
1717
1689
 
1718
1690
  canonical_fullname = self.get_canonical_fullname()
1719
- if (not self.doc_as_attr and not inspect.isNewType(self.object)
1691
+ if (not self.doc_as_attr and not isinstance(self.object, NewType)
1720
1692
  and canonical_fullname and self.fullname != canonical_fullname):
1721
1693
  self.add_line(' :canonical: %s' % canonical_fullname, sourcename)
1722
1694
 
@@ -1768,24 +1740,6 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1768
1740
  if isinstance(self.object, TypeVar):
1769
1741
  if self.object.__doc__ == TypeVar.__doc__:
1770
1742
  return []
1771
- if sys.version_info[:2] < (3, 10):
1772
- if inspect.isNewType(self.object) or isinstance(self.object, TypeVar):
1773
- parts = self.modname.strip('.').split('.')
1774
- orig_objpath = self.objpath
1775
- for i in range(len(parts)):
1776
- new_modname = '.'.join(parts[:len(parts) - i])
1777
- new_objpath = parts[len(parts) - i:] + orig_objpath
1778
- try:
1779
- analyzer = ModuleAnalyzer.for_module(new_modname)
1780
- analyzer.analyze()
1781
- key = ('', new_objpath[-1])
1782
- comment = list(analyzer.attr_docs.get(key, []))
1783
- if comment:
1784
- self.objpath = new_objpath
1785
- self.modname = new_modname
1786
- return [comment]
1787
- except PycodeError:
1788
- pass
1789
1743
  if self.doc_as_attr:
1790
1744
  # Don't show the docstring of the class when it is an alias.
1791
1745
  if self.get_variable_comment():
@@ -1849,7 +1803,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
1849
1803
  return None
1850
1804
 
1851
1805
  def add_content(self, more_content: StringList | None) -> None:
1852
- if inspect.isNewType(self.object):
1806
+ if isinstance(self.object, NewType):
1853
1807
  if self.config.autodoc_typehints_format == "short":
1854
1808
  supertype = restify(self.object.__supertype__, "smart")
1855
1809
  else:
@@ -2324,7 +2278,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
2324
2278
  if len(sig.parameters) == 1:
2325
2279
  return None
2326
2280
 
2327
- def dummy(): # NoQA: ANN202
2281
+ def dummy(): # type: ignore[no-untyped-def] # NoQA: ANN202
2328
2282
  pass
2329
2283
 
2330
2284
  params = list(sig.parameters.values())
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Any, Callable
3
+ from collections.abc import Callable
4
+ from typing import TYPE_CHECKING, Any
4
5
 
5
6
  from docutils import nodes
6
7
  from docutils.statemachine import StringList
@@ -31,14 +32,14 @@ AUTODOC_EXTENDABLE_OPTIONS = ['members', 'private-members', 'special-members',
31
32
  'exclude-members']
32
33
 
33
34
 
34
- class DummyOptionSpec(dict):
35
+ class DummyOptionSpec(dict[str, Callable[[str], str]]):
35
36
  """An option_spec allows any options."""
36
37
 
37
38
  def __bool__(self) -> bool:
38
39
  """Behaves like some options are defined."""
39
40
  return True
40
41
 
41
- def __getitem__(self, key: str) -> Callable[[str], str]:
42
+ def __getitem__(self, _key: str) -> Callable[[str], str]:
42
43
  return lambda x: x
43
44
 
44
45
 
@@ -56,8 +57,9 @@ class DocumenterBridge:
56
57
  self.state = state
57
58
 
58
59
 
59
- def process_documenter_options(documenter: type[Documenter], config: Config, options: dict,
60
- ) -> Options:
60
+ def process_documenter_options(
61
+ documenter: type[Documenter], config: Config, options: dict[str, str],
62
+ ) -> Options:
61
63
  """Recognize options of Documenter from user input."""
62
64
  default_options = config.autodoc_default_options
63
65
  for name in AUTODOC_DEFAULT_OPTIONS:
@@ -11,8 +11,9 @@ import typing
11
11
  from enum import Enum
12
12
  from typing import TYPE_CHECKING, NamedTuple
13
13
 
14
+ from sphinx.errors import PycodeError
14
15
  from sphinx.ext.autodoc.mock import ismock, undecorate
15
- from sphinx.pycode import ModuleAnalyzer, PycodeError
16
+ from sphinx.pycode import ModuleAnalyzer
16
17
  from sphinx.util import logging
17
18
  from sphinx.util.inspect import (
18
19
  getannotations,
@@ -102,9 +102,9 @@ def _is_lambda(x: Any, /) -> bool:
102
102
 
103
103
 
104
104
  def _get_arguments_inner(x: Any, /) -> ast.arguments | None:
105
- if isinstance(x, (ast.AsyncFunctionDef, ast.FunctionDef, ast.Lambda)):
105
+ if isinstance(x, ast.AsyncFunctionDef | ast.FunctionDef | ast.Lambda):
106
106
  return x.args
107
- if isinstance(x, (ast.Assign, ast.AnnAssign)):
107
+ if isinstance(x, ast.Assign | ast.AnnAssign):
108
108
  return _get_arguments_inner(x.value)
109
109
  return None
110
110