summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Turner <9087854+aa-turner@users.noreply.github.com>2023-01-01 20:43:59 +0000
committerAdam Turner <9087854+aa-turner@users.noreply.github.com>2023-01-01 20:48:39 +0000
commit14a9289d780240bbce78ad3640e8e1b1b12df43f (patch)
treefd753f5b0f8c7053923b78c8fef2b90b60f9c7fa
parent26f79b0d2dd88b353ac65623897bdfbe8bc07cab (diff)
downloadsphinx-git-14a9289d780240bbce78ad3640e8e1b1b12df43f.tar.gz
Use PEP 604 types
-rw-r--r--doc/development/tutorials/examples/autodoc_intenum.py4
-rw-r--r--sphinx/addnodes.py4
-rw-r--r--sphinx/application.py38
-rw-r--r--sphinx/builders/__init__.py8
-rw-r--r--sphinx/builders/_epub_base.py4
-rw-r--r--sphinx/builders/dirhtml.py4
-rw-r--r--sphinx/builders/dummy.py4
-rw-r--r--sphinx/builders/gettext.py12
-rw-r--r--sphinx/builders/html/__init__.py8
-rw-r--r--sphinx/builders/latex/__init__.py8
-rw-r--r--sphinx/builders/latex/theming.py3
-rw-r--r--sphinx/builders/latex/transforms.py4
-rw-r--r--sphinx/builders/latex/util.py4
-rw-r--r--sphinx/builders/linkcheck.py10
-rw-r--r--sphinx/builders/manpage.py6
-rw-r--r--sphinx/builders/singlehtml.py8
-rw-r--r--sphinx/builders/texinfo.py8
-rw-r--r--sphinx/builders/text.py6
-rw-r--r--sphinx/builders/xml.py6
-rw-r--r--sphinx/cmd/build.py8
-rw-r--r--sphinx/cmd/make_mode.py3
-rw-r--r--sphinx/cmd/quickstart.py10
-rw-r--r--sphinx/config.py17
-rw-r--r--sphinx/directives/__init__.py8
-rw-r--r--sphinx/directives/code.py24
-rw-r--r--sphinx/domains/__init__.py14
-rw-r--r--sphinx/domains/c.py30
-rw-r--r--sphinx/domains/citation.py4
-rw-r--r--sphinx/domains/cpp.py126
-rw-r--r--sphinx/domains/javascript.py4
-rw-r--r--sphinx/domains/math.py4
-rw-r--r--sphinx/domains/python.py10
-rw-r--r--sphinx/domains/rst.py4
-rw-r--r--sphinx/domains/std.py33
-rw-r--r--sphinx/environment/__init__.py24
-rw-r--r--sphinx/environment/adapters/indexentries.py8
-rw-r--r--sphinx/environment/adapters/toctree.py6
-rw-r--r--sphinx/environment/collectors/__init__.py4
-rw-r--r--sphinx/environment/collectors/toctree.py10
-rw-r--r--sphinx/errors.py4
-rw-r--r--sphinx/ext/apidoc.py12
-rw-r--r--sphinx/ext/autodoc/__init__.py86
-rw-r--r--sphinx/ext/autodoc/directive.py4
-rw-r--r--sphinx/ext/autodoc/importer.py6
-rw-r--r--sphinx/ext/autodoc/mock.py6
-rw-r--r--sphinx/ext/autodoc/preserve_defaults.py6
-rw-r--r--sphinx/ext/autodoc/type_comment.py4
-rw-r--r--sphinx/ext/autosummary/__init__.py16
-rw-r--r--sphinx/ext/autosummary/generate.py16
-rw-r--r--sphinx/ext/doctest.py8
-rw-r--r--sphinx/ext/graphviz.py14
-rw-r--r--sphinx/ext/imgmath.py12
-rw-r--r--sphinx/ext/inheritance_diagram.py8
-rw-r--r--sphinx/ext/intersphinx.py32
-rw-r--r--sphinx/ext/napoleon/docstring.py24
-rw-r--r--sphinx/ext/napoleon/iterators.py12
-rw-r--r--sphinx/ext/viewcode.py6
-rw-r--r--sphinx/highlighting.py8
-rw-r--r--sphinx/jinja2glue.py8
-rw-r--r--sphinx/parsers.py4
-rw-r--r--sphinx/project.py4
-rw-r--r--sphinx/pycode/__init__.py4
-rw-r--r--sphinx/pycode/ast.py10
-rw-r--r--sphinx/pycode/parser.py30
-rw-r--r--sphinx/registry.py16
-rw-r--r--sphinx/roles.py6
-rw-r--r--sphinx/setup_command.py8
-rw-r--r--sphinx/testing/comparer.py12
-rw-r--r--sphinx/testing/fixtures.py4
-rw-r--r--sphinx/testing/path.py4
-rw-r--r--sphinx/testing/util.py18
-rw-r--r--sphinx/transforms/i18n.py4
-rw-r--r--sphinx/transforms/post_transforms/__init__.py8
-rw-r--r--sphinx/transforms/post_transforms/images.py4
-rw-r--r--sphinx/util/__init__.py6
-rw-r--r--sphinx/util/cfamily.py6
-rw-r--r--sphinx/util/docfields.py4
-rw-r--r--sphinx/util/docutils.py10
-rw-r--r--sphinx/util/fileutil.py6
-rw-r--r--sphinx/util/i18n.py6
-rw-r--r--sphinx/util/images.py14
-rw-r--r--sphinx/util/inspect.py28
-rw-r--r--sphinx/util/jsdump.py4
-rw-r--r--sphinx/util/logging.py8
-rw-r--r--sphinx/util/matching.py6
-rw-r--r--sphinx/util/math.py4
-rw-r--r--sphinx/util/nodes.py18
-rw-r--r--sphinx/util/osutil.py6
-rw-r--r--sphinx/util/parallel.py8
-rw-r--r--sphinx/util/png.py3
-rw-r--r--sphinx/util/requests.py4
-rw-r--r--sphinx/util/tags.py4
-rw-r--r--sphinx/util/template.py12
-rw-r--r--sphinx/util/texescape.py5
-rw-r--r--sphinx/util/typing.py6
-rw-r--r--sphinx/writers/_html4.py6
-rw-r--r--sphinx/writers/html5.py6
-rw-r--r--sphinx/writers/latex.py10
-rw-r--r--sphinx/writers/texinfo.py20
-rw-r--r--sphinx/writers/text.py10
100 files changed, 567 insertions, 581 deletions
diff --git a/doc/development/tutorials/examples/autodoc_intenum.py b/doc/development/tutorials/examples/autodoc_intenum.py
index 67b5c3f70..67955600f 100644
--- a/doc/development/tutorials/examples/autodoc_intenum.py
+++ b/doc/development/tutorials/examples/autodoc_intenum.py
@@ -1,7 +1,7 @@
from __future__ import annotations
from enum import IntEnum
-from typing import Any, Optional
+from typing import Any
from docutils.statemachine import StringList
@@ -30,7 +30,7 @@ class IntEnumDocumenter(ClassDocumenter):
self.add_line(' :final:', self.get_sourcename())
def add_content(self,
- more_content: Optional[StringList],
+ more_content: StringList | None,
no_docstring: bool = False
) -> None:
diff --git a/sphinx/addnodes.py b/sphinx/addnodes.py
index 4658eb7d3..07807e46e 100644
--- a/sphinx/addnodes.py
+++ b/sphinx/addnodes.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import TYPE_CHECKING, Any, Optional, Sequence
+from typing import TYPE_CHECKING, Any, Sequence
from docutils import nodes
from docutils.nodes import Element
@@ -34,7 +34,7 @@ class document(nodes.document):
in your extensions. It will be removed without deprecation period.
"""
- def set_id(self, node: Element, msgnode: Optional[Element] = None,
+ def set_id(self, node: Element, msgnode: Element | None = None,
suggested_prefix: str = '') -> str:
return super().set_id(node, msgnode, suggested_prefix) # type: ignore
diff --git a/sphinx/application.py b/sphinx/application.py
index 2a153423b..6e0ed0bf0 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -11,7 +11,7 @@ import sys
from collections import deque
from io import StringIO
from os import path
-from typing import IO, TYPE_CHECKING, Any, Callable, Optional, Union
+from typing import IO, TYPE_CHECKING, Any, Callable
from docutils import nodes
from docutils.nodes import Element, TextElement
@@ -126,11 +126,11 @@ class Sphinx:
warningiserror: bool
_warncount: int
- def __init__(self, srcdir: str, confdir: Optional[str], outdir: str, doctreedir: str,
- buildername: str, confoverrides: Optional[dict] = None,
- status: Optional[IO] = sys.stdout, warning: Optional[IO] = sys.stderr,
+ def __init__(self, srcdir: str, confdir: str | None, outdir: str, doctreedir: str,
+ buildername: str, confoverrides: dict | None = None,
+ status: IO | None = sys.stdout, warning: IO | None = sys.stderr,
freshenv: bool = False, warningiserror: bool = False,
- tags: Optional[list[str]] = None,
+ tags: list[str] | None = None,
verbosity: int = 0, parallel: int = 0, keep_going: bool = False,
pdb: bool = False) -> None:
self.phase = BuildPhase.INITIALIZATION
@@ -278,7 +278,7 @@ class Sphinx:
catalog.write_mo(self.config.language,
self.config.gettext_allow_fuzzy_translations)
- locale_dirs: list[Optional[str]] = list(repo.locale_dirs)
+ locale_dirs: list[str | None] = list(repo.locale_dirs)
locale_dirs += [None]
locale_dirs += [path.join(package_dir, 'locale')]
@@ -335,7 +335,7 @@ class Sphinx:
# ---- main "build" method -------------------------------------------------
- def build(self, force_all: bool = False, filenames: Optional[list[str]] = None) -> None:
+ def build(self, force_all: bool = False, filenames: list[str] | None = None) -> None:
self.phase = BuildPhase.READING
try:
if force_all:
@@ -489,7 +489,7 @@ class Sphinx:
self.registry.add_builder(builder, override=override)
# TODO(stephenfin): Describe 'types' parameter
- def add_config_value(self, name: str, default: Any, rebuild: Union[bool, str],
+ def add_config_value(self, name: str, default: Any, rebuild: bool | str,
types: Any = ()) -> None:
"""Register a configuration value.
@@ -558,7 +558,7 @@ class Sphinx:
self.registry.add_translator(name, translator_class, override=override)
def add_node(self, node: type[Element], override: bool = False,
- **kwargs: tuple[Callable, Optional[Callable]]) -> None:
+ **kwargs: tuple[Callable, Callable | None]) -> None:
"""Register a Docutils node class.
This is necessary for Docutils internals. It may also be used in the
@@ -602,7 +602,7 @@ class Sphinx:
self.registry.add_translation_handlers(node, **kwargs)
def add_enumerable_node(self, node: type[Element], figtype: str,
- title_getter: Optional[TitleGetter] = None, override: bool = False,
+ title_getter: TitleGetter | None = None, override: bool = False,
**kwargs: tuple[Callable, Callable]) -> None:
"""Register a Docutils node class as a numfig target.
@@ -757,7 +757,7 @@ class Sphinx:
"""
self.registry.add_directive_to_domain(domain, name, cls, override=override)
- def add_role_to_domain(self, domain: str, name: str, role: Union[RoleFunction, XRefRole],
+ def add_role_to_domain(self, domain: str, name: str, role: RoleFunction | XRefRole,
override: bool = False) -> None:
"""Register a Docutils role in a domain.
@@ -796,8 +796,8 @@ class Sphinx:
self.registry.add_index_to_domain(domain, index)
def add_object_type(self, directivename: str, rolename: str, indextemplate: str = '',
- parse_node: Optional[Callable] = None,
- ref_nodeclass: Optional[type[TextElement]] = None,
+ parse_node: Callable | None = None,
+ ref_nodeclass: type[TextElement] | None = None,
objname: str = '', doc_field_types: list = [], override: bool = False
) -> None:
"""Register a new object type.
@@ -864,7 +864,7 @@ class Sphinx:
override=override)
def add_crossref_type(self, directivename: str, rolename: str, indextemplate: str = '',
- ref_nodeclass: Optional[type[TextElement]] = None, objname: str = '',
+ ref_nodeclass: type[TextElement] | None = None, objname: str = '',
override: bool = False) -> None:
"""Register a new crossref object type.
@@ -950,8 +950,8 @@ class Sphinx:
"""
self.registry.add_post_transform(transform)
- def add_js_file(self, filename: Optional[str], priority: int = 500,
- loading_method: Optional[str] = None, **kwargs: Any) -> None:
+ def add_js_file(self, filename: str | None, priority: int = 500,
+ loading_method: str | None = None, **kwargs: Any) -> None:
"""Register a JavaScript file to include in the HTML output.
:param filename: The name of a JavaScript file that the default HTML
@@ -1082,7 +1082,7 @@ class Sphinx:
self.builder.add_css_file(filename,
priority=priority, **kwargs)
- def add_latex_package(self, packagename: str, options: Optional[str] = None,
+ def add_latex_package(self, packagename: str, options: str | None = None,
after_hyperref: bool = False) -> None:
r"""Register a package to include in the LaTeX source code.
@@ -1310,8 +1310,8 @@ class TemplateBridge:
def init(
self,
builder: "Builder",
- theme: Optional[Theme] = None,
- dirs: Optional[list[str]] = None
+ theme: Theme | None = None,
+ dirs: list[str] | None = None
) -> None:
"""Called by the builder to initialize the template system.
diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py
index e6b8a6787..b6d71eb9d 100644
--- a/sphinx/builders/__init__.py
+++ b/sphinx/builders/__init__.py
@@ -7,7 +7,7 @@ import pickle
import time
import warnings
from os import path
-from typing import TYPE_CHECKING, Any, Iterable, Optional, Sequence, Union
+from typing import TYPE_CHECKING, Any, Iterable, Sequence
from docutils import nodes
from docutils.nodes import Node
@@ -168,7 +168,7 @@ class Builder:
return relative_uri(self.get_target_uri(from_),
self.get_target_uri(to, typ))
- def get_outdated_docs(self) -> Union[str, Iterable[str]]:
+ def get_outdated_docs(self) -> str | Iterable[str]:
"""Return an iterable of output files that are outdated, or a string
describing what an update build will build.
@@ -236,7 +236,7 @@ class Builder:
self.compile_catalogs(set(repo.catalogs), message)
def compile_specific_catalogs(self, specified_files: list[str]) -> None:
- def to_domain(fpath: str) -> Optional[str]:
+ def to_domain(fpath: str) -> str | None:
docname = self.env.path2doc(path.abspath(fpath))
if docname:
return docname_to_domain(docname, self.config.gettext_compact)
@@ -313,7 +313,7 @@ class Builder:
len(to_build))
def build(
- self, docnames: Iterable[str], summary: Optional[str] = None, method: str = 'update'
+ self, docnames: Iterable[str], summary: str | None = None, method: str = 'update'
) -> None:
"""Main build method.
diff --git a/sphinx/builders/_epub_base.py b/sphinx/builders/_epub_base.py
index 0827dbb2c..9acd8444a 100644
--- a/sphinx/builders/_epub_base.py
+++ b/sphinx/builders/_epub_base.py
@@ -6,7 +6,7 @@ import html
import os
import re
from os import path
-from typing import Any, NamedTuple, Optional
+from typing import Any, NamedTuple
from urllib.parse import quote
from zipfile import ZIP_DEFLATED, ZIP_STORED, ZipFile
@@ -451,7 +451,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
pass
def handle_page(self, pagename: str, addctx: dict, templatename: str = 'page.html',
- outfilename: Optional[str] = None, event_arg: Any = None) -> None:
+ outfilename: str | None = None, event_arg: Any = None) -> None:
"""Create a rendered page.
This method is overwritten for genindex pages in order to fix href link
diff --git a/sphinx/builders/dirhtml.py b/sphinx/builders/dirhtml.py
index f1bd63189..d1c10dcef 100644
--- a/sphinx/builders/dirhtml.py
+++ b/sphinx/builders/dirhtml.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from os import path
-from typing import Any, Optional
+from typing import Any
from sphinx.application import Sphinx
from sphinx.builders.html import StandaloneHTMLBuilder
@@ -21,7 +21,7 @@ class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
"""
name = 'dirhtml'
- def get_target_uri(self, docname: str, typ: Optional[str] = None) -> str:
+ def get_target_uri(self, docname: str, typ: str | None = None) -> str:
if docname == 'index':
return ''
if docname.endswith(SEP + 'index'):
diff --git a/sphinx/builders/dummy.py b/sphinx/builders/dummy.py
index c0e87be27..72006dacc 100644
--- a/sphinx/builders/dummy.py
+++ b/sphinx/builders/dummy.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Any, Optional
+from typing import Any
from docutils.nodes import Node
@@ -23,7 +23,7 @@ class DummyBuilder(Builder):
def get_outdated_docs(self) -> set[str]:
return self.env.found_docs
- def get_target_uri(self, docname: str, typ: Optional[str] = None) -> str:
+ def get_target_uri(self, docname: str, typ: str | None = None) -> str:
return ''
def prepare_writing(self, docnames: set[str]) -> None:
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
index 476025c01..b2efc0d35 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -7,7 +7,7 @@ from collections import OrderedDict, defaultdict
from datetime import datetime, timedelta, tzinfo
from os import getenv, path, walk
from time import time
-from typing import Any, Generator, Iterable, Optional, Union
+from typing import Any, Generator, Iterable, Union
from uuid import uuid4
from docutils import nodes
@@ -81,7 +81,7 @@ class MsgOrigin:
class GettextRenderer(SphinxRenderer):
def __init__(
- self, template_path: Optional[str] = None, outdir: Optional[str] = None
+ self, template_path: str | None = None, outdir: str | None = None
) -> None:
self.outdir = outdir
if template_path is None:
@@ -130,7 +130,7 @@ class I18nBuilder(Builder):
self.tags = I18nTags()
self.catalogs: defaultdict[str, Catalog] = defaultdict(Catalog)
- def get_target_uri(self, docname: str, typ: Optional[str] = None) -> str:
+ def get_target_uri(self, docname: str, typ: str | None = None) -> str:
return ''
def get_outdated_docs(self) -> set[str]:
@@ -182,10 +182,10 @@ class LocalTimeZone(tzinfo):
super().__init__(*args, **kwargs)
self.tzdelta = tzdelta
- def utcoffset(self, dt: Optional[datetime]) -> timedelta:
+ def utcoffset(self, dt: datetime | None) -> timedelta:
return self.tzdelta
- def dst(self, dt: Optional[datetime]) -> timedelta:
+ def dst(self, dt: datetime | None) -> timedelta:
return timedelta(0)
@@ -253,7 +253,7 @@ class MessageCatalogBuilder(I18nBuilder):
raise ThemeError('%s: %r' % (template, exc)) from exc
def build(
- self, docnames: Iterable[str], summary: Optional[str] = None, method: str = 'update'
+ self, docnames: Iterable[str], summary: str | None = None, method: str = 'update'
) -> None:
self._extract_from_template()
super().build(docnames, summary, method)
diff --git a/sphinx/builders/html/__init__.py b/sphinx/builders/html/__init__.py
index 867442bce..d9f72298e 100644
--- a/sphinx/builders/html/__init__.py
+++ b/sphinx/builders/html/__init__.py
@@ -10,7 +10,7 @@ import sys
import warnings
from datetime import datetime
from os import path
-from typing import IO, Any, Iterable, Iterator, List, Optional, Tuple, Type
+from typing import IO, Any, Iterable, Iterator, List, Tuple, Type
from urllib.parse import quote
import docutils.readers.doctree
@@ -80,7 +80,7 @@ def get_stable_hash(obj: Any) -> str:
return md5(str(obj).encode()).hexdigest()
-def convert_locale_to_language_tag(locale: Optional[str]) -> Optional[str]:
+def convert_locale_to_language_tag(locale: str | None) -> str | None:
"""Convert a locale string to a language tag (ex. en_US -> en-US).
refs: BCP 47 (:rfc:`5646`)
@@ -448,7 +448,7 @@ class StandaloneHTMLBuilder(Builder):
def get_asset_paths(self) -> list[str]:
return self.config.html_extra_path + self.config.html_static_path
- def render_partial(self, node: Optional[Node]) -> dict[str, str]:
+ def render_partial(self, node: Node | None) -> dict[str, str]:
"""Utility: Render a lone doctree node."""
if node is None:
return {'fragment': ''}
@@ -1024,7 +1024,7 @@ class StandaloneHTMLBuilder(Builder):
return quote(docname) + self.link_suffix
def handle_page(self, pagename: str, addctx: dict, templatename: str = 'page.html',
- outfilename: Optional[str] = None, event_arg: Any = None) -> None:
+ outfilename: str | None = None, event_arg: Any = None) -> None:
ctx = self.globalcontext.copy()
# current_page_name is backwards compatibility
ctx['pagename'] = ctx['current_page_name'] = pagename
diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py
index eb5898127..b9d4d657c 100644
--- a/sphinx/builders/latex/__init__.py
+++ b/sphinx/builders/latex/__init__.py
@@ -5,7 +5,7 @@ from __future__ import annotations
import os
import warnings
from os import path
-from typing import Any, Iterable, Optional, Union
+from typing import Any, Iterable
from docutils.frontend import OptionParser
from docutils.nodes import Node
@@ -126,16 +126,16 @@ class LaTeXBuilder(Builder):
self.init_babel()
self.init_multilingual()
- def get_outdated_docs(self) -> Union[str, list[str]]:
+ def get_outdated_docs(self) -> str | list[str]:
return 'all documents' # for now
- def get_target_uri(self, docname: str, typ: Optional[str] = None) -> str:
+ def get_target_uri(self, docname: str, typ: str | None = None) -> str:
if docname not in self.docnames:
raise NoUri(docname, typ)
else:
return '%' + docname
- def get_relative_uri(self, from_: str, to: str, typ: Optional[str] = None) -> str:
+ def get_relative_uri(self, from_: str, to: str, typ: str | None = None) -> str:
# ignore source path
return self.get_target_uri(to, typ)
diff --git a/sphinx/builders/latex/theming.py b/sphinx/builders/latex/theming.py
index 6fa01f55d..64046b5ab 100644
--- a/sphinx/builders/latex/theming.py
+++ b/sphinx/builders/latex/theming.py
@@ -4,7 +4,6 @@ from __future__ import annotations
import configparser
from os import path
-from typing import Optional
from sphinx.application import Sphinx
from sphinx.config import Config
@@ -120,7 +119,7 @@ class ThemeFactory:
theme.update(self.config)
return theme
- def find_user_theme(self, name: str) -> Optional[Theme]:
+ def find_user_theme(self, name: str) -> Theme | None:
"""Find a theme named as *name* from latex_theme_path."""
for theme_path in self.theme_paths:
config_path = path.join(theme_path, name, 'theme.conf')
diff --git a/sphinx/builders/latex/transforms.py b/sphinx/builders/latex/transforms.py
index 92022f099..79167c05d 100644
--- a/sphinx/builders/latex/transforms.py
+++ b/sphinx/builders/latex/transforms.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Any, Optional, cast
+from typing import Any, cast
from docutils import nodes
from docutils.nodes import Element, Node
@@ -363,7 +363,7 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
self.footnotes: list[nodes.footnote] = footnotes
self.pendings: list[nodes.footnote] = []
self.table_footnotes: list[nodes.footnote] = []
- self.restricted: Optional[Element] = None
+ self.restricted: Element | None = None
super().__init__(document)
def unknown_visit(self, node: Node) -> None:
diff --git a/sphinx/builders/latex/util.py b/sphinx/builders/latex/util.py
index a57104f53..01597f995 100644
--- a/sphinx/builders/latex/util.py
+++ b/sphinx/builders/latex/util.py
@@ -2,8 +2,6 @@
from __future__ import annotations
-from typing import Optional
-
from docutils.writers.latex2e import Babel
@@ -36,7 +34,7 @@ class ExtBabel(Babel):
self.supported = False
return 'english' # fallback to english
- def get_mainlanguage_options(self) -> Optional[str]:
+ def get_mainlanguage_options(self) -> str | None:
"""Return options for polyglossia's ``\\setmainlanguage``."""
if self.use_polyglossia is False:
return None
diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py
index cafbc7162..b2249308d 100644
--- a/sphinx/builders/linkcheck.py
+++ b/sphinx/builders/linkcheck.py
@@ -13,7 +13,7 @@ from html.parser import HTMLParser
from os import path
from queue import PriorityQueue, Queue
from threading import Thread
-from typing import Any, Generator, NamedTuple, Optional, Tuple, Union, cast
+from typing import Any, Generator, NamedTuple, Tuple, Union, cast
from urllib.parse import unquote, urlparse, urlunparse
from docutils import nodes
@@ -38,12 +38,12 @@ uri_re = re.compile('([a-z]+:)?//') # matches to foo:// and // (a protocol rela
class Hyperlink(NamedTuple):
uri: str
docname: str
- lineno: Optional[int]
+ lineno: int | None
class CheckRequest(NamedTuple):
next_check: float
- hyperlink: Optional[Hyperlink]
+ hyperlink: Hyperlink | None
class CheckResult(NamedTuple):
@@ -457,7 +457,7 @@ class HyperlinkAvailabilityCheckWorker(Thread):
self.rqueue.put(CheckResult(uri, docname, lineno, status, info, code))
self.wqueue.task_done()
- def limit_rate(self, response: Response) -> Optional[float]:
+ def limit_rate(self, response: Response) -> float | None:
next_check = None
retry_after = response.headers.get("Retry-After")
if retry_after:
@@ -534,7 +534,7 @@ class HyperlinkCollector(SphinxPostTransform):
add_uri(uri, rawnode)
-def rewrite_github_anchor(app: Sphinx, uri: str) -> Optional[str]:
+def rewrite_github_anchor(app: Sphinx, uri: str) -> str | None:
"""Rewrite anchor name of the hyperlink to github.com
The hyperlink anchors in github.com are dynamically generated. This rewrites
diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py
index 5252d0418..e53fb5aaf 100644
--- a/sphinx/builders/manpage.py
+++ b/sphinx/builders/manpage.py
@@ -4,7 +4,7 @@ from __future__ import annotations
import warnings
from os import path
-from typing import Any, Optional, Union
+from typing import Any
from docutils.frontend import OptionParser
from docutils.io import FileOutput
@@ -39,10 +39,10 @@ class ManualPageBuilder(Builder):
logger.warning(__('no "man_pages" config value found; no manual pages '
'will be written'))
- def get_outdated_docs(self) -> Union[str, list[str]]:
+ def get_outdated_docs(self) -> str | list[str]:
return 'all manpages' # for now
- def get_target_uri(self, docname: str, typ: Optional[str] = None) -> str:
+ def get_target_uri(self, docname: str, typ: str | None = None) -> str:
return ''
@progress_message(__('writing'))
diff --git a/sphinx/builders/singlehtml.py b/sphinx/builders/singlehtml.py
index 64f15c742..a2c9fe1d4 100644
--- a/sphinx/builders/singlehtml.py
+++ b/sphinx/builders/singlehtml.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from os import path
-from typing import Any, Optional, Union
+from typing import Any
from docutils import nodes
from docutils.nodes import Node
@@ -29,10 +29,10 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
copysource = False
- def get_outdated_docs(self) -> Union[str, list[str]]: # type: ignore[override]
+ def get_outdated_docs(self) -> str | list[str]: # type: ignore[override]
return 'all documents'
- def get_target_uri(self, docname: str, typ: Optional[str] = None) -> str:
+ def get_target_uri(self, docname: str, typ: str | None = None) -> str:
if docname in self.env.all_docs:
# all references are on the same page...
return self.config.root_doc + self.out_suffix + \
@@ -41,7 +41,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
# chances are this is a html_additional_page
return docname + self.out_suffix
- def get_relative_uri(self, from_: str, to: str, typ: Optional[str] = None) -> str:
+ def get_relative_uri(self, from_: str, to: str, typ: str | None = None) -> str:
# ignore source
return self.get_target_uri(to, typ)
diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py
index d1fd316bf..8fad6ad3c 100644
--- a/sphinx/builders/texinfo.py
+++ b/sphinx/builders/texinfo.py
@@ -5,7 +5,7 @@ from __future__ import annotations
import os
import warnings
from os import path
-from typing import Any, Iterable, Optional, Union
+from typing import Any, Iterable
from docutils import nodes
from docutils.frontend import OptionParser
@@ -51,16 +51,16 @@ class TexinfoBuilder(Builder):
self.docnames: Iterable[str] = []
self.document_data: list[tuple[str, str, str, str, str, str, str, bool]] = []
- def get_outdated_docs(self) -> Union[str, list[str]]:
+ def get_outdated_docs(self) -> str | list[str]:
return 'all documents' # for now
- def get_target_uri(self, docname: str, typ: Optional[str] = None) -> str:
+ def get_target_uri(self, docname: str, typ: str | None = None) -> str:
if docname not in self.docnames:
raise NoUri(docname, typ)
else:
return '%' + docname
- def get_relative_uri(self, from_: str, to: str, typ: Optional[str] = None) -> str:
+ def get_relative_uri(self, from_: str, to: str, typ: str | None = None) -> str:
# ignore source path
return self.get_target_uri(to, typ)
diff --git a/sphinx/builders/text.py b/sphinx/builders/text.py
index 0f04ac889..a3cc14d1b 100644
--- a/sphinx/builders/text.py
+++ b/sphinx/builders/text.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from os import path
-from typing import Any, Iterator, Optional
+from typing import Any, Iterator
from docutils.io import StringOutput
from docutils.nodes import Node
@@ -27,7 +27,7 @@ class TextBuilder(Builder):
allow_parallel = True
default_translator_class = TextTranslator
- current_docname: Optional[str] = None
+ current_docname: str | None = None
def init(self) -> None:
# section numbers for headings in the currently visited document
@@ -51,7 +51,7 @@ class TextBuilder(Builder):
# source doesn't exist anymore
pass
- def get_target_uri(self, docname: str, typ: Optional[str] = None) -> str:
+ def get_target_uri(self, docname: str, typ: str | None = None) -> str:
return ''
def prepare_writing(self, docnames: set[str]) -> None:
diff --git a/sphinx/builders/xml.py b/sphinx/builders/xml.py
index c5f805bb4..e8c29dfcd 100644
--- a/sphinx/builders/xml.py
+++ b/sphinx/builders/xml.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from os import path
-from typing import Any, Iterator, Optional, Union
+from typing import Any, Iterator
from docutils import nodes
from docutils.io import StringOutput
@@ -31,7 +31,7 @@ class XMLBuilder(Builder):
out_suffix = '.xml'
allow_parallel = True
- _writer_class: Union[type[XMLWriter], type[PseudoXMLWriter]] = XMLWriter
+ _writer_class: type[XMLWriter] | type[PseudoXMLWriter] = XMLWriter
default_translator_class = XMLTranslator
def init(self) -> None:
@@ -55,7 +55,7 @@ class XMLBuilder(Builder):
# source doesn't exist anymore
pass
- def get_target_uri(self, docname: str, typ: Optional[str] = None) -> str:
+ def get_target_uri(self, docname: str, typ: str | None = None) -> str:
return docname
def prepare_writing(self, docnames: set[str]) -> None:
diff --git a/sphinx/cmd/build.py b/sphinx/cmd/build.py
index 25cdc9907..a6c58a539 100644
--- a/sphinx/cmd/build.py
+++ b/sphinx/cmd/build.py
@@ -11,7 +11,7 @@ import pdb # NoQA: T100
import sys
import traceback
from os import path
-from typing import Any, Optional, TextIO
+from typing import Any, TextIO
from docutils.utils import SystemMessage
@@ -27,7 +27,7 @@ from sphinx.util.osutil import abspath, ensuredir
def handle_exception(
- app: Optional[Sphinx], args: Any, exception: BaseException, stderr: TextIO = sys.stderr
+ app: Sphinx | None, args: Any, exception: BaseException, stderr: TextIO = sys.stderr
) -> None:
if isinstance(exception, bdb.BdbQuit):
return
@@ -215,8 +215,8 @@ def _parse_arguments(argv: list[str] = sys.argv[1:]) -> argparse.Namespace:
if args.color == 'no' or (args.color == 'auto' and not color_terminal()):
nocolor()
- status: Optional[TextIO] = sys.stdout
- warning: Optional[TextIO] = sys.stderr
+ status: TextIO | None = sys.stdout
+ warning: TextIO | None = sys.stderr
error = sys.stderr
if args.quiet:
diff --git a/sphinx/cmd/make_mode.py b/sphinx/cmd/make_mode.py
index 226e5ae14..3e3663c81 100644
--- a/sphinx/cmd/make_mode.py
+++ b/sphinx/cmd/make_mode.py
@@ -13,7 +13,6 @@ import os
import subprocess
import sys
from os import path
-from typing import Optional
import sphinx
from sphinx.cmd.build import build_main
@@ -134,7 +133,7 @@ class Make:
return 1
return 0
- def run_generic_build(self, builder: str, doctreedir: Optional[str] = None) -> int:
+ def run_generic_build(self, builder: str, doctreedir: str | None = None) -> int:
# compatibility with old Makefile
papersize = os.getenv('PAPER', '')
opts = self.opts
diff --git a/sphinx/cmd/quickstart.py b/sphinx/cmd/quickstart.py
index 0aafcf113..9e4660ab9 100644
--- a/sphinx/cmd/quickstart.py
+++ b/sphinx/cmd/quickstart.py
@@ -9,7 +9,7 @@ import sys
import time
from collections import OrderedDict
from os import path
-from typing import TYPE_CHECKING, Any, Callable, Optional, Union
+from typing import TYPE_CHECKING, Any, Callable
# try to import readline, unix specific enhancement
try:
@@ -133,8 +133,8 @@ def ok(x: str) -> str:
def do_prompt(
- text: str, default: Optional[str] = None, validator: Callable[[str], Any] = nonempty
-) -> Union[str, bool]:
+ text: str, default: str | None = None, validator: Callable[[str], Any] = nonempty
+) -> str | bool:
while True:
if default is not None:
prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default)
@@ -328,7 +328,7 @@ def ask_user(d: dict[str, Any]) -> None:
def generate(
- d: dict, overwrite: bool = True, silent: bool = False, templatedir: Optional[str] = None
+ d: dict, overwrite: bool = True, silent: bool = False, templatedir: str | None = None
) -> None:
"""Generate project based on values in *d*."""
template = QuickstartRenderer(templatedir or '')
@@ -364,7 +364,7 @@ def generate(
ensuredir(path.join(srcdir, d['dot'] + 'templates'))
ensuredir(path.join(srcdir, d['dot'] + 'static'))
- def write_file(fpath: str, content: str, newline: Optional[str] = None) -> None:
+ def write_file(fpath: str, content: str, newline: str | None = None) -> None:
if overwrite or not path.isfile(fpath):
if 'quiet' not in d:
print(__('Creating file %s.') % fpath)
diff --git a/sphinx/config.py b/sphinx/config.py
index f72f01e60..4cc04fc2e 100644
--- a/sphinx/config.py
+++ b/sphinx/config.py
@@ -7,8 +7,7 @@ import traceback
import types
from collections import OrderedDict
from os import getenv, path
-from typing import (TYPE_CHECKING, Any, Callable, Generator, Iterator, NamedTuple, Optional,
- Union)
+from typing import TYPE_CHECKING, Any, Callable, Generator, Iterator, NamedTuple, Optional
from sphinx.errors import ConfigError, ExtensionError
from sphinx.locale import _, __
@@ -32,7 +31,7 @@ copyright_year_re = re.compile(r'^((\d{4}-)?)(\d{4})(?=[ ,])')
class ConfigValue(NamedTuple):
name: str
value: Any
- rebuild: Union[bool, str]
+ rebuild: bool | str
def is_serializable(obj: Any) -> bool:
@@ -58,7 +57,7 @@ class ENUM:
def __init__(self, *candidates: str) -> None:
self.candidates = candidates
- def match(self, value: Union[str, list, tuple]) -> bool:
+ def match(self, value: str | list | tuple) -> bool:
if isinstance(value, (list, tuple)):
return all(item in self.candidates for item in value)
else:
@@ -153,7 +152,7 @@ class Config:
self.overrides = dict(overrides)
self.values = Config.config_values.copy()
self._raw_config = config
- self.setup: Optional[Callable] = config.get('setup', None)
+ self.setup: Callable | None = config.get('setup', None)
if 'extensions' in self.overrides:
if isinstance(self.overrides['extensions'], str):
@@ -164,7 +163,7 @@ class Config:
@classmethod
def read(
- cls, confdir: str, overrides: Optional[dict] = None, tags: Optional[Tags] = None
+ cls, confdir: str, overrides: dict | None = None, tags: Tags | None = None
) -> "Config":
"""Create a Config object from configuration file."""
filename = path.join(confdir, CONFIG_FILENAME)
@@ -300,13 +299,13 @@ class Config:
for name, value in self.values.items():
yield ConfigValue(name, getattr(self, name), value[1])
- def add(self, name: str, default: Any, rebuild: Union[bool, str], types: Any) -> None:
+ def add(self, name: str, default: Any, rebuild: bool | str, types: Any) -> None:
if name in self.values:
raise ExtensionError(__('Config value %r already present') % name)
else:
self.values[name] = (default, rebuild, types)
- def filter(self, rebuild: Union[str, list[str]]) -> Iterator[ConfigValue]:
+ def filter(self, rebuild: str | list[str]) -> Iterator[ConfigValue]:
if isinstance(rebuild, str):
rebuild = [rebuild]
return (value for value in self if value.rebuild in rebuild)
@@ -338,7 +337,7 @@ class Config:
self.__dict__.update(state)
-def eval_config_file(filename: str, tags: Optional[Tags]) -> dict[str, Any]:
+def eval_config_file(filename: str, tags: Tags | None) -> dict[str, Any]:
"""Evaluate a config file."""
namespace: dict[str, Any] = {}
namespace['__file__'] = filename
diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py
index 4900dd161..c5592e187 100644
--- a/sphinx/directives/__init__.py
+++ b/sphinx/directives/__init__.py
@@ -3,7 +3,7 @@
from __future__ import annotations
import re
-from typing import TYPE_CHECKING, Any, Generic, List, Optional, TypeVar, cast
+from typing import TYPE_CHECKING, Any, Generic, List, TypeVar, cast
from docutils import nodes
from docutils.nodes import Node
@@ -60,9 +60,9 @@ class ObjectDescription(SphinxDirective, Generic[T]):
# types of doc fields that this directive handles, see sphinx.util.docfields
doc_field_types: list[Field] = []
- domain: Optional[str] = None
- objtype: Optional[str] = None
- indexnode: Optional[addnodes.index] = None
+ domain: str | None = None
+ objtype: str | None = None
+ indexnode: addnodes.index | None = None
# Warning: this might be removed in future version. Don't touch this from extensions.
_doc_field_type_map: dict[str, tuple[Field, bool]] = {}
diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py
index 559e5571d..719703aae 100644
--- a/sphinx/directives/code.py
+++ b/sphinx/directives/code.py
@@ -3,7 +3,7 @@ from __future__ import annotations
import sys
import textwrap
from difflib import unified_diff
-from typing import TYPE_CHECKING, Any, Optional
+from typing import TYPE_CHECKING, Any
from docutils import nodes
from docutils.nodes import Element, Node
@@ -51,7 +51,7 @@ class Highlight(SphinxDirective):
def dedent_lines(
- lines: list[str], dedent: Optional[int], location: Optional[tuple[str, int]] = None
+ lines: list[str], dedent: int | None, location: tuple[str, int] | None = None
) -> list[str]:
if dedent is None:
return textwrap.dedent(''.join(lines)).splitlines(True)
@@ -207,7 +207,7 @@ class LiteralIncludeReader:
(option1, option2))
def read_file(
- self, filename: str, location: Optional[tuple[str, int]] = None
+ self, filename: str, location: tuple[str, int] | None = None
) -> list[str]:
try:
with open(filename, encoding=self.encoding, errors='strict') as f:
@@ -224,7 +224,7 @@ class LiteralIncludeReader:
'be wrong, try giving an :encoding: option') %
(self.encoding, filename)) from exc
- def read(self, location: Optional[tuple[str, int]] = None) -> tuple[str, int]:
+ def read(self, location: tuple[str, int] | None = None) -> tuple[str, int]:
if 'diff' in self.options:
lines = self.show_diff()
else:
@@ -241,7 +241,7 @@ class LiteralIncludeReader:
return ''.join(lines), len(lines)
- def show_diff(self, location: Optional[tuple[str, int]] = None) -> list[str]:
+ def show_diff(self, location: tuple[str, int] | None = None) -> list[str]:
new_lines = self.read_file(self.filename)
old_filename = self.options['diff']
old_lines = self.read_file(old_filename)
@@ -249,7 +249,7 @@ class LiteralIncludeReader:
return list(diff)
def pyobject_filter(
- self, lines: list[str], location: Optional[tuple[str, int]] = None
+ self, lines: list[str], location: tuple[str, int] | None = None
) -> list[str]:
pyobject = self.options.get('pyobject')
if pyobject:
@@ -269,7 +269,7 @@ class LiteralIncludeReader:
return lines
def lines_filter(
- self, lines: list[str], location: Optional[tuple[str, int]] = None
+ self, lines: list[str], location: tuple[str, int] | None = None
) -> list[str]:
linespec = self.options.get('lines')
if linespec:
@@ -295,7 +295,7 @@ class LiteralIncludeReader:
return lines
def start_filter(
- self, lines: list[str], location: Optional[tuple[str, int]] = None
+ self, lines: list[str], location: tuple[str, int] | None = None
) -> list[str]:
if 'start-at' in self.options:
start = self.options.get('start-at')
@@ -328,7 +328,7 @@ class LiteralIncludeReader:
return lines
def end_filter(
- self, lines: list[str], location: Optional[tuple[str, int]] = None
+ self, lines: list[str], location: tuple[str, int] | None = None
) -> list[str]:
if 'end-at' in self.options:
end = self.options.get('end-at')
@@ -357,7 +357,7 @@ class LiteralIncludeReader:
return lines
def prepend_filter(
- self, lines: list[str], location: Optional[tuple[str, int]] = None
+ self, lines: list[str], location: tuple[str, int] | None = None
) -> list[str]:
prepend = self.options.get('prepend')
if prepend:
@@ -366,7 +366,7 @@ class LiteralIncludeReader:
return lines
def append_filter(
- self, lines: list[str], location: Optional[tuple[str, int]] = None
+ self, lines: list[str], location: tuple[str, int] | None = None
) -> list[str]:
append = self.options.get('append')
if append:
@@ -375,7 +375,7 @@ class LiteralIncludeReader:
return lines
def dedent_filter(
- self, lines: list[str], location: Optional[tuple[str, int]] = None
+ self, lines: list[str], location: tuple[str, int] | None = None
) -> list[str]:
if 'dedent' in self.options:
return dedent_lines(lines, self.options.get('dedent'), location=location)
diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py
index c4cf71834..8ea9a1e25 100644
--- a/sphinx/domains/__init__.py
+++ b/sphinx/domains/__init__.py
@@ -8,7 +8,7 @@ from __future__ import annotations
import copy
from abc import ABC, abstractmethod
-from typing import TYPE_CHECKING, Any, Callable, Iterable, NamedTuple, Optional, Union, cast
+from typing import TYPE_CHECKING, Any, Callable, Iterable, NamedTuple, cast
from docutils import nodes
from docutils.nodes import Element, Node, system_message
@@ -181,7 +181,7 @@ class Domain:
#: directive name -> directive class
directives: dict[str, Any] = {}
#: role name -> role callable
- roles: dict[str, Union[RoleFunction, XRefRole]] = {}
+ roles: dict[str, RoleFunction | XRefRole] = {}
#: a list of Index subclasses
indices: list[type[Index]] = []
#: role name -> a warning message if reference is missing
@@ -247,7 +247,7 @@ class Domain:
for role in objtype.roles:
self._role2type.setdefault(role, []).append(name)
- def role(self, name: str) -> Optional[RoleFunction]:
+ def role(self, name: str) -> RoleFunction | None:
"""Return a role adapter function that always gives the registered
role its full name ('domain:name') as the first argument.
"""
@@ -265,7 +265,7 @@ class Domain:
self._role_cache[name] = role_adapter
return role_adapter
- def directive(self, name: str) -> Optional[Callable]:
+ def directive(self, name: str) -> Callable | None:
"""Return a directive adapter class that always gives the registered
directive its full name ('domain:name') as ``self.name``.
"""
@@ -314,7 +314,7 @@ class Domain:
def resolve_xref(self, env: "BuildEnvironment", fromdocname: str, builder: "Builder",
typ: str, target: str, node: pending_xref, contnode: Element
- ) -> Optional[Element]:
+ ) -> Element | None:
"""Resolve the pending_xref *node* with the given *typ* and *target*.
This method should return a new node, to replace the xref node,
@@ -389,11 +389,11 @@ class Domain:
return type.lname
return _('%s %s') % (self.label, type.lname)
- def get_enumerable_node_type(self, node: Node) -> Optional[str]:
+ def get_enumerable_node_type(self, node: Node) -> str | None:
"""Get type of enumerable nodes (experimental)."""
enum_node_type, _ = self.enumerable_nodes.get(node.__class__, (None, None))
return enum_node_type
- def get_full_qualified_name(self, node: Element) -> Optional[str]:
+ def get_full_qualified_name(self, node: Element) -> str | None:
"""Return full qualified name for given node."""
return None
diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py
index 7c518218a..567911ec3 100644
--- a/sphinx/domains/c.py
+++ b/sphinx/domains/c.py
@@ -1162,7 +1162,7 @@ class ASTBracedInitList(ASTBase):
class ASTInitializer(ASTBase):
- def __init__(self, value: Union[ASTBracedInitList, ASTExpression],
+ def __init__(self, value: ASTBracedInitList | ASTExpression,
hasAssign: bool = True) -> None:
self.value = value
self.hasAssign = hasAssign
@@ -1374,7 +1374,7 @@ class ASTEnum(ASTBase):
class ASTEnumerator(ASTBase):
- def __init__(self, name: ASTNestedName, init: Optional[ASTInitializer],
+ def __init__(self, name: ASTNestedName, init: ASTInitializer | None,
attrs: ASTAttributeList) -> None:
self.name = name
self.init = init
@@ -1406,7 +1406,7 @@ class ASTEnumerator(ASTBase):
class ASTDeclaration(ASTBaseBase):
def __init__(self, objectType: str, directiveType: str,
- declaration: Union[DeclarationType, ASTFunctionParameter],
+ declaration: DeclarationType | ASTFunctionParameter,
semicolon: bool = False) -> None:
self.objectType = objectType
self.directiveType = directiveType
@@ -2574,7 +2574,7 @@ class DefinitionParser(BaseParser):
break
return ASTNestedName(names, rooted)
- def _parse_simple_type_specifier(self) -> Optional[str]:
+ def _parse_simple_type_specifier(self) -> str | None:
if self.match(_simple_type_specifiers_re):
return self.matched_text
for t in ('bool', 'complex', 'imaginary'):
@@ -2616,7 +2616,7 @@ class DefinitionParser(BaseParser):
nestedName = self._parse_nested_name()
return ASTTrailingTypeSpecName(prefix, nestedName)
- def _parse_parameters(self, paramMode: str) -> Optional[ASTParameters]:
+ def _parse_parameters(self, paramMode: str) -> ASTParameters | None:
self.skip_ws()
if not self.skip_string('('):
if paramMode == 'function':
@@ -2727,7 +2727,7 @@ class DefinitionParser(BaseParser):
return ASTDeclSpecs(outer, leftSpecs, rightSpecs, trailing)
def _parse_declarator_name_suffix(
- self, named: Union[bool, str], paramMode: str, typed: bool
+ self, named: bool | str, paramMode: str, typed: bool
) -> ASTDeclarator:
assert named in (True, False, 'single')
# now we should parse the name, and then suffixes
@@ -2807,7 +2807,7 @@ class DefinitionParser(BaseParser):
return ASTDeclaratorNameParam(declId=declId, arrayOps=arrayOps,
param=param)
- def _parse_declarator(self, named: Union[bool, str], paramMode: str,
+ def _parse_declarator(self, named: bool | str, paramMode: str,
typed: bool = True) -> ASTDeclarator:
# 'typed' here means 'parse return type stuff'
if paramMode not in ('type', 'function'):
@@ -2917,7 +2917,7 @@ class DefinitionParser(BaseParser):
value = self._parse_expression_fallback(fallbackEnd, parser, allow=allowFallback)
return ASTInitializer(value)
- def _parse_type(self, named: Union[bool, str], outer: Optional[str] = None) -> ASTType:
+ def _parse_type(self, named: bool | str, outer: str | None = None) -> ASTType:
"""
named=False|'single'|True: 'single' is e.g., for function objects which
doesn't need to name the arguments, but otherwise is a single name
@@ -2976,7 +2976,7 @@ class DefinitionParser(BaseParser):
decl = self._parse_declarator(named=named, paramMode=paramMode)
return ASTType(declSpecs, decl)
- def _parse_type_with_init(self, named: Union[bool, str], outer: str) -> ASTTypeWithInit:
+ def _parse_type_with_init(self, named: bool | str, outer: str) -> ASTTypeWithInit:
if outer:
assert outer in ('type', 'member', 'function')
type = self._parse_type(outer=outer, named=named)
@@ -3095,9 +3095,9 @@ class DefinitionParser(BaseParser):
self.assert_end()
return name
- def parse_expression(self) -> Union[ASTExpression, ASTType]:
+ def parse_expression(self) -> ASTExpression | ASTType:
pos = self.pos
- res: Union[ASTExpression, ASTType] = None
+ res: ASTExpression | ASTType = None
try:
res = self._parse_expression()
self.skip_ws()
@@ -3489,7 +3489,7 @@ class AliasTransform(SphinxTransform):
if recurse:
if skipThis:
- childContainer: Union[list[Node], addnodes.desc] = nodes
+ childContainer: list[Node] | addnodes.desc = nodes
else:
content = addnodes.desc_content()
desc = addnodes.desc()
@@ -3721,7 +3721,7 @@ class CDomain(Domain):
'expr': CExprRole(asCode=True),
'texpr': CExprRole(asCode=False)
}
- initial_data: dict[str, Union[Symbol, dict[str, tuple[str, str, str]]]] = {
+ initial_data: dict[str, Symbol | dict[str, tuple[str, str, str]]] = {
'root_symbol': Symbol(None, None, None, None, None),
'objects': {}, # fullname -> docname, node_id, objtype
}
@@ -3774,7 +3774,7 @@ class CDomain(Domain):
def _resolve_xref_inner(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
typ: str, target: str, node: pending_xref,
- contnode: Element) -> tuple[Optional[Element], Optional[str]]:
+ contnode: Element) -> tuple[Element | None, str | None]:
parser = DefinitionParser(target, location=node, config=env.config)
try:
name = parser.parse_xref_object()
@@ -3811,7 +3811,7 @@ class CDomain(Domain):
def resolve_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
typ: str, target: str, node: pending_xref,
- contnode: Element) -> Optional[Element]:
+ contnode: Element) -> Element | None:
return self._resolve_xref_inner(env, fromdocname, builder, typ,
target, node, contnode)[0]
diff --git a/sphinx/domains/citation.py b/sphinx/domains/citation.py
index b3a179a29..668c2ddc6 100644
--- a/sphinx/domains/citation.py
+++ b/sphinx/domains/citation.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import TYPE_CHECKING, Any, Optional, cast
+from typing import TYPE_CHECKING, Any, cast
from docutils import nodes
from docutils.nodes import Element
@@ -82,7 +82,7 @@ class CitationDomain(Domain):
def resolve_xref(self, env: "BuildEnvironment", fromdocname: str, builder: "Builder",
typ: str, target: str, node: pending_xref, contnode: Element
- ) -> Optional[Element]:
+ ) -> Element | None:
docname, labelid, lineno = self.citations.get(target, ('', '', 0))
if not docname:
return None
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
index e5ae227d0..77b2598ad 100644
--- a/sphinx/domains/cpp.py
+++ b/sphinx/domains/cpp.py
@@ -543,7 +543,7 @@ _id_operator_unary_v2 = {
'!': 'nt', 'not': 'nt',
'~': 'co', 'compl': 'co'
}
-_id_char_from_prefix: dict[Optional[str], str] = {
+_id_char_from_prefix: dict[str | None, str] = {
None: 'c', 'u8': 'c',
'u': 'Ds', 'U': 'Di', 'L': 'w'
}
@@ -1591,7 +1591,7 @@ class ASTBracedInitList(ASTBase):
class ASTAssignmentExpr(ASTExpression):
def __init__(self, leftExpr: ASTExpression, op: str,
- rightExpr: Union[ASTExpression, ASTBracedInitList]):
+ rightExpr: ASTExpression | ASTBracedInitList):
self.leftExpr = leftExpr
self.op = op
self.rightExpr = rightExpr
@@ -1952,7 +1952,7 @@ class ASTTrailingTypeSpecDecltype(ASTTrailingTypeSpec):
class ASTTrailingTypeSpecName(ASTTrailingTypeSpec):
def __init__(self, prefix: str, nestedName: ASTNestedName,
- placeholderType: Optional[str]) -> None:
+ placeholderType: str | None) -> None:
self.prefix = prefix
self.nestedName = nestedName
self.placeholderType = placeholderType
@@ -2028,7 +2028,7 @@ class ASTFunctionParameter(ASTBase):
class ASTNoexceptSpec(ASTBase):
- def __init__(self, expr: Optional[ASTExpression]):
+ def __init__(self, expr: ASTExpression | None):
self.expr = expr
def _stringify(self, transform: StringifyTransform) -> str:
@@ -2047,10 +2047,10 @@ class ASTNoexceptSpec(ASTBase):
class ASTParametersQualifiers(ASTBase):
def __init__(self, args: list[ASTFunctionParameter], volatile: bool, const: bool,
- refQual: Optional[str], exceptionSpec: ASTNoexceptSpec,
+ refQual: str | None, exceptionSpec: ASTNoexceptSpec,
trailingReturn: "ASTType",
override: bool, final: bool, attrs: ASTAttributeList,
- initializer: Optional[str]) -> None:
+ initializer: str | None) -> None:
self.args = args
self.volatile = volatile
self.const = const
@@ -2187,7 +2187,7 @@ class ASTParametersQualifiers(ASTBase):
class ASTExplicitSpec(ASTBase):
- def __init__(self, expr: Optional[ASTExpression]) -> None:
+ def __init__(self, expr: ASTExpression | None) -> None:
self.expr = expr
def _stringify(self, transform: StringifyTransform) -> str:
@@ -2209,7 +2209,7 @@ class ASTExplicitSpec(ASTBase):
class ASTDeclSpecsSimple(ASTBase):
def __init__(self, storage: str, threadLocal: bool, inline: bool, virtual: bool,
- explicitSpec: Optional[ASTExplicitSpec],
+ explicitSpec: ASTExplicitSpec | None,
consteval: bool, constexpr: bool, constinit: bool,
volatile: bool, const: bool, friend: bool,
attrs: ASTAttributeList) -> None:
@@ -3004,7 +3004,7 @@ class ASTDeclaratorParen(ASTDeclarator):
##############################################################################################
class ASTPackExpansionExpr(ASTExpression):
- def __init__(self, expr: Union[ASTExpression, ASTBracedInitList]):
+ def __init__(self, expr: ASTExpression | ASTBracedInitList):
self.expr = expr
def _stringify(self, transform: StringifyTransform) -> str:
@@ -3021,7 +3021,7 @@ class ASTPackExpansionExpr(ASTExpression):
class ASTParenExprList(ASTBaseParenExprList):
- def __init__(self, exprs: list[Union[ASTExpression, ASTBracedInitList]]) -> None:
+ def __init__(self, exprs: list[ASTExpression | ASTBracedInitList]) -> None:
self.exprs = exprs
def get_id(self, version: int) -> str:
@@ -3047,7 +3047,7 @@ class ASTParenExprList(ASTBaseParenExprList):
class ASTInitializer(ASTBase):
- def __init__(self, value: Union[ASTExpression, ASTBracedInitList],
+ def __init__(self, value: ASTExpression | ASTBracedInitList,
hasAssign: bool = True) -> None:
self.value = value
self.hasAssign = hasAssign
@@ -3477,7 +3477,7 @@ class ASTEnum(ASTBase):
class ASTEnumerator(ASTBase):
- def __init__(self, name: ASTNestedName, init: Optional[ASTInitializer],
+ def __init__(self, name: ASTNestedName, init: ASTInitializer | None,
attrs: ASTAttributeList) -> None:
self.name = name
self.init = init
@@ -3648,7 +3648,7 @@ class ASTTemplateParamTemplateType(ASTTemplateParam):
return self.data.get_identifier()
def get_id(
- self, version: int, objectType: Optional[str] = None, symbol: Optional["Symbol"] = None
+ self, version: int, objectType: str | None = None, symbol: Optional["Symbol"] = None
) -> str:
assert version >= 2
# this is not part of the normal name mangling in C++
@@ -3670,8 +3670,7 @@ class ASTTemplateParamTemplateType(ASTTemplateParam):
class ASTTemplateParamNonType(ASTTemplateParam):
def __init__(self,
- param: Union[ASTTypeWithInit,
- ASTTemplateParamConstrainedTypeWithInit],
+ param: ASTTypeWithInit | ASTTemplateParamConstrainedTypeWithInit,
parameterPack: bool = False) -> None:
assert param
self.param = param
@@ -3910,8 +3909,7 @@ class ASTTemplateIntroduction(ASTBase):
class ASTTemplateDeclarationPrefix(ASTBase):
def __init__(self,
- templates: list[Union[ASTTemplateParams,
- ASTTemplateIntroduction]]) -> None:
+ templates: list[ASTTemplateParams | ASTTemplateIntroduction]) -> None:
# templates is None means it's an explicit instantiation of a variable
self.templates = templates
@@ -3966,11 +3964,11 @@ class ASTRequiresClause(ASTBase):
################################################################################
class ASTDeclaration(ASTBase):
- def __init__(self, objectType: str, directiveType: Optional[str] = None,
- visibility: Optional[str] = None,
- templatePrefix: Optional[ASTTemplateDeclarationPrefix] = None,
+ def __init__(self, objectType: str, directiveType: str | None = None,
+ visibility: str | None = None,
+ templatePrefix: ASTTemplateDeclarationPrefix | None = None,
declaration: Any = None,
- trailingRequiresClause: Optional[ASTRequiresClause] = None,
+ trailingRequiresClause: ASTRequiresClause | None = None,
semicolon: bool = False) -> None:
self.objectType = objectType
self.directiveType = directiveType
@@ -4149,7 +4147,7 @@ class ASTNamespace(ASTBase):
class SymbolLookupResult:
def __init__(self, symbols: Iterator["Symbol"], parentSymbol: "Symbol",
- identOrOp: Union[ASTIdentifier, ASTOperator], templateParams: Any,
+ identOrOp: ASTIdentifier | ASTOperator, templateParams: Any,
templateArgs: ASTTemplateArgs) -> None:
self.symbols = symbols
self.parentSymbol = parentSymbol
@@ -4160,13 +4158,12 @@ class SymbolLookupResult:
class LookupKey:
def __init__(self, data: list[tuple[ASTNestedNameElement,
- Union[ASTTemplateParams,
- ASTTemplateIntroduction],
+ ASTTemplateParams | ASTTemplateIntroduction,
str]]) -> None:
self.data = data
-def _is_specialization(templateParams: Union[ASTTemplateParams, ASTTemplateIntroduction],
+def _is_specialization(templateParams: ASTTemplateParams | ASTTemplateIntroduction,
templateArgs: ASTTemplateArgs) -> bool:
# Checks if `templateArgs` does not exactly match `templateParams`.
# the names of the template parameters must be given exactly as args
@@ -4231,14 +4228,14 @@ class Symbol:
return super().__setattr__(key, value)
def __init__(self, parent: Optional["Symbol"],
- identOrOp: Union[ASTIdentifier, ASTOperator, None],
- templateParams: Union[ASTTemplateParams, ASTTemplateIntroduction, None],
- templateArgs: Any, declaration: Optional[ASTDeclaration],
- docname: Optional[str], line: Optional[int]) -> None:
+ identOrOp: ASTIdentifier | ASTOperator | None,
+ templateParams: ASTTemplateParams | ASTTemplateIntroduction | None,
+ templateArgs: Any, declaration: ASTDeclaration | None,
+ docname: str | None, line: int | None) -> None:
self.parent = parent
# declarations in a single directive are linked together
- self.siblingAbove: Optional[Symbol] = None
- self.siblingBelow: Optional[Symbol] = None
+ self.siblingAbove: Symbol | None = None
+ self.siblingBelow: Symbol | None = None
self.identOrOp = identOrOp
# Ensure the same symbol for `A` is created for:
#
@@ -4394,7 +4391,7 @@ class Symbol:
templates.append(False)
return ASTNestedName(names, templates, rooted=False)
- def _find_first_named_symbol(self, identOrOp: Union[ASTIdentifier, ASTOperator],
+ def _find_first_named_symbol(self, identOrOp: ASTIdentifier | ASTOperator,
templateParams: Any, templateArgs: ASTTemplateArgs,
templateShorthand: bool, matchSelf: bool,
recurseInAnon: bool, correctPrimaryTemplateArgs: bool
@@ -4410,7 +4407,7 @@ class Symbol:
except StopIteration:
return None
- def _find_named_symbols(self, identOrOp: Union[ASTIdentifier, ASTOperator],
+ def _find_named_symbols(self, identOrOp: ASTIdentifier | ASTOperator,
templateParams: Any, templateArgs: ASTTemplateArgs,
templateShorthand: bool, matchSelf: bool,
recurseInAnon: bool, correctPrimaryTemplateArgs: bool,
@@ -4500,7 +4497,7 @@ class Symbol:
nestedName: ASTNestedName,
templateDecls: list[Any],
onMissingQualifiedSymbol: Callable[
- ["Symbol", Union[ASTIdentifier, ASTOperator], Any, ASTTemplateArgs], "Symbol"
+ ["Symbol", ASTIdentifier | ASTOperator, Any, ASTTemplateArgs], "Symbol"
],
strictTemplateParamArgLists: bool, ancestorLookupType: str,
templateShorthand: bool, matchSelf: bool,
@@ -4645,7 +4642,7 @@ class Symbol:
Symbol.debug_print(f"location: {docname}:{line}")
def onMissingQualifiedSymbol(parentSymbol: "Symbol",
- identOrOp: Union[ASTIdentifier, ASTOperator],
+ identOrOp: ASTIdentifier | ASTOperator,
templateParams: Any, templateArgs: ASTTemplateArgs
) -> "Symbol":
if Symbol.debug_lookup:
@@ -4954,7 +4951,7 @@ class Symbol:
Symbol.debug_indent -= 1
return res
- def find_identifier(self, identOrOp: Union[ASTIdentifier, ASTOperator],
+ def find_identifier(self, identOrOp: ASTIdentifier | ASTOperator,
matchSelf: bool, recurseInAnon: bool, searchInSiblings: bool
) -> "Symbol":
if Symbol.debug_lookup:
@@ -5050,7 +5047,7 @@ class Symbol:
pass
def onMissingQualifiedSymbol(parentSymbol: "Symbol",
- identOrOp: Union[ASTIdentifier, ASTOperator],
+ identOrOp: ASTIdentifier | ASTOperator,
templateParams: Any,
templateArgs: ASTTemplateArgs) -> "Symbol":
# TODO: Maybe search without template args?
@@ -5116,7 +5113,7 @@ class Symbol:
templateDecls = []
def onMissingQualifiedSymbol(parentSymbol: "Symbol",
- identOrOp: Union[ASTIdentifier, ASTOperator],
+ identOrOp: ASTIdentifier | ASTOperator,
templateParams: Any,
templateArgs: ASTTemplateArgs) -> "Symbol":
return None
@@ -5367,8 +5364,7 @@ class DefinitionParser(BaseParser):
return None
def _parse_initializer_list(self, name: str, open: str, close: str
- ) -> tuple[list[Union[ASTExpression,
- ASTBracedInitList]],
+ ) -> tuple[list[ASTExpression | ASTBracedInitList],
bool]:
# Parse open and close with the actual initializer-list in between
# -> initializer-clause '...'[opt]
@@ -5379,7 +5375,7 @@ class DefinitionParser(BaseParser):
if self.skip_string(close):
return [], False
- exprs: list[Union[ASTExpression, ASTBracedInitList]] = []
+ exprs: list[ASTExpression | ASTBracedInitList] = []
trailingComma = False
while True:
self.skip_ws()
@@ -5413,7 +5409,7 @@ class DefinitionParser(BaseParser):
return None
return ASTParenExprList(exprs)
- def _parse_initializer_clause(self) -> Union[ASTExpression, ASTBracedInitList]:
+ def _parse_initializer_clause(self) -> ASTExpression | ASTBracedInitList:
bracedInitList = self._parse_braced_init_list()
if bracedInitList is not None:
return bracedInitList
@@ -5429,7 +5425,7 @@ class DefinitionParser(BaseParser):
def _parse_expression_list_or_braced_init_list(
self
- ) -> Union[ASTParenExprList, ASTBracedInitList]:
+ ) -> ASTParenExprList | ASTBracedInitList:
paren = self._parse_paren_expression_list()
if paren is not None:
return paren
@@ -5758,7 +5754,7 @@ class DefinitionParser(BaseParser):
return _parse_bin_op_expr(self, 0, inTemplate=inTemplate)
def _parse_conditional_expression_tail(self, orExprHead: ASTExpression,
- inTemplate: bool) -> Optional[ASTConditionalExpr]:
+ inTemplate: bool) -> ASTConditionalExpr | None:
# Consumes the orExprHead on success.
# -> "?" expression ":" assignment-expression
@@ -5917,7 +5913,7 @@ class DefinitionParser(BaseParser):
if self.skip_string('>'):
return ASTTemplateArgs([], False)
prevErrors = []
- templateArgs: list[Union[ASTType, ASTTemplateArgConstant]] = []
+ templateArgs: list[ASTType | ASTTemplateArgConstant] = []
packExpansion = False
while 1:
pos = self.pos
@@ -5983,7 +5979,7 @@ class DefinitionParser(BaseParser):
else:
template = False
templates.append(template)
- identOrOp: Union[ASTIdentifier, ASTOperator] = None
+ identOrOp: ASTIdentifier | ASTOperator = None
if self.skip_word_and_ws('operator'):
identOrOp = self._parse_operator()
else:
@@ -6019,10 +6015,10 @@ class DefinitionParser(BaseParser):
# ==========================================================================
def _parse_simple_type_specifiers(self) -> ASTTrailingTypeSpecFundamental:
- modifier: Optional[str] = None
- signedness: Optional[str] = None
+ modifier: str | None = None
+ signedness: str | None = None
width: list[str] = []
- typ: Optional[str] = None
+ typ: str | None = None
names: list[str] = [] # the parsed sequence
self.skip_ws()
@@ -6368,8 +6364,8 @@ class DefinitionParser(BaseParser):
return ASTDeclSpecs(outer, leftSpecs, rightSpecs, trailing)
def _parse_declarator_name_suffix(
- self, named: Union[bool, str], paramMode: str, typed: bool
- ) -> Union[ASTDeclaratorNameParamQual, ASTDeclaratorNameBitField]:
+ self, named: bool | str, paramMode: str, typed: bool
+ ) -> ASTDeclaratorNameParamQual | ASTDeclaratorNameBitField:
# now we should parse the name, and then suffixes
if named == 'maybe':
pos = self.pos
@@ -6422,7 +6418,7 @@ class DefinitionParser(BaseParser):
return ASTDeclaratorNameParamQual(declId=declId, arrayOps=arrayOps,
paramQual=paramQual)
- def _parse_declarator(self, named: Union[bool, str], paramMode: str,
+ def _parse_declarator(self, named: bool | str, paramMode: str,
typed: bool = True
) -> ASTDeclarator:
# 'typed' here means 'parse return type stuff'
@@ -6586,7 +6582,7 @@ class DefinitionParser(BaseParser):
value = self._parse_expression_fallback(fallbackEnd, parser, allow=allowFallback)
return ASTInitializer(value)
- def _parse_type(self, named: Union[bool, str], outer: str = None) -> ASTType:
+ def _parse_type(self, named: bool | str, outer: str = None) -> ASTType:
"""
named=False|'maybe'|True: 'maybe' is e.g., for function objects which
doesn't need to name the arguments
@@ -6675,8 +6671,8 @@ class DefinitionParser(BaseParser):
return ASTType(declSpecs, decl)
def _parse_type_with_init(
- self, named: Union[bool, str],
- outer: str) -> Union[ASTTypeWithInit, ASTTemplateParamConstrainedTypeWithInit]:
+ self, named: bool | str,
+ outer: str) -> ASTTypeWithInit | ASTTemplateParamConstrainedTypeWithInit:
if outer:
assert outer in ('type', 'member', 'function', 'templateParam')
type = self._parse_type(outer=outer, named=named)
@@ -6930,7 +6926,7 @@ class DefinitionParser(BaseParser):
'Expected ",", or "}".')
return ASTTemplateIntroduction(concept, params)
- def _parse_requires_clause(self) -> Optional[ASTRequiresClause]:
+ def _parse_requires_clause(self) -> ASTRequiresClause | None:
# requires-clause -> 'requires' constraint-logical-or-expression
# constraint-logical-or-expression
# -> constraint-logical-and-expression
@@ -6984,12 +6980,12 @@ class DefinitionParser(BaseParser):
return ASTRequiresClause(ASTBinOpExpr(orExprs, ops))
def _parse_template_declaration_prefix(self, objectType: str
- ) -> Optional[ASTTemplateDeclarationPrefix]:
- templates: list[Union[ASTTemplateParams, ASTTemplateIntroduction]] = []
+ ) -> ASTTemplateDeclarationPrefix | None:
+ templates: list[ASTTemplateParams | ASTTemplateIntroduction] = []
while 1:
self.skip_ws()
# the saved position is only used to provide a better error message
- params: Union[ASTTemplateParams, ASTTemplateIntroduction] = None
+ params: ASTTemplateParams | ASTTemplateIntroduction = None
pos = self.pos
if self.skip_word("template"):
try:
@@ -7047,7 +7043,7 @@ class DefinitionParser(BaseParser):
msg += str(nestedName)
self.warn(msg)
- newTemplates: list[Union[ASTTemplateParams, ASTTemplateIntroduction]] = []
+ newTemplates: list[ASTTemplateParams | ASTTemplateIntroduction] = []
for _i in range(numExtra):
newTemplates.append(ASTTemplateParams([], requiresClause=None))
if templatePrefix and not isMemberInstantiation:
@@ -7129,7 +7125,7 @@ class DefinitionParser(BaseParser):
res.objectType = 'namespace' # type: ignore
return res
- def parse_xref_object(self) -> tuple[Union[ASTNamespace, ASTDeclaration], bool]:
+ def parse_xref_object(self) -> tuple[ASTNamespace | ASTDeclaration, bool]:
pos = self.pos
try:
templatePrefix = self._parse_template_declaration_prefix(objectType="xref")
@@ -7159,7 +7155,7 @@ class DefinitionParser(BaseParser):
msg = "Error in cross-reference."
raise self._make_multi_error(errs, msg) from e2
- def parse_expression(self) -> Union[ASTExpression, ASTType]:
+ def parse_expression(self) -> ASTExpression | ASTType:
pos = self.pos
try:
expr = self._parse_expression()
@@ -7603,7 +7599,7 @@ class AliasTransform(SphinxTransform):
if recurse:
if skipThis:
- childContainer: Union[list[Node], addnodes.desc] = nodes
+ childContainer: list[Node] | addnodes.desc = nodes
else:
content = addnodes.desc_content()
desc = addnodes.desc()
@@ -7950,7 +7946,7 @@ class CPPDomain(Domain):
def _resolve_xref_inner(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
typ: str, target: str, node: pending_xref,
- contnode: Element) -> tuple[Optional[Element], Optional[str]]:
+ contnode: Element) -> tuple[Element | None, str | None]:
# add parens again for those that could be functions
if typ in ('any', 'func'):
target += '()'
@@ -8099,7 +8095,7 @@ class CPPDomain(Domain):
def resolve_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
typ: str, target: str, node: pending_xref, contnode: Element
- ) -> Optional[Element]:
+ ) -> Element | None:
return self._resolve_xref_inner(env, fromdocname, builder, typ,
target, node, contnode)[0]
diff --git a/sphinx/domains/javascript.py b/sphinx/domains/javascript.py
index 89c1d0ec6..89f04d7ad 100644
--- a/sphinx/domains/javascript.py
+++ b/sphinx/domains/javascript.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Any, Iterator, Optional, Tuple, cast
+from typing import Any, Iterator, Tuple, cast
from docutils import nodes
from docutils.nodes import Element, Node
@@ -447,7 +447,7 @@ class JavaScriptDomain(Domain):
def resolve_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
typ: str, target: str, node: pending_xref, contnode: Element
- ) -> Optional[Element]:
+ ) -> Element | None:
mod_name = node.get('js:module')
prefix = node.get('js:object')
searchorder = 1 if node.hasattr('refspecific') else 0
diff --git a/sphinx/domains/math.py b/sphinx/domains/math.py
index dc52d1bfd..9ca3eb030 100644
--- a/sphinx/domains/math.py
+++ b/sphinx/domains/math.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import TYPE_CHECKING, Any, Iterable, Optional
+from typing import TYPE_CHECKING, Any, Iterable
from docutils import nodes
from docutils.nodes import Element, Node, make_id, system_message
@@ -91,7 +91,7 @@ class MathDomain(Domain):
def resolve_xref(self, env: BuildEnvironment, fromdocname: str, builder: "Builder",
typ: str, target: str, node: pending_xref, contnode: Element
- ) -> Optional[Element]:
+ ) -> Element | None:
assert typ in ('eq', 'numref')
docname, number = self.equations.get(target, (None, None))
if docname:
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
index 84fa77e35..3f43f3783 100644
--- a/sphinx/domains/python.py
+++ b/sphinx/domains/python.py
@@ -8,7 +8,7 @@ import inspect
import re
import typing
from inspect import Parameter
-from typing import Any, Iterable, Iterator, List, NamedTuple, Optional, Tuple, cast
+from typing import Any, Iterable, Iterator, List, NamedTuple, Tuple, cast
from docutils import nodes
from docutils.nodes import Element, Node
@@ -98,7 +98,7 @@ def parse_reftarget(reftarget: str, suppress_prefix: bool = False
return reftype, reftarget, title, refspecific
-def type_to_xref(target: str, env: Optional[BuildEnvironment] = None,
+def type_to_xref(target: str, env: BuildEnvironment | None = None,
suppress_prefix: bool = False) -> addnodes.pending_xref:
"""Convert a type string to a cross reference node."""
if env:
@@ -227,7 +227,7 @@ def _parse_annotation(annotation: str, env: BuildEnvironment) -> list[Node]:
def _parse_arglist(
- arglist: str, env: Optional[BuildEnvironment] = None
+ arglist: str, env: BuildEnvironment | None = None
) -> addnodes.desc_parameterlist:
"""Parse a list of arguments using AST parser"""
params = addnodes.desc_parameterlist(arglist)
@@ -1327,7 +1327,7 @@ class PythonDomain(Domain):
def resolve_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
type: str, target: str, node: pending_xref, contnode: Element
- ) -> Optional[Element]:
+ ) -> Element | None:
modname = node.get('py:module')
clsname = node.get('py:class')
searchmode = 1 if node.hasattr('refspecific') else 0
@@ -1432,7 +1432,7 @@ class PythonDomain(Domain):
else:
yield (refname, refname, obj.objtype, obj.docname, obj.node_id, 1)
- def get_full_qualified_name(self, node: Element) -> Optional[str]:
+ def get_full_qualified_name(self, node: Element) -> str | None:
modname = node.get('py:module')
clsname = node.get('py:class')
target = node.get('reftarget')
diff --git a/sphinx/domains/rst.py b/sphinx/domains/rst.py
index 0f6a1950c..b3ce291d7 100644
--- a/sphinx/domains/rst.py
+++ b/sphinx/domains/rst.py
@@ -3,7 +3,7 @@
from __future__ import annotations
import re
-from typing import Any, Iterator, Optional, cast
+from typing import Any, Iterator, cast
from docutils.nodes import Element
from docutils.parsers.rst import directives
@@ -264,7 +264,7 @@ class ReSTDomain(Domain):
def resolve_xref(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
typ: str, target: str, node: pending_xref, contnode: Element
- ) -> Optional[Element]:
+ ) -> Element | None:
objtypes = self.objtypes_for_role(typ)
for objtype in objtypes:
todocname, node_id = self.objects.get((objtype, target), (None, None))
diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py
index 869877545..165ef7d95 100644
--- a/sphinx/domains/std.py
+++ b/sphinx/domains/std.py
@@ -4,8 +4,7 @@ from __future__ import annotations
import re
from copy import copy
-from typing import (TYPE_CHECKING, Any, Callable, Final, Iterable, Iterator, Optional, Union,
- cast)
+from typing import TYPE_CHECKING, Any, Callable, Final, Iterable, Iterator, cast
from docutils import nodes
from docutils.nodes import Element, Node, system_message
@@ -286,9 +285,9 @@ class OptionXRefRole(XRefRole):
return title, target
-def split_term_classifiers(line: str) -> list[Optional[str]]:
+def split_term_classifiers(line: str) -> list[str | None]:
# split line into a term and classifiers. if no classifier, None is used..
- parts: list[Optional[str]] = re.split(' +: +', line) + [None]
+ parts: list[str | None] = re.split(' +: +', line) + [None]
return parts
@@ -565,7 +564,7 @@ class StandardDomain(Domain):
'glossary': Glossary,
'productionlist': ProductionList,
}
- roles: dict[str, Union[RoleFunction, XRefRole]] = {
+ roles: dict[str, RoleFunction | XRefRole] = {
'option': OptionXRefRole(warn_dangling=True),
'envvar': EnvVarXRefRole(),
# links to tokens in grammar productions
@@ -615,7 +614,7 @@ class StandardDomain(Domain):
}
# node_class -> (figtype, title_getter)
- enumerable_nodes: dict[type[Node], tuple[str, Optional[Callable]]] = {
+ enumerable_nodes: dict[type[Node], tuple[str, Callable | None]] = {
nodes.figure: ('figure', None),
nodes.table: ('table', None),
nodes.container: ('code-block', None),
@@ -815,7 +814,7 @@ class StandardDomain(Domain):
def resolve_xref(self, env: "BuildEnvironment", fromdocname: str, builder: "Builder",
typ: str, target: str, node: pending_xref, contnode: Element
- ) -> Optional[Element]:
+ ) -> Element | None:
if typ == 'ref':
resolver = self._resolve_ref_xref
elif typ == 'numref':
@@ -835,7 +834,7 @@ class StandardDomain(Domain):
def _resolve_ref_xref(self, env: "BuildEnvironment", fromdocname: str,
builder: "Builder", typ: str, target: str, node: pending_xref,
- contnode: Element) -> Optional[Element]:
+ contnode: Element) -> Element | None:
if node['refexplicit']:
# reference to anonymous label; the reference uses
# the supplied link caption
@@ -853,7 +852,7 @@ class StandardDomain(Domain):
def _resolve_numref_xref(self, env: "BuildEnvironment", fromdocname: str,
builder: "Builder", typ: str, target: str,
- node: pending_xref, contnode: Element) -> Optional[Element]:
+ node: pending_xref, contnode: Element) -> Element | None:
if target in self.labels:
docname, labelid, figname = self.labels.get(target, ('', '', ''))
else:
@@ -916,7 +915,7 @@ class StandardDomain(Domain):
def _resolve_keyword_xref(self, env: "BuildEnvironment", fromdocname: str,
builder: "Builder", typ: str, target: str,
- node: pending_xref, contnode: Element) -> Optional[Element]:
+ node: pending_xref, contnode: Element) -> Element | None:
# keywords are oddballs: they are referenced by named labels
docname, labelid, _ = self.labels.get(target, ('', '', ''))
if not docname:
@@ -926,7 +925,7 @@ class StandardDomain(Domain):
def _resolve_doc_xref(self, env: "BuildEnvironment", fromdocname: str,
builder: "Builder", typ: str, target: str,
- node: pending_xref, contnode: Element) -> Optional[Element]:
+ node: pending_xref, contnode: Element) -> Element | None:
# directly reference to document by source name; can be absolute or relative
refdoc = node.get('refdoc', fromdocname)
docname = docname_join(refdoc, node['reftarget'])
@@ -943,7 +942,7 @@ class StandardDomain(Domain):
def _resolve_option_xref(self, env: "BuildEnvironment", fromdocname: str,
builder: "Builder", typ: str, target: str,
- node: pending_xref, contnode: Element) -> Optional[Element]:
+ node: pending_xref, contnode: Element) -> Element | None:
progname = node.get('std:program')
target = target.strip()
docname, labelid = self.progoptions.get((progname, target), ('', ''))
@@ -991,7 +990,7 @@ class StandardDomain(Domain):
def _resolve_obj_xref(self, env: "BuildEnvironment", fromdocname: str,
builder: "Builder", typ: str, target: str,
- node: pending_xref, contnode: Element) -> Optional[Element]:
+ node: pending_xref, contnode: Element) -> Element | None:
objtypes = self.objtypes_for_role(typ) or []
for objtype in objtypes:
if (objtype, target) in self.objects:
@@ -1055,7 +1054,7 @@ class StandardDomain(Domain):
def is_enumerable_node(self, node: Node) -> bool:
return node.__class__ in self.enumerable_nodes
- def get_numfig_title(self, node: Node) -> Optional[str]:
+ def get_numfig_title(self, node: Node) -> str | None:
"""Get the title of enumerable nodes to refer them using its title"""
if self.is_enumerable_node(node):
elem = cast(Element, node)
@@ -1069,7 +1068,7 @@ class StandardDomain(Domain):
return None
- def get_enumerable_node_type(self, node: Node) -> Optional[str]:
+ def get_enumerable_node_type(self, node: Node) -> str | None:
"""Get type of enumerable nodes."""
def has_child(node: Element, cls: type) -> bool:
return any(isinstance(child, cls) for child in node)
@@ -1108,7 +1107,7 @@ class StandardDomain(Domain):
# Maybe it is defined in orphaned document.
raise ValueError from exc
- def get_full_qualified_name(self, node: Element) -> Optional[str]:
+ def get_full_qualified_name(self, node: Element) -> str | None:
if node.get('reftype') == 'option':
progname = node.get('std:program')
command = ws_re.split(node.get('reftarget'))
@@ -1124,7 +1123,7 @@ class StandardDomain(Domain):
def warn_missing_reference(app: "Sphinx", domain: Domain, node: pending_xref
- ) -> Optional[bool]:
+ ) -> bool | None:
if (domain and domain.name != 'std') or node['reftype'] != 'ref':
return None
else:
diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py
index 323f018de..47c904d69 100644
--- a/sphinx/environment/__init__.py
+++ b/sphinx/environment/__init__.py
@@ -8,7 +8,7 @@ from collections import defaultdict
from copy import copy
from datetime import datetime
from os import path
-from typing import TYPE_CHECKING, Any, Callable, Generator, Iterator, Optional, Union
+from typing import TYPE_CHECKING, Any, Callable, Generator, Iterator
from docutils import nodes
from docutils.nodes import Node
@@ -70,7 +70,7 @@ CONFIG_CHANGED_REASON = {
}
-versioning_conditions: dict[str, Union[bool, Callable]] = {
+versioning_conditions: dict[str, bool | Callable] = {
'none': False,
'text': is_translatable,
}
@@ -153,7 +153,7 @@ class BuildEnvironment:
self.version: dict[str, str] = None
# the method of doctree versioning; see set_versioning_method
- self.versioning_condition: Union[bool, Callable] = None
+ self.versioning_condition: bool | Callable = None
self.versioning_compare: bool = None
# all the registered domains, set by the application
@@ -307,7 +307,7 @@ class BuildEnvironment:
# Allow to disable by 3rd party extension (workaround)
self.settings.setdefault('smart_quotes', True)
- def set_versioning_method(self, method: Union[str, Callable], compare: bool) -> None:
+ def set_versioning_method(self, method: str | Callable, compare: bool) -> None:
"""This sets the doctree versioning method for this environment.
Versioning methods are a builder property; only builders with the same
@@ -315,7 +315,7 @@ class BuildEnvironment:
raise an exception if the user tries to use an environment with an
incompatible versioning method.
"""
- condition: Union[bool, Callable]
+ condition: bool | Callable
if callable(method):
condition = method
else:
@@ -358,7 +358,7 @@ class BuildEnvironment:
domain.merge_domaindata(docnames, other.domaindata[domainname])
self.events.emit('env-merge-info', self, docnames, other)
- def path2doc(self, filename: str) -> Optional[str]:
+ def path2doc(self, filename: str) -> str | None:
"""Return the docname for the filename if the file is document.
*filename* should be absolute or relative to the source directory.
@@ -373,7 +373,7 @@ class BuildEnvironment:
"""
return self.project.doc2path(docname, base)
- def relfn2path(self, filename: str, docname: Optional[str] = None) -> tuple[str, str]:
+ def relfn2path(self, filename: str, docname: str | None = None) -> tuple[str, str]:
"""Return paths to a file referenced from a document, relative to
documentation root and absolute.
@@ -569,7 +569,7 @@ class BuildEnvironment:
self,
docname: str,
builder: "Builder",
- doctree: Optional[nodes.document] = None,
+ doctree: nodes.document | None = None,
prune_toctrees: bool = True,
includehidden: bool = False
) -> nodes.document:
@@ -596,7 +596,7 @@ class BuildEnvironment:
def resolve_toctree(self, docname: str, builder: "Builder", toctree: addnodes.toctree,
prune: bool = True, maxdepth: int = 0, titles_only: bool = False,
- collapse: bool = False, includehidden: bool = False) -> Optional[Node]:
+ collapse: bool = False, includehidden: bool = False) -> Node | None:
"""Resolve a *toctree* node into individual bullet lists with titles
as items, returning None (if no containing titles are found) or
a new node.
@@ -633,12 +633,12 @@ class BuildEnvironment:
# allow custom references to be resolved
self.events.emit('doctree-resolved', doctree, docname)
- def collect_relations(self) -> dict[str, list[Optional[str]]]:
+ def collect_relations(self) -> dict[str, list[str | None]]:
traversed = set()
def traverse_toctree(
- parent: Optional[str], docname: str
- ) -> Iterator[tuple[Optional[str], str]]:
+ parent: str | None, docname: str
+ ) -> Iterator[tuple[str | None, str]]:
if parent == docname:
logger.warning(__('self referenced toctree found. Ignored.'),
location=docname, type='toc',
diff --git a/sphinx/environment/adapters/indexentries.py b/sphinx/environment/adapters/indexentries.py
index 413d864f9..a2d41abb4 100644
--- a/sphinx/environment/adapters/indexentries.py
+++ b/sphinx/environment/adapters/indexentries.py
@@ -5,7 +5,7 @@ from __future__ import annotations
import re
import unicodedata
from itertools import groupby
-from typing import Any, Optional, cast
+from typing import Any, cast
from sphinx.builders import Builder
from sphinx.domains.index import IndexDomain
@@ -27,8 +27,8 @@ class IndexEntries:
"""Create the real index from the collected index entries."""
new: dict[str, list] = {}
- def add_entry(word: str, subword: str, main: Optional[str], link: bool = True,
- dic: dict[str, list] = new, key: Optional[str] = None) -> None:
+ def add_entry(word: str, subword: str, main: str | None, link: bool = True,
+ dic: dict[str, list] = new, key: str | None = None) -> None:
# Force the word to be unicode if it's a ASCII bytestring.
# This will solve problems with unicode normalization later.
# For instance the RFC role will add bytestrings at the moment
@@ -120,7 +120,7 @@ class IndexEntries:
# (in module foo)
# (in module bar)
oldkey = ''
- oldsubitems: Optional[dict[str, list]] = None
+ oldsubitems: dict[str, list] | None = None
i = 0
while i < len(newlist):
key, (targets, subitems, _key) = newlist[i]
diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py
index be416adbc..84c3e8db6 100644
--- a/sphinx/environment/adapters/toctree.py
+++ b/sphinx/environment/adapters/toctree.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import TYPE_CHECKING, Any, Iterable, Optional, cast
+from typing import TYPE_CHECKING, Any, Iterable, cast
from docutils import nodes
from docutils.nodes import Element, Node
@@ -42,7 +42,7 @@ class TocTree:
def resolve(self, docname: str, builder: "Builder", toctree: addnodes.toctree,
prune: bool = True, maxdepth: int = 0, titles_only: bool = False,
- collapse: bool = False, includehidden: bool = False) -> Optional[Element]:
+ collapse: bool = False, includehidden: bool = False) -> Element | None:
"""Resolve a *toctree* node into individual bullet lists with titles
as items, returning None (if no containing titles are found) or
a new node.
@@ -321,7 +321,7 @@ class TocTree:
return toc
def get_toctree_for(self, docname: str, builder: "Builder", collapse: bool,
- **kwargs: Any) -> Optional[Element]:
+ **kwargs: Any) -> Element | None:
"""Return the global TOC nodetree."""
doctree = self.env.get_doctree(self.env.config.root_doc)
toctrees: list[Element] = []
diff --git a/sphinx/environment/collectors/__init__.py b/sphinx/environment/collectors/__init__.py
index b7fa495fa..396d72cdf 100644
--- a/sphinx/environment/collectors/__init__.py
+++ b/sphinx/environment/collectors/__init__.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import TYPE_CHECKING, Optional
+from typing import TYPE_CHECKING
from docutils import nodes
@@ -21,7 +21,7 @@ class EnvironmentCollector:
entries and toctrees, etc.
"""
- listener_ids: Optional[dict[str, int]] = None
+ listener_ids: dict[str, int] | None = None
def enable(self, app: "Sphinx") -> None:
assert self.listener_ids is None
diff --git a/sphinx/environment/collectors/toctree.py b/sphinx/environment/collectors/toctree.py
index 97715b61f..cdce3b1c2 100644
--- a/sphinx/environment/collectors/toctree.py
+++ b/sphinx/environment/collectors/toctree.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Any, Optional, Sequence, TypeVar, Union, cast
+from typing import Any, Sequence, TypeVar, cast
from docutils import nodes
from docutils.nodes import Element, Node
@@ -57,9 +57,9 @@ class TocTreeCollector(EnvironmentCollector):
numentries = [0] # nonlocal again...
def build_toc(
- node: Union[Element, Sequence[Element]],
+ node: Element | Sequence[Element],
depth: int = 1
- ) -> Optional[nodes.bullet_list]:
+ ) -> nodes.bullet_list | None:
# list of table of contents entries
entries: list[Element] = []
# cache of parents -> list item
@@ -171,7 +171,7 @@ class TocTreeCollector(EnvironmentCollector):
env.toc_secnumbers = {}
def _walk_toc(
- node: Element, secnums: dict, depth: int, titlenode: Optional[nodes.title] = None
+ node: Element, secnums: dict, depth: int, titlenode: nodes.title | None = None
) -> None:
# titlenode is the title of the document, it will get assigned a
# secnumber too, so that it shows up in next/prev/parent rellinks
@@ -250,7 +250,7 @@ class TocTreeCollector(EnvironmentCollector):
env.toc_fignumbers = {}
fignum_counter: dict[str, dict[tuple[int, ...], int]] = {}
- def get_figtype(node: Node) -> Optional[str]:
+ def get_figtype(node: Node) -> str | None:
for domain in env.domains.values():
figtype = domain.get_enumerable_node_type(node)
if (domain.name == 'std'
diff --git a/sphinx/errors.py b/sphinx/errors.py
index db754dd08..a9172e07b 100644
--- a/sphinx/errors.py
+++ b/sphinx/errors.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Any, Optional
+from typing import Any
class SphinxError(Exception):
@@ -42,7 +42,7 @@ class ExtensionError(SphinxError):
"""Extension error."""
def __init__(
- self, message: str, orig_exc: Optional[Exception] = None, modname: Optional[str] = None
+ self, message: str, orig_exc: Exception | None = None, modname: str | None = None
) -> None:
super().__init__(message)
self.message = message
diff --git a/sphinx/ext/apidoc.py b/sphinx/ext/apidoc.py
index 011582d34..e706fb226 100644
--- a/sphinx/ext/apidoc.py
+++ b/sphinx/ext/apidoc.py
@@ -20,7 +20,7 @@ from copy import copy
from fnmatch import fnmatch
from importlib.machinery import EXTENSION_SUFFIXES
from os import path
-from typing import Any, Generator, Optional
+from typing import Any, Generator
import sphinx.locale
from sphinx import __display_version__, package_dir
@@ -59,7 +59,7 @@ def module_join(*modnames: str) -> str:
return '.'.join(filter(None, modnames))
-def is_packagedir(dirname: Optional[str] = None, files: Optional[list[str]] = None) -> bool:
+def is_packagedir(dirname: str | None = None, files: list[str] | None = None) -> bool:
"""Check given *files* contains __init__ file."""
if files is None and dirname is None:
return False
@@ -89,7 +89,7 @@ def write_file(name: str, text: str, opts: Any) -> None:
def create_module_file(package: str, basename: str, opts: Any,
- user_template_dir: Optional[str] = None) -> None:
+ user_template_dir: str | None = None) -> None:
"""Build the text of the file and write the file."""
options = copy(OPTIONS)
if opts.includeprivate and 'private-members' not in options:
@@ -108,7 +108,7 @@ def create_module_file(package: str, basename: str, opts: Any,
def create_package_file(root: str, master_package: str, subroot: str, py_files: list[str],
opts: Any, subs: list[str], is_namespace: bool,
- excludes: list[str] = [], user_template_dir: Optional[str] = None
+ excludes: list[str] = [], user_template_dir: str | None = None
) -> None:
"""Build the text of the file and write the file."""
# build a list of sub packages (directories containing an __init__ file)
@@ -147,7 +147,7 @@ def create_package_file(root: str, master_package: str, subroot: str, py_files:
def create_modules_toc_file(modules: list[str], opts: Any, name: str = 'modules',
- user_template_dir: Optional[str] = None) -> None:
+ user_template_dir: str | None = None) -> None:
"""Create the module's index."""
modules.sort()
prev_module = ''
@@ -233,7 +233,7 @@ def has_child_module(rootpath: str, excludes: list[str], opts: Any) -> bool:
def recurse_tree(rootpath: str, excludes: list[str], opts: Any,
- user_template_dir: Optional[str] = None) -> list[str]:
+ user_template_dir: str | None = None) -> list[str]:
"""
Look for every file in the directory tree and create the corresponding
ReST files.
diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py
index b0419b172..e8fbd3865 100644
--- a/sphinx/ext/autodoc/__init__.py
+++ b/sphinx/ext/autodoc/__init__.py
@@ -10,8 +10,8 @@ from __future__ import annotations
import re
from inspect import Parameter, Signature
from types import ModuleType
-from typing import (TYPE_CHECKING, Any, Callable, Iterator, List, Optional, Sequence, Tuple,
- TypeVar, Union)
+from typing import (TYPE_CHECKING, Any, Callable, Iterator, List, Sequence, Tuple, TypeVar,
+ Union)
from docutils.statemachine import StringList
@@ -81,7 +81,7 @@ INSTANCEATTR = object()
SLOTSATTR = object()
-def members_option(arg: Any) -> Union[object, list[str]]:
+def members_option(arg: Any) -> object | list[str]:
"""Used to convert the :members: option to auto directives."""
if arg in (None, True):
return ALL
@@ -91,7 +91,7 @@ def members_option(arg: Any) -> Union[object, list[str]]:
return [x.strip() for x in arg.split(',') if x.strip()]
-def exclude_members_option(arg: Any) -> Union[object, set[str]]:
+def exclude_members_option(arg: Any) -> object | set[str]:
"""Used to convert the :exclude-members: option."""
if arg in (None, True):
return EMPTY
@@ -108,7 +108,7 @@ def inherited_members_option(arg: Any) -> set[str]:
return set()
-def member_order_option(arg: Any) -> Optional[str]:
+def member_order_option(arg: Any) -> str | None:
"""Used to convert the :member-order: option to auto directives."""
if arg in (None, True):
return None
@@ -118,7 +118,7 @@ def member_order_option(arg: Any) -> Optional[str]:
raise ValueError(__('invalid value for member-order option: %s') % arg)
-def class_doc_from_option(arg: Any) -> Optional[str]:
+def class_doc_from_option(arg: Any) -> str | None:
"""Used to convert the :class-doc-from: option to autoclass directives."""
if arg in ('both', 'class', 'init'):
return arg
@@ -162,7 +162,7 @@ def merge_members_option(options: dict) -> None:
# Some useful event listener factories for autodoc-process-docstring.
-def cut_lines(pre: int, post: int = 0, what: Optional[str] = None) -> Callable:
+def cut_lines(pre: int, post: int = 0, what: str | None = None) -> Callable:
"""Return a listener that removes the first *pre* and last *post*
lines of every docstring. If *what* is a sequence of strings,
only docstrings of a type in *what* will be processed.
@@ -192,7 +192,7 @@ def cut_lines(pre: int, post: int = 0, what: Optional[str] = None) -> Callable:
def between(
marker: str,
- what: Optional[Sequence[str]] = None,
+ what: Sequence[str] | None = None,
keepempty: bool = False,
exclude: bool = False
) -> Callable:
@@ -261,7 +261,7 @@ class ObjectMember(tuple):
def __new__(cls, name: str, obj: Any, **kwargs: Any) -> Any:
return super().__new__(cls, (name, obj)) # type: ignore
- def __init__(self, name: str, obj: Any, docstring: Optional[str] = None,
+ def __init__(self, name: str, obj: Any, docstring: str | None = None,
class_: Any = None, skipped: bool = False) -> None:
self.__name__ = name
self.object = obj
@@ -443,7 +443,7 @@ class Documenter:
return False
return True
- def format_args(self, **kwargs: Any) -> Optional[str]:
+ def format_args(self, **kwargs: Any) -> str | None:
"""Format the argument signature of *self.object*.
Should return None if the object does not have a signature.
@@ -461,7 +461,7 @@ class Documenter:
# directives of course)
return '.'.join(self.objpath) or self.modname
- def _call_format_args(self, **kwargs: Any) -> Optional[str]:
+ def _call_format_args(self, **kwargs: Any) -> str | None:
if kwargs:
try:
return self.format_args(**kwargs)
@@ -529,7 +529,7 @@ class Documenter:
# etc. don't support a prepended module name
self.add_line(' :module: %s' % self.modname, sourcename)
- def get_doc(self) -> Optional[list[list[str]]]:
+ def get_doc(self) -> list[list[str]] | None:
"""Decode and return lines of the docstring(s) for the object.
When it returns None, autodoc-process-docstring will not be called for this
@@ -571,7 +571,7 @@ class Documenter:
else:
return 'docstring of %s' % fullname
- def add_content(self, more_content: Optional[StringList]) -> None:
+ def add_content(self, more_content: StringList | None) -> None:
"""Add content from docstrings, attribute documentation and user."""
docstring = True
@@ -843,8 +843,8 @@ class Documenter:
def generate(
self,
- more_content: Optional[StringList] = None,
- real_modname: Optional[str] = None,
+ more_content: StringList | None = None,
+ real_modname: str | None = None,
check_module: bool = False,
all_members: bool = False
) -> None:
@@ -963,9 +963,9 @@ class ModuleDocumenter(Documenter):
def __init__(self, *args: Any) -> None:
super().__init__(*args)
merge_members_option(self.options)
- self.__all__: Optional[Sequence[str]] = None
+ self.__all__: Sequence[str] | None = None
- def add_content(self, more_content: Optional[StringList]) -> None:
+ def add_content(self, more_content: StringList | None) -> None:
old_indent = self.indent
self.indent += self._extra_indent
super().add_content(None)
@@ -1157,7 +1157,7 @@ class DocstringSignatureMixin:
_new_docstrings: list[list[str]] = None
_signatures: list[str] = None
- def _find_signature(self) -> tuple[Optional[str], Optional[str]]:
+ def _find_signature(self) -> tuple[str | None, str | None]:
# candidates of the object name
valid_names = [self.objpath[-1]] # type: ignore
if isinstance(self, ClassDocumenter):
@@ -1262,7 +1262,7 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
return (inspect.isfunction(member) or inspect.isbuiltin(member) or
(inspect.isroutine(member) and isinstance(parent, ModuleDocumenter)))
- def format_args(self, **kwargs: Any) -> Optional[str]:
+ def format_args(self, **kwargs: Any) -> str | None:
if self.config.autodoc_typehints in ('none', 'description'):
kwargs.setdefault('show_annotation', False)
if self.config.autodoc_typehints_format == "short":
@@ -1345,7 +1345,7 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
return overload.replace(parameters=parameters)
- def annotate_to_first_argument(self, func: Callable, typ: type) -> Optional[Callable]:
+ def annotate_to_first_argument(self, func: Callable, typ: type) -> Callable | None:
"""Annotate type hint to the first argument of function if needed."""
try:
sig = inspect.signature(func, type_aliases=self.config.autodoc_type_aliases)
@@ -1455,7 +1455,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
self.doc_as_attr = True
return ret
- def _get_signature(self) -> tuple[Optional[Any], Optional[str], Optional[Signature]]:
+ def _get_signature(self) -> tuple[Any | None, str | None, Signature | None]:
def get_user_defined_function_or_method(obj: Any, attr: str) -> Any:
""" Get the `attr` function or method from `obj`, if it is user-defined. """
if inspect.is_builtin_class_method(obj, attr):
@@ -1533,7 +1533,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
# with __init__ in C and no `__text_signature__`.
return None, None, None
- def format_args(self, **kwargs: Any) -> Optional[str]:
+ def format_args(self, **kwargs: Any) -> str | None:
if self.config.autodoc_typehints in ('none', 'description'):
kwargs.setdefault('show_annotation', False)
if self.config.autodoc_typehints_format == "short":
@@ -1615,7 +1615,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
return []
- def get_canonical_fullname(self) -> Optional[str]:
+ def get_canonical_fullname(self) -> str | None:
__modname__ = safe_getattr(self.object, '__module__', self.modname)
__qualname__ = safe_getattr(self.object, '__qualname__', None)
if __qualname__ is None:
@@ -1687,7 +1687,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
else:
return False, [m for m in members.values() if m.class_ == self.object]
- def get_doc(self) -> Optional[list[list[str]]]:
+ def get_doc(self) -> list[list[str]] | None:
if self.doc_as_attr:
# Don't show the docstring of the class when it is an alias.
comment = self.get_variable_comment()
@@ -1739,7 +1739,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
tab_width = self.directive.state.document.settings.tab_width
return [prepare_docstring(docstring, tab_width) for docstring in docstrings]
- def get_variable_comment(self) -> Optional[list[str]]:
+ def get_variable_comment(self) -> list[str] | None:
try:
key = ('', '.'.join(self.objpath))
if self.doc_as_attr:
@@ -1751,7 +1751,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
except PycodeError:
return None
- def add_content(self, more_content: Optional[StringList]) -> None:
+ def add_content(self, more_content: StringList | None) -> None:
if self.doc_as_attr and self.modname != self.get_real_modname():
try:
# override analyzer to obtain doccomment around its definition.
@@ -1779,8 +1779,8 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
def generate(
self,
- more_content: Optional[StringList] = None,
- real_modname: Optional[str] = None,
+ more_content: StringList | None = None,
+ real_modname: str | None = None,
check_module: bool = False,
all_members: bool = False
) -> None:
@@ -1888,7 +1888,7 @@ class TypeVarMixin(DataDocumenterMixinBase):
return (isinstance(self.object, TypeVar) or
super().should_suppress_directive_header())
- def get_doc(self) -> Optional[list[list[str]]]:
+ def get_doc(self) -> list[list[str]] | None:
if isinstance(self.object, TypeVar):
if self.object.__doc__ != TypeVar.__doc__:
return super().get_doc() # type: ignore
@@ -1956,7 +1956,7 @@ class UninitializedGlobalVariableMixin(DataDocumenterMixinBase):
return (self.object is UNINITIALIZED_ATTR or
super().should_suppress_value_header())
- def get_doc(self) -> Optional[list[list[str]]]:
+ def get_doc(self) -> list[list[str]] | None:
if self.object is UNINITIALIZED_ATTR:
return []
else:
@@ -2050,7 +2050,7 @@ class DataDocumenter(GenericAliasMixin, NewTypeMixin, TypeVarMixin,
real_modname = self.get_attr(self.parent or self.object, '__module__', None)
return real_modname or self.modname
- def get_module_comment(self, attrname: str) -> Optional[list[str]]:
+ def get_module_comment(self, attrname: str) -> list[str] | None:
try:
analyzer = ModuleAnalyzer.for_module(self.modname)
analyzer.analyze()
@@ -2062,7 +2062,7 @@ class DataDocumenter(GenericAliasMixin, NewTypeMixin, TypeVarMixin,
return None
- def get_doc(self) -> Optional[list[list[str]]]:
+ def get_doc(self) -> list[list[str]] | None:
# Check the variable has a docstring-comment
comment = self.get_module_comment(self.objpath[-1])
if comment:
@@ -2070,7 +2070,7 @@ class DataDocumenter(GenericAliasMixin, NewTypeMixin, TypeVarMixin,
else:
return super().get_doc()
- def add_content(self, more_content: Optional[StringList]) -> None:
+ def add_content(self, more_content: StringList | None) -> None:
# Disable analyzing variable comment on Documenter.add_content() to control it on
# DataDocumenter.add_content()
self.analyzer = None
@@ -2131,7 +2131,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
return ret
- def format_args(self, **kwargs: Any) -> Optional[str]:
+ def format_args(self, **kwargs: Any) -> str | None:
if self.config.autodoc_typehints in ('none', 'description'):
kwargs.setdefault('show_annotation', False)
if self.config.autodoc_typehints_format == "short":
@@ -2247,7 +2247,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
return overload.replace(parameters=parameters)
- def annotate_to_first_argument(self, func: Callable, typ: type) -> Optional[Callable]:
+ def annotate_to_first_argument(self, func: Callable, typ: type) -> Callable | None:
"""Annotate type hint to the first argument of function if needed."""
try:
sig = inspect.signature(func, type_aliases=self.config.autodoc_type_aliases)
@@ -2276,7 +2276,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
return func
- def get_doc(self) -> Optional[list[list[str]]]:
+ def get_doc(self) -> list[list[str]] | None:
if self._new_docstrings is not None:
# docstring already returned previously, then modified by
# `DocstringSignatureMixin`. Just return the previously-computed
@@ -2335,7 +2335,7 @@ class NonDataDescriptorMixin(DataDocumenterMixinBase):
return (not getattr(self, 'non_data_descriptor', False) or
super().should_suppress_directive_header())
- def get_doc(self) -> Optional[list[list[str]]]:
+ def get_doc(self) -> list[list[str]] | None:
if getattr(self, 'non_data_descriptor', False):
# the docstring of non datadescriptor is very probably the wrong thing
# to display
@@ -2373,7 +2373,7 @@ class SlotsMixin(DataDocumenterMixinBase):
else:
return super().should_suppress_value_header()
- def get_doc(self) -> Optional[list[list[str]]]:
+ def get_doc(self) -> list[list[str]] | None:
if self.object is SLOTSATTR:
try:
__slots__ = inspect.getslots(self.parent)
@@ -2462,7 +2462,7 @@ class RuntimeInstanceAttributeMixin(DataDocumenterMixinBase):
return (self.object is self.RUNTIME_INSTANCE_ATTRIBUTE or
super().should_suppress_value_header())
- def get_doc(self) -> Optional[list[list[str]]]:
+ def get_doc(self) -> list[list[str]] | None:
if (self.object is self.RUNTIME_INSTANCE_ATTRIBUTE and
self.is_runtime_instance_attribute_not_commented(self.parent)):
return None
@@ -2518,7 +2518,7 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
return (self.object is UNINITIALIZED_ATTR or
super().should_suppress_value_header())
- def get_doc(self) -> Optional[list[list[str]]]:
+ def get_doc(self) -> list[list[str]] | None:
if self.object is UNINITIALIZED_ATTR:
return None
else:
@@ -2638,7 +2638,7 @@ class AttributeDocumenter(GenericAliasMixin, NewTypeMixin, SlotsMixin, # type:
except ValueError:
pass
- def get_attribute_comment(self, parent: Any, attrname: str) -> Optional[list[str]]:
+ def get_attribute_comment(self, parent: Any, attrname: str) -> list[str] | None:
for cls in inspect.getmro(parent):
try:
module = safe_getattr(cls, '__module__')
@@ -2655,7 +2655,7 @@ class AttributeDocumenter(GenericAliasMixin, NewTypeMixin, SlotsMixin, # type:
return None
- def get_doc(self) -> Optional[list[list[str]]]:
+ def get_doc(self) -> list[list[str]] | None:
# Check the attribute has a docstring-comment
comment = self.get_attribute_comment(self.parent, self.objpath[-1])
if comment:
@@ -2671,7 +2671,7 @@ class AttributeDocumenter(GenericAliasMixin, NewTypeMixin, SlotsMixin, # type:
finally:
self.config.autodoc_inherit_docstrings = orig # type: ignore
- def add_content(self, more_content: Optional[StringList]) -> None:
+ def add_content(self, more_content: StringList | None) -> None:
# Disable analyzing attribute comment on Documenter.add_content() to control it on
# AttributeDocumenter.add_content()
self.analyzer = None
diff --git a/sphinx/ext/autodoc/directive.py b/sphinx/ext/autodoc/directive.py
index ff0a3eb05..8bc075068 100644
--- a/sphinx/ext/autodoc/directive.py
+++ b/sphinx/ext/autodoc/directive.py
@@ -1,6 +1,6 @@
from __future__ import annotations
-from typing import Any, Callable, Optional
+from typing import Any, Callable
from docutils import nodes
from docutils.nodes import Element, Node
@@ -42,7 +42,7 @@ class DummyOptionSpec(dict):
class DocumenterBridge:
"""A parameters container for Documenters."""
- def __init__(self, env: BuildEnvironment, reporter: Optional[Reporter], options: Options,
+ def __init__(self, env: BuildEnvironment, reporter: Reporter | None, options: Options,
lineno: int, state: Any) -> None:
self.env = env
self._reporter = reporter
diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py
index b1c0b4ebd..5fa95edcd 100644
--- a/sphinx/ext/autodoc/importer.py
+++ b/sphinx/ext/autodoc/importer.py
@@ -5,7 +5,7 @@ from __future__ import annotations
import importlib
import traceback
import warnings
-from typing import TYPE_CHECKING, Any, Callable, NamedTuple, Optional
+from typing import TYPE_CHECKING, Any, Callable, NamedTuple
from sphinx.ext.autodoc.mock import ismock, undecorate
from sphinx.pycode import ModuleAnalyzer, PycodeError
@@ -30,7 +30,7 @@ def mangle(subject: Any, name: str) -> str:
return name
-def unmangle(subject: Any, name: str) -> Optional[str]:
+def unmangle(subject: Any, name: str) -> str | None:
"""Unmangle the given name."""
try:
if isclass(subject) and not name.endswith('__'):
@@ -147,7 +147,7 @@ def get_object_members(
subject: Any,
objpath: list[str],
attrgetter: Callable,
- analyzer: Optional[ModuleAnalyzer] = None
+ analyzer: ModuleAnalyzer | None = None
) -> dict[str, Attribute]:
"""Get members and attributes of target object."""
from sphinx.ext.autodoc import INSTANCEATTR
diff --git a/sphinx/ext/autodoc/mock.py b/sphinx/ext/autodoc/mock.py
index b5690236f..6bc2e8f1e 100644
--- a/sphinx/ext/autodoc/mock.py
+++ b/sphinx/ext/autodoc/mock.py
@@ -8,7 +8,7 @@ import sys
from importlib.abc import Loader, MetaPathFinder
from importlib.machinery import ModuleSpec
from types import MethodType, ModuleType
-from typing import Any, Generator, Iterator, Optional, Sequence, Union
+from typing import Any, Generator, Iterator, Sequence
from sphinx.util import logging
from sphinx.util.inspect import isboundmethod, safe_getattr
@@ -116,8 +116,8 @@ class MockFinder(MetaPathFinder):
self.loader = MockLoader(self)
self.mocked_modules: list[str] = []
- def find_spec(self, fullname: str, path: Optional[Sequence[Union[bytes, str]]],
- target: ModuleType = None) -> Optional[ModuleSpec]:
+ def find_spec(self, fullname: str, path: Sequence[bytes | str] | None,
+ target: ModuleType = None) -> ModuleSpec | None:
for modname in self.modnames:
# check if fullname is (or is a descendant of) one of our targets
if modname == fullname or fullname.startswith(modname + '.'):
diff --git a/sphinx/ext/autodoc/preserve_defaults.py b/sphinx/ext/autodoc/preserve_defaults.py
index 3c455f76b..6571f8189 100644
--- a/sphinx/ext/autodoc/preserve_defaults.py
+++ b/sphinx/ext/autodoc/preserve_defaults.py
@@ -8,7 +8,7 @@ from __future__ import annotations
import ast
import inspect
-from typing import Any, Optional
+from typing import Any
import sphinx
from sphinx.application import Sphinx
@@ -27,7 +27,7 @@ class DefaultValue:
return self.name
-def get_function_def(obj: Any) -> Optional[ast.FunctionDef]:
+def get_function_def(obj: Any) -> ast.FunctionDef | None:
"""Get FunctionDef object from living object.
This tries to parse original code for living object and returns
AST node for given *obj*.
@@ -46,7 +46,7 @@ def get_function_def(obj: Any) -> Optional[ast.FunctionDef]:
return None
-def get_default_value(lines: list[str], position: ast.AST) -> Optional[str]:
+def get_default_value(lines: list[str], position: ast.AST) -> str | None:
try:
if position.lineno == position.end_lineno:
line = lines[position.lineno - 1]
diff --git a/sphinx/ext/autodoc/type_comment.py b/sphinx/ext/autodoc/type_comment.py
index e8e5cc2da..8e16aaa92 100644
--- a/sphinx/ext/autodoc/type_comment.py
+++ b/sphinx/ext/autodoc/type_comment.py
@@ -4,7 +4,7 @@ from __future__ import annotations
import ast
from inspect import Parameter, Signature, getsource
-from typing import Any, Optional, cast
+from typing import Any, cast
import sphinx
from sphinx.application import Sphinx
@@ -76,7 +76,7 @@ def signature_from_ast(node: ast.FunctionDef, bound_method: bool,
return Signature(params)
-def get_type_comment(obj: Any, bound_method: bool = False) -> Optional[Signature]:
+def get_type_comment(obj: Any, bound_method: bool = False) -> Signature | None:
"""Get type_comment'ed FunctionDef object from living object.
This tries to parse original code for living object and returns
diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py
index f169b2416..be8187624 100644
--- a/sphinx/ext/autosummary/__init__.py
+++ b/sphinx/ext/autosummary/__init__.py
@@ -57,7 +57,7 @@ import warnings
from inspect import Parameter
from os import path
from types import ModuleType
-from typing import Any, List, Optional, Sequence, cast
+from typing import Any, List, Sequence, cast
from docutils import nodes
from docutils.nodes import Node, system_message
@@ -265,7 +265,7 @@ class Autosummary(SphinxDirective):
return nodes
def import_by_name(
- self, name: str, prefixes: list[Optional[str]]
+ self, name: str, prefixes: list[str | None]
) -> tuple[str, Any, Any, str]:
with mock(self.config.autosummary_mock_imports):
try:
@@ -595,17 +595,17 @@ class ImportExceptionGroup(Exception):
It contains an error messages and a list of exceptions as its arguments.
"""
- def __init__(self, message: Optional[str], exceptions: Sequence[BaseException]):
+ def __init__(self, message: str | None, exceptions: Sequence[BaseException]):
super().__init__(message)
self.exceptions = list(exceptions)
-def get_import_prefixes_from_env(env: BuildEnvironment) -> list[Optional[str]]:
+def get_import_prefixes_from_env(env: BuildEnvironment) -> list[str | None]:
"""
Obtain current Python import prefixes (for `import_by_name`)
from ``document.env``
"""
- prefixes: list[Optional[str]] = [None]
+ prefixes: list[str | None] = [None]
currmodule = env.ref_context.get('py:module')
if currmodule:
@@ -622,7 +622,7 @@ def get_import_prefixes_from_env(env: BuildEnvironment) -> list[Optional[str]]:
def import_by_name(
- name: str, prefixes: list[Optional[str]] = [None], grouped_exception: bool = True
+ name: str, prefixes: list[str | None] = [None], grouped_exception: bool = True
) -> tuple[str, Any, Any, str]:
"""Import a Python object that has the given *name*, under one of the
*prefixes*. The first name that succeeds is used.
@@ -703,7 +703,7 @@ def _import_by_name(name: str, grouped_exception: bool = True) -> tuple[Any, Any
raise ImportError(*exc.args) from exc
-def import_ivar_by_name(name: str, prefixes: list[Optional[str]] = [None],
+def import_ivar_by_name(name: str, prefixes: list[str | None] = [None],
grouped_exception: bool = True) -> tuple[str, Any, Any, str]:
"""Import an instance variable that has the given *name*, under one of the
*prefixes*. The first name that succeeds is used.
@@ -754,7 +754,7 @@ class AutoLink(SphinxRole):
return objects, errors
-def get_rst_suffix(app: Sphinx) -> Optional[str]:
+def get_rst_suffix(app: Sphinx) -> str | None:
def get_supported_format(suffix: str) -> tuple[str, ...]:
parser_class = app.registry.get_source_parsers().get(suffix)
if parser_class is None:
diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py
index 4322c64d2..4681fe3ec 100644
--- a/sphinx/ext/autosummary/generate.py
+++ b/sphinx/ext/autosummary/generate.py
@@ -24,7 +24,7 @@ import re
import sys
from gettext import NullTranslations
from os import path
-from typing import Any, NamedTuple, Optional, Sequence
+from typing import Any, NamedTuple, Sequence
from jinja2 import TemplateNotFound
from jinja2.sandbox import SandboxedEnvironment
@@ -214,8 +214,8 @@ def generate_autosummary_content(name: str, obj: Any, parent: Any,
template: AutosummaryRenderer, template_name: str,
imported_members: bool, app: Any,
recursive: bool, context: dict,
- modname: Optional[str] = None,
- qualname: Optional[str] = None) -> str:
+ modname: str | None = None,
+ qualname: str | None = None) -> str:
doc = get_documenter(app, obj, parent)
def skip_member(obj: Any, name: str, objtype: str) -> bool:
@@ -354,8 +354,8 @@ def generate_autosummary_content(name: str, obj: Any, parent: Any,
return template.render(doc.objtype, ns)
-def generate_autosummary_docs(sources: list[str], output_dir: Optional[str] = None,
- suffix: str = '.rst', base_path: Optional[str] = None,
+def generate_autosummary_docs(sources: list[str], output_dir: str | None = None,
+ suffix: str = '.rst', base_path: str | None = None,
imported_members: bool = False, app: Any = None,
overwrite: bool = True, encoding: str = 'utf-8') -> None:
showed_sources = sorted(sources)
@@ -460,7 +460,7 @@ def find_autosummary_in_files(filenames: list[str]) -> list[AutosummaryEntry]:
def find_autosummary_in_docstring(
- name: str, filename: Optional[str] = None
+ name: str, filename: str | None = None
) -> list[AutosummaryEntry]:
"""Find out what items are documented in the given object's docstring.
@@ -482,7 +482,7 @@ def find_autosummary_in_docstring(
def find_autosummary_in_lines(
- lines: list[str], module: Optional[str] = None, filename: Optional[str] = None
+ lines: list[str], module: str | None = None, filename: str | None = None
) -> list[AutosummaryEntry]:
"""Find out what items appear in autosummary:: directives in the
given lines.
@@ -507,7 +507,7 @@ def find_autosummary_in_lines(
documented: list[AutosummaryEntry] = []
recursive = False
- toctree: Optional[str] = None
+ toctree: str | None = None
template = None
current_module = module
in_autosummary = False
diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py
index 7eeb5e0d3..650ed8a3f 100644
--- a/sphinx/ext/doctest.py
+++ b/sphinx/ext/doctest.py
@@ -11,7 +11,7 @@ import sys
import time
from io import StringIO
from os import path
-from typing import TYPE_CHECKING, Any, Callable, Iterable, Optional, Sequence
+from typing import TYPE_CHECKING, Any, Callable, Iterable, Sequence
from docutils import nodes
from docutils.nodes import Element, Node, TextElement
@@ -220,7 +220,7 @@ class TestGroup:
class TestCode:
def __init__(self, code: str, type: str, filename: str,
- lineno: int, options: Optional[dict] = None) -> None:
+ lineno: int, options: dict | None = None) -> None:
self.code = code
self.type = type
self.filename = filename
@@ -312,7 +312,7 @@ class DocTestBuilder(Builder):
logger.info(text, nonl=True)
self.outfile.write(text)
- def get_target_uri(self, docname: str, typ: Optional[str] = None) -> str:
+ def get_target_uri(self, docname: str, typ: str | None = None) -> str:
return ''
def get_outdated_docs(self) -> set[str]:
@@ -361,7 +361,7 @@ Doctest summary
return filename
@staticmethod
- def get_line_number(node: Node) -> Optional[int]:
+ def get_line_number(node: Node) -> int | None:
"""Get the real line number or admit we don't know."""
# TODO: Work out how to store or calculate real (file-relative)
# line numbers for doctest blocks in docstrings.
diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py
index 8e7e5828c..b9b2c1558 100644
--- a/sphinx/ext/graphviz.py
+++ b/sphinx/ext/graphviz.py
@@ -8,7 +8,7 @@ import re
import subprocess
from os import path
from subprocess import CalledProcessError
-from typing import Any, Optional
+from typing import Any
from docutils import nodes
from docutils.nodes import Node
@@ -44,7 +44,7 @@ class ClickableMapDefinition:
href_re = re.compile('href=".*?"')
def __init__(self, filename: str, content: str, dot: str = '') -> None:
- self.id: Optional[str] = None
+ self.id: str | None = None
self.filename = filename
self.content = content.splitlines()
self.clickable: list[str] = []
@@ -212,8 +212,8 @@ class GraphvizSimple(SphinxDirective):
def render_dot(self: SphinxTranslator, code: str, options: dict, format: str,
- prefix: str = 'graphviz', filename: Optional[str] = None
- ) -> tuple[Optional[str], Optional[str]]:
+ prefix: str = 'graphviz', filename: str | None = None
+ ) -> tuple[str | None, str | None]:
"""Render graphviz code into a PNG or PDF output file."""
graphviz_dot = options.get('graphviz_dot', self.builder.config.graphviz_dot)
hashkey = (code + str(options) + str(graphviz_dot) +
@@ -265,8 +265,8 @@ def render_dot(self: SphinxTranslator, code: str, options: dict, format: str,
def render_dot_html(self: HTML5Translator, node: graphviz, code: str, options: dict,
- prefix: str = 'graphviz', imgcls: Optional[str] = None,
- alt: Optional[str] = None, filename: Optional[str] = None
+ prefix: str = 'graphviz', imgcls: str | None = None,
+ alt: str | None = None, filename: str | None = None
) -> tuple[str, str]:
format = self.builder.config.graphviz_output_format
try:
@@ -322,7 +322,7 @@ def html_visit_graphviz(self: HTML5Translator, node: graphviz) -> None:
def render_dot_latex(self: LaTeXTranslator, node: graphviz, code: str,
- options: dict, prefix: str = 'graphviz', filename: Optional[str] = None
+ options: dict, prefix: str = 'graphviz', filename: str | None = None
) -> None:
try:
fname, outfn = render_dot(self, code, options, 'pdf', prefix, filename)
diff --git a/sphinx/ext/imgmath.py b/sphinx/ext/imgmath.py
index 2af25788b..d3a6a25d2 100644
--- a/sphinx/ext/imgmath.py
+++ b/sphinx/ext/imgmath.py
@@ -9,7 +9,7 @@ import subprocess
import tempfile
from os import path
from subprocess import CalledProcessError
-from typing import Any, Optional
+from typing import Any
from docutils import nodes
from docutils.nodes import Element
@@ -39,7 +39,7 @@ class MathExtError(SphinxError):
category = 'Math extension error'
def __init__(
- self, msg: str, stderr: Optional[str] = None, stdout: Optional[str] = None
+ self, msg: str, stderr: str | None = None, stdout: str | None = None
) -> None:
if stderr:
msg += '\n[stderr]\n' + stderr
@@ -59,7 +59,7 @@ depthsvg_re = re.compile(r'.*, depth=(.*)pt')
depthsvgcomment_re = re.compile(r'<!-- DEPTH=(-?\d+) -->')
-def read_svg_depth(filename: str) -> Optional[int]:
+def read_svg_depth(filename: str) -> int | None:
"""Read the depth from comment at last line of SVG file
"""
with open(filename, encoding="utf-8") as f:
@@ -158,7 +158,7 @@ def convert_dvi_to_image(command: list[str], name: str) -> tuple[str, str]:
raise MathExtError('%s exited with error' % name, exc.stderr, exc.stdout) from exc
-def convert_dvi_to_png(dvipath: str, builder: Builder, out_path: str) -> Optional[int]:
+def convert_dvi_to_png(dvipath: str, builder: Builder, out_path: str) -> int | None:
"""Convert DVI file to PNG image."""
name = 'dvipng'
command = [builder.config.imgmath_dvipng, '-o', out_path, '-T', 'tight', '-z9']
@@ -181,7 +181,7 @@ def convert_dvi_to_png(dvipath: str, builder: Builder, out_path: str) -> Optiona
return depth
-def convert_dvi_to_svg(dvipath: str, builder: Builder, out_path: str) -> Optional[int]:
+def convert_dvi_to_svg(dvipath: str, builder: Builder, out_path: str) -> int | None:
"""Convert DVI file to SVG image."""
name = 'dvisvgm'
command = [builder.config.imgmath_dvisvgm, '-o', out_path]
@@ -205,7 +205,7 @@ def convert_dvi_to_svg(dvipath: str, builder: Builder, out_path: str) -> Optiona
def render_math(
self: HTML5Translator,
math: str,
-) -> tuple[Optional[str], Optional[int]]:
+) -> tuple[str | None, int | None]:
"""Render the LaTeX math expression *math* using latex and dvipng or
dvisvgm.
diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py
index b83cc437f..e134bd753 100644
--- a/sphinx/ext/inheritance_diagram.py
+++ b/sphinx/ext/inheritance_diagram.py
@@ -34,7 +34,7 @@ import builtins
import inspect
import re
from importlib import import_module
-from typing import Any, Iterable, Optional, cast
+from typing import Any, Iterable, cast
from docutils import nodes
from docutils.nodes import Node
@@ -134,7 +134,7 @@ class InheritanceGraph:
"""
def __init__(self, class_names: list[str], currmodule: str, show_builtins: bool = False,
private_bases: bool = False, parts: int = 0,
- aliases: Optional[dict[str, str]] = None, top_classes: list[Any] = []
+ aliases: dict[str, str] | None = None, top_classes: list[Any] = []
) -> None:
"""*class_names* is a list of child classes to show bases from.
@@ -216,7 +216,7 @@ class InheritanceGraph:
return list(all_classes.values())
def class_name(
- self, cls: Any, parts: int = 0, aliases: Optional[dict[str, str]] = None
+ self, cls: Any, parts: int = 0, aliases: dict[str, str] | None = None
) -> str:
"""Given a class object, return a fully-qualified name.
@@ -268,7 +268,7 @@ class InheritanceGraph:
return ''.join(['%s=%s;\n' % x for x in sorted(attrs.items())])
def generate_dot(self, name: str, urls: dict[str, str] = {},
- env: Optional[BuildEnvironment] = None,
+ env: BuildEnvironment | None = None,
graph_attrs: dict = {}, node_attrs: dict = {}, edge_attrs: dict = {}
) -> str:
"""Generate a graphviz dot graph from the classes that were passed in
diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py
index cd29bbdc5..f501867ff 100644
--- a/sphinx/ext/intersphinx.py
+++ b/sphinx/ext/intersphinx.py
@@ -26,7 +26,7 @@ import sys
import time
from os import path
from types import ModuleType
-from typing import IO, Any, Optional, cast
+from typing import IO, Any, cast
from urllib.parse import urlsplit, urlunsplit
from docutils import nodes
@@ -100,7 +100,7 @@ def _strip_basic_auth(url: str) -> str:
return urlunsplit(frags)
-def _read_from_url(url: str, config: Optional[Config] = None) -> IO:
+def _read_from_url(url: str, config: Config | None = None) -> IO:
"""Reads data from *url* with an HTTP *GET*.
This function supports fetching from resources which use basic HTTP auth as
@@ -259,7 +259,7 @@ def load_mappings(app: Sphinx) -> None:
inventories.main_inventory.setdefault(type, {}).update(objects)
-def _create_element_from_result(domain: Domain, inv_name: Optional[str],
+def _create_element_from_result(domain: Domain, inv_name: str | None,
data: InventoryItem,
node: pending_xref, contnode: TextElement) -> Element:
proj, version, uri, dispname = data
@@ -290,10 +290,10 @@ def _create_element_from_result(domain: Domain, inv_name: Optional[str],
def _resolve_reference_in_domain_by_target(
- inv_name: Optional[str], inventory: Inventory,
+ inv_name: str | None, inventory: Inventory,
domain: Domain, objtypes: list[str],
target: str,
- node: pending_xref, contnode: TextElement) -> Optional[Element]:
+ node: pending_xref, contnode: TextElement) -> Element | None:
for objtype in objtypes:
if objtype not in inventory:
# Continue if there's nothing of this kind in the inventory
@@ -322,11 +322,11 @@ def _resolve_reference_in_domain_by_target(
def _resolve_reference_in_domain(env: BuildEnvironment,
- inv_name: Optional[str], inventory: Inventory,
+ inv_name: str | None, inventory: Inventory,
honor_disabled_refs: bool,
domain: Domain, objtypes: list[str],
node: pending_xref, contnode: TextElement
- ) -> Optional[Element]:
+ ) -> Element | None:
# we adjust the object types for backwards compatibility
if domain.name == 'std' and 'cmdoption' in objtypes:
# until Sphinx-1.6, cmdoptions are stored as std:option
@@ -357,9 +357,9 @@ def _resolve_reference_in_domain(env: BuildEnvironment,
full_qualified_name, node, contnode)
-def _resolve_reference(env: BuildEnvironment, inv_name: Optional[str], inventory: Inventory,
+def _resolve_reference(env: BuildEnvironment, inv_name: str | None, inventory: Inventory,
honor_disabled_refs: bool,
- node: pending_xref, contnode: TextElement) -> Optional[Element]:
+ node: pending_xref, contnode: TextElement) -> Element | None:
# disabling should only be done if no inventory is given
honor_disabled_refs = honor_disabled_refs and inv_name is None
@@ -405,7 +405,7 @@ def inventory_exists(env: BuildEnvironment, inv_name: str) -> bool:
def resolve_reference_in_inventory(env: BuildEnvironment,
inv_name: str,
node: pending_xref, contnode: TextElement
- ) -> Optional[Element]:
+ ) -> Element | None:
"""Attempt to resolve a missing reference via intersphinx references.
Resolution is tried in the given inventory with the target as is.
@@ -420,7 +420,7 @@ def resolve_reference_in_inventory(env: BuildEnvironment,
def resolve_reference_any_inventory(env: BuildEnvironment,
honor_disabled_refs: bool,
node: pending_xref, contnode: TextElement
- ) -> Optional[Element]:
+ ) -> Element | None:
"""Attempt to resolve a missing reference via intersphinx references.
Resolution is tried with the target as is in any inventory.
@@ -432,7 +432,7 @@ def resolve_reference_any_inventory(env: BuildEnvironment,
def resolve_reference_detect_inventory(env: BuildEnvironment,
node: pending_xref, contnode: TextElement
- ) -> Optional[Element]:
+ ) -> Element | None:
"""Attempt to resolve a missing reference via intersphinx references.
Resolution is tried first with the target as is in any inventory.
@@ -460,7 +460,7 @@ def resolve_reference_detect_inventory(env: BuildEnvironment,
def missing_reference(app: Sphinx, env: BuildEnvironment, node: pending_xref,
- contnode: TextElement) -> Optional[Element]:
+ contnode: TextElement) -> Element | None:
"""Attempt to resolve a missing reference via intersphinx references."""
return resolve_reference_detect_inventory(env, node, contnode)
@@ -511,7 +511,7 @@ class IntersphinxRole(SphinxRole):
return result, messages
- def get_inventory_and_name_suffix(self, name: str) -> tuple[Optional[str], str]:
+ def get_inventory_and_name_suffix(self, name: str) -> tuple[str | None, str]:
assert name.startswith('external'), name
assert name[8] in ':+', name
# either we have an explicit inventory name, i.e,
@@ -523,7 +523,7 @@ class IntersphinxRole(SphinxRole):
inv, suffix = IntersphinxRole._re_inv_ref.fullmatch(name, 8).group(2, 3)
return inv, suffix
- def get_role_name(self, name: str) -> Optional[tuple[str, str]]:
+ def get_role_name(self, name: str) -> tuple[str, str] | None:
names = name.split(':')
if len(names) == 1:
# role
@@ -654,7 +654,7 @@ def inspect_main(argv: list[str]) -> None:
raise SystemExit(1)
class MockConfig:
- intersphinx_timeout: Optional[int] = None
+ intersphinx_timeout: int | None = None
tls_verify = False
user_agent = None
diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py
index 88a62de68..cb8a5e1cd 100644
--- a/sphinx/ext/napoleon/docstring.py
+++ b/sphinx/ext/napoleon/docstring.py
@@ -6,7 +6,7 @@ import collections
import inspect
import re
from functools import partial
-from typing import Any, Callable, Optional, Union
+from typing import Any, Callable
from sphinx.application import Sphinx
from sphinx.config import Config as SphinxConfig
@@ -149,9 +149,9 @@ class GoogleDocstring:
def __init__(
self,
- docstring: Union[str, list[str]],
- config: Optional[SphinxConfig] = None,
- app: Optional[Sphinx] = None,
+ docstring: str | list[str],
+ config: SphinxConfig | None = None,
+ app: Sphinx | None = None,
what: str = '',
name: str = '',
obj: Any = None,
@@ -418,7 +418,7 @@ class GoogleDocstring:
return ['.. %s::' % admonition, '']
def _format_block(
- self, prefix: str, lines: list[str], padding: Optional[str] = None
+ self, prefix: str, lines: list[str], padding: str | None = None
) -> list[str]:
if lines:
if padding is None:
@@ -958,7 +958,7 @@ def _tokenize_type_spec(spec: str) -> list[str]:
return tokens
-def _token_type(token: str, location: Optional[str] = None) -> str:
+def _token_type(token: str, location: str | None = None) -> str:
def is_numeric(token):
try:
# use complex to make sure every numeric value is detected as literal
@@ -1018,7 +1018,7 @@ def _token_type(token: str, location: Optional[str] = None) -> str:
def _convert_numpy_type_spec(
- _type: str, location: Optional[str] = None, translations: dict = {}
+ _type: str, location: str | None = None, translations: dict = {}
) -> str:
def convert_obj(obj, translations, default_translation):
translation = translations.get(obj, obj)
@@ -1150,9 +1150,9 @@ class NumpyDocstring(GoogleDocstring):
"""
def __init__(
self,
- docstring: Union[str, list[str]],
- config: Optional[SphinxConfig] = None,
- app: Optional[Sphinx] = None,
+ docstring: str | list[str],
+ config: SphinxConfig | None = None,
+ app: Sphinx | None = None,
what: str = '',
name: str = '',
obj: Any = None,
@@ -1161,7 +1161,7 @@ class NumpyDocstring(GoogleDocstring):
self._directive_sections = ['.. index::']
super().__init__(docstring, config, app, what, name, obj, options)
- def _get_location(self) -> Optional[str]:
+ def _get_location(self) -> str | None:
try:
filepath = inspect.getfile(self._obj) if self._obj is not None else None
except TypeError:
@@ -1264,7 +1264,7 @@ class NumpyDocstring(GoogleDocstring):
"""
items = []
- def parse_item_name(text: str) -> tuple[str, Optional[str]]:
+ def parse_item_name(text: str) -> tuple[str, str | None]:
"""Match ':role:`name`' or 'name'"""
m = self._name_rgx.match(text)
if m:
diff --git a/sphinx/ext/napoleon/iterators.py b/sphinx/ext/napoleon/iterators.py
index de4f05329..750e1b3e0 100644
--- a/sphinx/ext/napoleon/iterators.py
+++ b/sphinx/ext/napoleon/iterators.py
@@ -4,7 +4,7 @@ from __future__ import annotations
import collections
import warnings
-from typing import Any, Iterable, Optional
+from typing import Any, Iterable
from sphinx.deprecation import RemovedInSphinx70Warning
@@ -57,10 +57,10 @@ class peek_iter:
def __iter__(self) -> "peek_iter":
return self
- def __next__(self, n: Optional[int] = None) -> Any:
+ def __next__(self, n: int | None = None) -> Any:
return self.next(n)
- def _fillcache(self, n: Optional[int]) -> None:
+ def _fillcache(self, n: int | None) -> None:
"""Cache `n` items. If `n` is 0 or None, then 1 item is cached."""
if not n:
n = 1
@@ -86,7 +86,7 @@ class peek_iter:
"""
return self.peek() != self.sentinel
- def next(self, n: Optional[int] = None) -> Any:
+ def next(self, n: int | None = None) -> Any:
"""Get the next item or `n` items of the iterator.
Parameters
@@ -121,7 +121,7 @@ class peek_iter:
result = [self._cache.popleft() for i in range(n)]
return result
- def peek(self, n: Optional[int] = None) -> Any:
+ def peek(self, n: int | None = None) -> Any:
"""Preview the next item or `n` items of the iterator.
The iterator is not advanced when peek is called.
@@ -218,7 +218,7 @@ class modify_iter(peek_iter):
'modifier must be callable')
super().__init__(*args)
- def _fillcache(self, n: Optional[int]) -> None:
+ def _fillcache(self, n: int | None) -> None:
"""Cache `n` modified items. If `n` is 0 or None, 1 item is cached.
Each item returned by the iterator is passed through the
diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py
index 6a9845722..5bde12d6c 100644
--- a/sphinx/ext/viewcode.py
+++ b/sphinx/ext/viewcode.py
@@ -5,7 +5,7 @@ from __future__ import annotations
import posixpath
import traceback
from os import path
-from typing import Any, Generator, Iterable, Optional, cast
+from typing import Any, Generator, Iterable, cast
from docutils import nodes
from docutils.nodes import Element, Node
@@ -37,7 +37,7 @@ class viewcode_anchor(Element):
"""
-def _get_full_modname(app: Sphinx, modname: str, attribute: str) -> Optional[str]:
+def _get_full_modname(app: Sphinx, modname: str, attribute: str) -> str | None:
try:
return get_full_modname(modname, attribute)
except AttributeError:
@@ -187,7 +187,7 @@ class ViewcodeAnchorTransform(SphinxPostTransform):
node.parent.remove(node)
-def get_module_filename(app: Sphinx, modname: str) -> Optional[str]:
+def get_module_filename(app: Sphinx, modname: str) -> str | None:
"""Get module filename for *modname*."""
source_info = app.emit_firstresult('viewcode-find-source', modname)
if source_info:
diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py
index a8ec62cb6..7ed933f43 100644
--- a/sphinx/highlighting.py
+++ b/sphinx/highlighting.py
@@ -4,7 +4,7 @@ from __future__ import annotations
from functools import partial
from importlib import import_module
-from typing import Any, Optional, Union
+from typing import Any, Union
from pygments import highlight
from pygments.filters import ErrorToken
@@ -83,7 +83,7 @@ class PygmentsBridge:
latex_formatter = LatexFormatter
def __init__(self, dest: str = 'html', stylename: str = 'sphinx',
- latex_engine: Optional[str] = None) -> None:
+ latex_engine: str | None = None) -> None:
self.dest = dest
self.latex_engine = latex_engine
@@ -110,7 +110,7 @@ class PygmentsBridge:
kwargs.update(self.formatter_args)
return self.formatter(**kwargs)
- def get_lexer(self, source: str, lang: str, opts: Optional[dict] = None,
+ def get_lexer(self, source: str, lang: str, opts: dict | None = None,
force: bool = False, location: Any = None) -> Lexer:
if not opts:
opts = {}
@@ -146,7 +146,7 @@ class PygmentsBridge:
return lexer
- def highlight_block(self, source: str, lang: str, opts: Optional[dict] = None,
+ def highlight_block(self, source: str, lang: str, opts: dict | None = None,
force: bool = False, location: Any = None, **kwargs: Any) -> str:
if not isinstance(source, str):
source = source.decode()
diff --git a/sphinx/jinja2glue.py b/sphinx/jinja2glue.py
index ff821cdcc..c19257c72 100644
--- a/sphinx/jinja2glue.py
+++ b/sphinx/jinja2glue.py
@@ -5,7 +5,7 @@ from __future__ import annotations
import pathlib
from os import path
from pprint import pformat
-from typing import TYPE_CHECKING, Any, Callable, Iterator, Optional, Union
+from typing import TYPE_CHECKING, Any, Callable, Iterator
from jinja2 import BaseLoader, FileSystemLoader, TemplateNotFound
from jinja2.environment import Environment
@@ -39,7 +39,7 @@ def _toint(val: str) -> int:
return 0
-def _todim(val: Union[int, str]) -> str:
+def _todim(val: int | str) -> str:
"""
Make val a css dimension. In particular the following transformations
are performed:
@@ -147,8 +147,8 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
def init(
self,
builder: "Builder",
- theme: Optional[Theme] = None,
- dirs: Optional[list[str]] = None
+ theme: Theme | None = None,
+ dirs: list[str] | None = None
) -> None:
# create a chain of paths to search
if theme:
diff --git a/sphinx/parsers.py b/sphinx/parsers.py
index b8d4410e1..3f03501e2 100644
--- a/sphinx/parsers.py
+++ b/sphinx/parsers.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import TYPE_CHECKING, Any, Union
+from typing import TYPE_CHECKING, Any
import docutils.parsers
import docutils.parsers.rst
@@ -58,7 +58,7 @@ class RSTParser(docutils.parsers.rst.Parser, Parser):
transforms.remove(SmartQuotes)
return transforms
- def parse(self, inputstring: Union[str, StringList], document: nodes.document) -> None:
+ def parse(self, inputstring: str | StringList, document: nodes.document) -> None:
"""Parse text and generate a document tree."""
self.setup_parse(inputstring, document) # type: ignore
self.statemachine = states.RSTStateMachine(
diff --git a/sphinx/project.py b/sphinx/project.py
index d993ec504..89e003b22 100644
--- a/sphinx/project.py
+++ b/sphinx/project.py
@@ -4,7 +4,7 @@ from __future__ import annotations
import os
from glob import glob
-from typing import Iterable, Optional
+from typing import Iterable
from sphinx.locale import __
from sphinx.util import logging
@@ -58,7 +58,7 @@ class Project:
return self.docnames
- def path2doc(self, filename: str) -> Optional[str]:
+ def path2doc(self, filename: str) -> str | None:
"""Return the docname for the filename if the file is a document.
*filename* should be absolute or relative to the source directory.
diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py
index 8cba37bb0..c11579f96 100644
--- a/sphinx/pycode/__init__.py
+++ b/sphinx/pycode/__init__.py
@@ -8,7 +8,7 @@ from collections import OrderedDict
from importlib import import_module
from inspect import Signature
from os import path
-from typing import Any, Optional
+from typing import Any
from zipfile import ZipFile
from sphinx.errors import PycodeError
@@ -27,7 +27,7 @@ class ModuleAnalyzer:
cache: dict[tuple[str, str], Any] = {}
@staticmethod
- def get_module_source(modname: str) -> tuple[Optional[str], Optional[str]]:
+ def get_module_source(modname: str) -> tuple[str | None, str | None]:
"""Try to find the source code for a module.
Returns ('filename', 'source'). One of it can be None if
diff --git a/sphinx/pycode/ast.py b/sphinx/pycode/ast.py
index 1e773223e..b85edb1b5 100644
--- a/sphinx/pycode/ast.py
+++ b/sphinx/pycode/ast.py
@@ -4,7 +4,7 @@ from __future__ import annotations
import ast
import warnings
-from typing import Optional, overload
+from typing import overload
from sphinx.deprecation import RemovedInSphinx70Warning
@@ -55,7 +55,7 @@ def unparse(node: ast.AST, code: str = '') -> str:
...
-def unparse(node: Optional[ast.AST], code: str = '') -> Optional[str]:
+def unparse(node: ast.AST | None, code: str = '') -> str | None:
"""Unparse an AST to string."""
if node is None:
return None
@@ -80,7 +80,7 @@ class _UnparseVisitor(ast.NodeVisitor):
else:
return node.arg
- def _visit_arg_with_default(self, arg: ast.arg, default: Optional[ast.AST]) -> str:
+ def _visit_arg_with_default(self, arg: ast.arg, default: ast.AST | None) -> str:
"""Unparse a single argument to a string."""
name = self.visit(arg)
if default:
@@ -91,14 +91,14 @@ class _UnparseVisitor(ast.NodeVisitor):
return name
def visit_arguments(self, node: ast.arguments) -> str:
- defaults: list[Optional[ast.expr]] = list(node.defaults)
+ defaults: list[ast.expr | None] = list(node.defaults)
positionals = len(node.args)
posonlyargs = len(node.posonlyargs)
positionals += posonlyargs
for _ in range(len(defaults), positionals):
defaults.insert(0, None)
- kw_defaults: list[Optional[ast.expr]] = list(node.kw_defaults)
+ kw_defaults: list[ast.expr | None] = list(node.kw_defaults)
for _ in range(len(kw_defaults), len(node.kwonlyargs)):
kw_defaults.insert(0, None)
diff --git a/sphinx/pycode/parser.py b/sphinx/pycode/parser.py
index d13191611..68a3523b3 100644
--- a/sphinx/pycode/parser.py
+++ b/sphinx/pycode/parser.py
@@ -11,7 +11,7 @@ from collections import OrderedDict
from inspect import Signature
from token import DEDENT, INDENT, NAME, NEWLINE, NUMBER, OP, STRING
from tokenize import COMMENT, NL
-from typing import Any, Optional
+from typing import Any
from sphinx.pycode.ast import unparse as ast_unparse
@@ -32,7 +32,7 @@ def get_assign_targets(node: ast.AST) -> list[ast.expr]:
return [node.target] # type: ignore
-def get_lvar_names(node: ast.AST, self: Optional[ast.arg] = None) -> list[str]:
+def get_lvar_names(node: ast.AST, self: ast.arg | None = None) -> list[str]:
"""Convert assignment-AST to variable names.
This raises `TypeError` if the assignment does not create new variable::
@@ -127,14 +127,14 @@ class TokenProcessor:
lines = iter(buffers)
self.buffers = buffers
self.tokens = tokenize.generate_tokens(lambda: next(lines))
- self.current: Optional[Token] = None
- self.previous: Optional[Token] = None
+ self.current: Token | None = None
+ self.previous: Token | None = None
def get_line(self, lineno: int) -> str:
"""Returns specified line."""
return self.buffers[lineno - 1]
- def fetch_token(self) -> Optional[Token]:
+ def fetch_token(self) -> Token | None:
"""Fetch the next token from source code.
Returns ``None`` if sequence finished.
@@ -176,7 +176,7 @@ class AfterCommentParser(TokenProcessor):
def __init__(self, lines: list[str]) -> None:
super().__init__(lines)
- self.comment: Optional[str] = None
+ self.comment: str | None = None
def fetch_rvalue(self) -> list[Token]:
"""Fetch right-hand value of assignment."""
@@ -221,19 +221,19 @@ class VariableCommentPicker(ast.NodeVisitor):
self.encoding = encoding
self.context: list[str] = []
self.current_classes: list[str] = []
- self.current_function: Optional[ast.FunctionDef] = None
+ self.current_function: ast.FunctionDef | None = None
self.comments: dict[tuple[str, str], str] = OrderedDict()
self.annotations: dict[tuple[str, str], str] = {}
- self.previous: Optional[ast.AST] = None
+ self.previous: ast.AST | None = None
self.deforders: dict[str, int] = {}
self.finals: list[str] = []
self.overloads: dict[str, list[Signature]] = {}
- self.typing: Optional[str] = None
- self.typing_final: Optional[str] = None
- self.typing_overload: Optional[str] = None
+ self.typing: str | None = None
+ self.typing_final: str | None = None
+ self.typing_overload: str | None = None
super().__init__()
- def get_qualname_for(self, name: str) -> Optional[list[str]]:
+ def get_qualname_for(self, name: str) -> list[str] | None:
"""Get qualified name for given object as a list of string(s)."""
if self.current_function:
if self.current_classes and self.context[-1] == "__init__":
@@ -306,7 +306,7 @@ class VariableCommentPicker(ast.NodeVisitor):
return False
- def get_self(self) -> Optional[ast.arg]:
+ def get_self(self) -> ast.arg | None:
"""Returns the name of the first argument if in a function."""
if self.current_function and self.current_function.args.args:
return self.current_function.args.args[0]
@@ -467,9 +467,9 @@ class DefinitionFinder(TokenProcessor):
def __init__(self, lines: list[str]) -> None:
super().__init__(lines)
- self.decorator: Optional[Token] = None
+ self.decorator: Token | None = None
self.context: list[str] = []
- self.indents: list[tuple[str, Optional[str], Optional[int]]] = []
+ self.indents: list[tuple[str, str | None, int | None]] = []
self.definitions: dict[str, tuple[str, int, int]] = {}
def add_definition(self, name: str, entry: tuple[str, int, int]) -> None:
diff --git a/sphinx/registry.py b/sphinx/registry.py
index c5ff9708c..14581b8cb 100644
--- a/sphinx/registry.py
+++ b/sphinx/registry.py
@@ -6,7 +6,7 @@ import traceback
import warnings
from importlib import import_module
from types import MethodType
-from typing import TYPE_CHECKING, Any, Callable, Iterator, Optional, Union
+from typing import TYPE_CHECKING, Any, Callable, Iterator
from docutils import nodes
from docutils.core import Publisher
@@ -80,7 +80,7 @@ class SphinxComponentRegistry:
#: additional roles for domains
#: a dict of domain name -> dict of role name -> role impl.
- self.domain_roles: dict[str, dict[str, Union[RoleFunction, XRefRole]]] = {}
+ self.domain_roles: dict[str, dict[str, RoleFunction | XRefRole]] = {}
#: additional enumerable nodes
#: a dict of node class -> tuple of figtype and title_getter function
@@ -151,7 +151,7 @@ class SphinxComponentRegistry:
self.load_extension(app, entry_point.module)
def create_builder(self, app: "Sphinx", name: str,
- env: Optional[BuildEnvironment] = None) -> Builder:
+ env: BuildEnvironment | None = None) -> Builder:
if name not in self.builders:
raise SphinxError(__('Builder name %s not registered') % name)
@@ -203,7 +203,7 @@ class SphinxComponentRegistry:
directives[name] = cls
def add_role_to_domain(self, domain: str, name: str,
- role: Union[RoleFunction, XRefRole], override: bool = False
+ role: RoleFunction | XRefRole, override: bool = False
) -> None:
logger.debug('[app] adding role to domain: %r', (domain, name, role))
if domain not in self.domains:
@@ -230,8 +230,8 @@ class SphinxComponentRegistry:
directivename: str,
rolename: str,
indextemplate: str = '',
- parse_node: Optional[Callable] = None,
- ref_nodeclass: Optional[type[TextElement]] = None,
+ parse_node: Callable | None = None,
+ ref_nodeclass: type[TextElement] | None = None,
objname: str = '',
doc_field_types: list = [],
override: bool = False
@@ -261,7 +261,7 @@ class SphinxComponentRegistry:
directivename: str,
rolename: str,
indextemplate: str = '',
- ref_nodeclass: Optional[type[TextElement]] = None,
+ ref_nodeclass: type[TextElement] | None = None,
objname: str = '',
override: bool = False
) -> None:
@@ -405,7 +405,7 @@ class SphinxComponentRegistry:
self,
node: type[Node],
figtype: str,
- title_getter: Optional[TitleGetter] = None, override: bool = False
+ title_getter: TitleGetter | None = None, override: bool = False
) -> None:
logger.debug('[app] adding enumerable node: (%r, %r, %r)', node, figtype, title_getter)
if node in self.enumerable_nodes and not override:
diff --git a/sphinx/roles.py b/sphinx/roles.py
index fb53dbcbf..d682b4cb7 100644
--- a/sphinx/roles.py
+++ b/sphinx/roles.py
@@ -3,7 +3,7 @@
from __future__ import annotations
import re
-from typing import TYPE_CHECKING, Any, Optional
+from typing import TYPE_CHECKING, Any
import docutils.parsers.rst.directives
import docutils.parsers.rst.roles
@@ -66,8 +66,8 @@ class XRefRole(ReferenceRole):
innernodeclass: type[TextElement] = nodes.literal
def __init__(self, fix_parens: bool = False, lowercase: bool = False,
- nodeclass: Optional[type[Element]] = None,
- innernodeclass: Optional[type[TextElement]] = None,
+ nodeclass: type[Element] | None = None,
+ innernodeclass: type[TextElement] | None = None,
warn_dangling: bool = False) -> None:
self.fix_parens = fix_parens
self.lowercase = lowercase
diff --git a/sphinx/setup_command.py b/sphinx/setup_command.py
index b7aa683e3..35371a7d2 100644
--- a/sphinx/setup_command.py
+++ b/sphinx/setup_command.py
@@ -9,7 +9,7 @@ import os
import sys
import warnings
from io import StringIO
-from typing import Any, Optional
+from typing import Any
from sphinx.application import Sphinx
from sphinx.cmd.build import handle_exception
@@ -92,15 +92,15 @@ class BuildDoc(Command):
def initialize_options(self) -> None:
self.fresh_env = self.all_files = False
self.pdb = False
- self.source_dir: Optional[str] = None
- self.build_dir: Optional[str] = None
+ self.source_dir: str | None = None
+ self.build_dir: str | None = None
self.builder = 'html'
self.warning_is_error = False
self.project = ''
self.version = ''
self.release = ''
self.today = ''
- self.config_dir: Optional[str] = None
+ self.config_dir: str | None = None
self.link_index = False
self.copyright = ''
# Link verbosity to distutils' (which uses 1 by default).
diff --git a/sphinx/testing/comparer.py b/sphinx/testing/comparer.py
index 72494ae5a..8b2ec8892 100644
--- a/sphinx/testing/comparer.py
+++ b/sphinx/testing/comparer.py
@@ -3,7 +3,7 @@ from __future__ import annotations
import difflib
import pathlib
-from typing import Any, Union
+from typing import Any
class PathComparer:
@@ -26,7 +26,7 @@ class PathComparer:
>>> 'C:\\to\\index' == PathComparer('D:/to/index')
False
"""
- def __init__(self, path: Union[str, pathlib.Path]):
+ def __init__(self, path: str | pathlib.Path):
"""
:param str path: path string, it will be cast as pathlib.Path.
"""
@@ -38,10 +38,10 @@ class PathComparer:
def __repr__(self) -> str:
return "<{0.__class__.__name__}: '{0}'>".format(self)
- def __eq__(self, other: Union[str, pathlib.Path]) -> bool: # type: ignore
+ def __eq__(self, other: str | pathlib.Path) -> bool: # type: ignore
return not bool(self.ldiff(other))
- def diff(self, other: Union[str, pathlib.Path]) -> list[str]:
+ def diff(self, other: str | pathlib.Path) -> list[str]:
"""compare self and other.
When different is not exist, return empty list.
@@ -60,13 +60,13 @@ class PathComparer:
"""
return self.ldiff(other)
- def ldiff(self, other: Union[str, pathlib.Path]) -> list[str]:
+ def ldiff(self, other: str | pathlib.Path) -> list[str]:
return self._diff(
self.path,
pathlib.Path(other),
)
- def rdiff(self, other: Union[str, pathlib.Path]) -> list[str]:
+ def rdiff(self, other: str | pathlib.Path) -> list[str]:
return self._diff(
pathlib.Path(other),
self.path,
diff --git a/sphinx/testing/fixtures.py b/sphinx/testing/fixtures.py
index 64612f2cc..4f6b5de44 100644
--- a/sphinx/testing/fixtures.py
+++ b/sphinx/testing/fixtures.py
@@ -6,7 +6,7 @@ import subprocess
import sys
from collections import namedtuple
from io import StringIO
-from typing import Any, Callable, Generator, Optional
+from typing import Any, Callable, Generator
import pytest
@@ -29,7 +29,7 @@ def pytest_configure(config):
@pytest.fixture(scope='session')
-def rootdir() -> Optional[str]:
+def rootdir() -> str | None:
return None
diff --git a/sphinx/testing/path.py b/sphinx/testing/path.py
index a9a420f73..9c03132de 100644
--- a/sphinx/testing/path.py
+++ b/sphinx/testing/path.py
@@ -4,7 +4,7 @@ import builtins
import os
import shutil
import sys
-from typing import IO, Any, Callable, Optional
+from typing import IO, Any, Callable
FILESYSTEMENCODING = sys.getfilesystemencoding() or sys.getdefaultencoding()
@@ -71,7 +71,7 @@ class path(str):
"""
return os.path.ismount(self)
- def rmtree(self, ignore_errors: bool = False, onerror: Optional[Callable] = None) -> None:
+ def rmtree(self, ignore_errors: bool = False, onerror: Callable | None = None) -> None:
"""
Removes the file or directory and any files or directories it may
contain.
diff --git a/sphinx/testing/util.py b/sphinx/testing/util.py
index 6c5012c26..4e99c50ef 100644
--- a/sphinx/testing/util.py
+++ b/sphinx/testing/util.py
@@ -7,7 +7,7 @@ import re
import sys
import warnings
from io import StringIO
-from typing import IO, Any, Generator, Optional
+from typing import IO, Any, Generator
from xml.etree import ElementTree
from docutils import nodes
@@ -99,14 +99,14 @@ class SphinxTestApp(application.Sphinx):
def __init__(
self,
buildername: str = 'html',
- srcdir: Optional[path] = None,
- builddir: Optional[path] = None,
+ srcdir: path | None = None,
+ builddir: path | None = None,
freshenv: bool = False,
- confoverrides: Optional[dict] = None,
- status: Optional[IO] = None,
- warning: Optional[IO] = None,
- tags: Optional[list[str]] = None,
- docutilsconf: Optional[str] = None,
+ confoverrides: dict | None = None,
+ status: IO | None = None,
+ warning: IO | None = None,
+ tags: list[str] | None = None,
+ docutilsconf: str | None = None,
parallel: int = 0
) -> None:
@@ -180,7 +180,7 @@ class SphinxTestAppWrapperForSkipBuilding:
_unicode_literals_re = re.compile(r'u(".*?")|u(\'.*?\')')
-def find_files(root: str, suffix: Optional[str] = None) -> Generator[str, None, None]:
+def find_files(root: str, suffix: str | None = None) -> Generator[str, None, None]:
for dirpath, _dirs, files in os.walk(root, followlinks=True):
dirpath = path(dirpath)
for f in [f for f in files if not suffix or f.endswith(suffix)]:
diff --git a/sphinx/transforms/i18n.py b/sphinx/transforms/i18n.py
index f9844a8a9..145eb9cbb 100644
--- a/sphinx/transforms/i18n.py
+++ b/sphinx/transforms/i18n.py
@@ -5,7 +5,7 @@ from __future__ import annotations
from os import path
from re import DOTALL, match
from textwrap import indent
-from typing import TYPE_CHECKING, Any, Optional, TypeVar
+from typing import TYPE_CHECKING, Any, TypeVar
from docutils import nodes
from docutils.io import StringInput
@@ -439,7 +439,7 @@ class Locale(SphinxTransform):
.format(old_xref_rawsources, new_xref_rawsources),
location=node, type='i18n', subtype='inconsistent_references')
- def get_ref_key(node: addnodes.pending_xref) -> Optional[tuple[str, str, str]]:
+ def get_ref_key(node: addnodes.pending_xref) -> tuple[str, str, str] | None:
case = node["refdomain"], node["reftype"]
if case == ('std', 'term'):
return None
diff --git a/sphinx/transforms/post_transforms/__init__.py b/sphinx/transforms/post_transforms/__init__.py
index d2ba85321..07e734dcb 100644
--- a/sphinx/transforms/post_transforms/__init__.py
+++ b/sphinx/transforms/post_transforms/__init__.py
@@ -3,7 +3,7 @@
from __future__ import annotations
import re
-from typing import Any, Optional, Sequence, cast
+from typing import Any, Sequence, cast
from docutils import nodes
from docutils.nodes import Element, Node
@@ -116,7 +116,7 @@ class ReferencesResolver(SphinxPostTransform):
def resolve_anyref(
self, refdoc: str, node: pending_xref, contnode: Element
- ) -> Optional[Element]:
+ ) -> Element | None:
"""Resolve reference generated by the "any" role."""
stddomain = self.env.get_domain('std')
target = node['reftarget']
@@ -166,7 +166,7 @@ class ReferencesResolver(SphinxPostTransform):
return newnode
def warn_missing_reference(self, refdoc: str, typ: str, target: str,
- node: pending_xref, domain: Optional[Domain]) -> None:
+ node: pending_xref, domain: Domain | None) -> None:
warn = node.get('refwarn')
if self.config.nitpicky:
warn = True
@@ -206,7 +206,7 @@ class ReferencesResolver(SphinxPostTransform):
logger.warning(msg, location=node, type='ref', subtype=typ)
def find_pending_xref_condition(self, node: pending_xref, conditions: Sequence[str]
- ) -> Optional[list[Node]]:
+ ) -> list[Node] | None:
for condition in conditions:
matched = find_pending_xref_condition(node, condition)
if matched:
diff --git a/sphinx/transforms/post_transforms/images.py b/sphinx/transforms/post_transforms/images.py
index 5025b94c4..afb8bfd6d 100644
--- a/sphinx/transforms/post_transforms/images.py
+++ b/sphinx/transforms/post_transforms/images.py
@@ -5,7 +5,7 @@ from __future__ import annotations
import os
import re
from math import ceil
-from typing import Any, Optional
+from typing import Any
from docutils import nodes
@@ -172,7 +172,7 @@ class ImageConverter(BaseImageConverter):
#:
#: .. todo:: This should be refactored not to store the state without class
#: variable.
- available: Optional[bool] = None
+ available: bool | None = None
#: A conversion rules the image converter supports.
#: It is represented as a list of pair of source image format (mimetype) and
diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py
index 0a9dee944..32e0229d1 100644
--- a/sphinx/util/__init__.py
+++ b/sphinx/util/__init__.py
@@ -249,7 +249,7 @@ def save_traceback(app: Optional["Sphinx"]) -> str:
return path
-def get_full_modname(modname: str, attribute: str) -> Optional[str]:
+def get_full_modname(modname: str, attribute: str) -> str | None:
if modname is None:
# Prevents a TypeError: if the last getattr() call will return None
# then it's better to return it directly
@@ -378,7 +378,7 @@ def format_exception_cut_frames(x: int = 1) -> str:
return ''.join(res)
-def import_object(objname: str, source: Optional[str] = None) -> Any:
+def import_object(objname: str, source: str | None = None) -> Any:
"""Import python object by qualname."""
try:
objpath = objname.split('.')
@@ -400,7 +400,7 @@ def import_object(objname: str, source: Optional[str] = None) -> Any:
raise ExtensionError('Could not import %s' % objname, exc) from exc
-def split_full_qualified_name(name: str) -> tuple[Optional[str], str]:
+def split_full_qualified_name(name: str) -> tuple[str | None, str]:
"""Split full qualified name to a pair of modname and qualname.
A qualname is an abbreviation for "Qualified name" introduced at PEP-3155
diff --git a/sphinx/util/cfamily.py b/sphinx/util/cfamily.py
index 31f5b2ab3..282499d70 100644
--- a/sphinx/util/cfamily.py
+++ b/sphinx/util/cfamily.py
@@ -4,7 +4,7 @@ from __future__ import annotations
import re
from copy import deepcopy
-from typing import Any, Callable, Optional, Union
+from typing import Any, Callable, Optional
from docutils import nodes
from docutils.nodes import TextElement
@@ -236,7 +236,7 @@ class DefinitionError(Exception):
class BaseParser:
def __init__(self, definition: str, *,
- location: Union[nodes.Node, tuple[str, int], str],
+ location: nodes.Node | tuple[str, int] | str,
config: "Config") -> None:
self.definition = definition.strip()
self.location = location # for warnings
@@ -393,7 +393,7 @@ class BaseParser:
% startPos)
return self.definition[startPos:self.pos]
- def _parse_attribute(self) -> Optional[ASTAttribute]:
+ def _parse_attribute(self) -> ASTAttribute | None:
self.skip_ws()
# try C++11 style
startPos = self.pos
diff --git a/sphinx/util/docfields.py b/sphinx/util/docfields.py
index c5764cf83..d997b0f43 100644
--- a/sphinx/util/docfields.py
+++ b/sphinx/util/docfields.py
@@ -5,7 +5,7 @@ be domain-specifically transformed to a more appealing presentation.
"""
from __future__ import annotations
-from typing import TYPE_CHECKING, Any, List, Tuple, Union, cast
+from typing import TYPE_CHECKING, Any, List, Tuple, cast
from docutils import nodes
from docutils.nodes import Node
@@ -251,7 +251,7 @@ class DocFieldTransformer:
"""Transform a single field list *node*."""
typemap = self.typemap
- entries: list[Union[nodes.field, tuple[Field, Any, Node]]] = []
+ entries: list[nodes.field | tuple[Field, Any, Node]] = []
groupindices: dict[str, int] = {}
types: dict[str, dict] = {}
diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py
index b4dde6ebb..e012470c7 100644
--- a/sphinx/util/docutils.py
+++ b/sphinx/util/docutils.py
@@ -9,7 +9,7 @@ from contextlib import contextmanager
from copy import copy
from os import path
from types import ModuleType
-from typing import IO, TYPE_CHECKING, Any, Callable, Generator, Optional, cast
+from typing import IO, TYPE_CHECKING, Any, Callable, Generator, cast
import docutils
from docutils import nodes
@@ -171,7 +171,7 @@ def patched_rst_get_language() -> Generator[None, None, None]:
@contextmanager
-def using_user_docutils_conf(confdir: Optional[str]) -> Generator[None, None, None]:
+def using_user_docutils_conf(confdir: str | None) -> Generator[None, None, None]:
"""Let docutils know the location of ``docutils.conf`` for Sphinx."""
try:
docutilsconfig = os.environ.get('DOCUTILSCONFIG', None)
@@ -220,7 +220,7 @@ def du19_footnotes() -> Generator[None, None, None]:
@contextmanager
-def patch_docutils(confdir: Optional[str] = None) -> Generator[None, None, None]:
+def patch_docutils(confdir: str | None = None) -> Generator[None, None, None]:
"""Patch to docutils temporarily."""
with patched_get_language(), \
patched_rst_get_language(), \
@@ -261,7 +261,7 @@ class CustomReSTDispatcher:
def directive(self,
directive_name: str, language_module: ModuleType, document: nodes.document
- ) -> tuple[Optional[type[Directive]], list[system_message]]:
+ ) -> tuple[type[Directive] | None, list[system_message]]:
return self.directive_func(directive_name, language_module, document)
def role(self, role_name: str, language_module: ModuleType, lineno: int, reporter: Reporter
@@ -313,7 +313,7 @@ class sphinx_domains(CustomReSTDispatcher):
def directive(self,
directive_name: str, language_module: ModuleType, document: nodes.document
- ) -> tuple[Optional[type[Directive]], list[system_message]]:
+ ) -> tuple[type[Directive] | None, list[system_message]]:
try:
return self.lookup_domain_element('directive', directive_name)
except ElementLookupError:
diff --git a/sphinx/util/fileutil.py b/sphinx/util/fileutil.py
index bccba90c7..c9c50e84a 100644
--- a/sphinx/util/fileutil.py
+++ b/sphinx/util/fileutil.py
@@ -16,7 +16,7 @@ if TYPE_CHECKING:
def copy_asset_file(source: str, destination: str,
- context: Optional[dict] = None,
+ context: dict | None = None,
renderer: Optional["BaseRenderer"] = None) -> None:
"""Copy an asset file to destination.
@@ -50,8 +50,8 @@ def copy_asset_file(source: str, destination: str,
def copy_asset(source: str, destination: str, excluded: PathMatcher = lambda path: False,
- context: Optional[dict] = None, renderer: Optional["BaseRenderer"] = None,
- onerror: Optional[Callable[[str, Exception], None]] = None) -> None:
+ context: dict | None = None, renderer: Optional["BaseRenderer"] = None,
+ onerror: Callable[[str, Exception], None] | None = None) -> None:
"""Copy asset files to destination recursively.
On copying, it expands the template variables if context argument is given and
diff --git a/sphinx/util/i18n.py b/sphinx/util/i18n.py
index eaaa921b9..1219269bf 100644
--- a/sphinx/util/i18n.py
+++ b/sphinx/util/i18n.py
@@ -7,7 +7,7 @@ import re
import warnings
from datetime import datetime, timezone
from os import path
-from typing import TYPE_CHECKING, Callable, Generator, NamedTuple, Optional, Union
+from typing import TYPE_CHECKING, Callable, Generator, NamedTuple
import babel.dates
from babel.messages.mofile import write_mo
@@ -115,7 +115,7 @@ class CatalogRepository:
yield CatalogInfo(basedir, domain, self.encoding)
-def docname_to_domain(docname: str, compaction: Union[bool, str]) -> str:
+def docname_to_domain(docname: str, compaction: bool | str) -> str:
"""Convert docname to domain for catalogs."""
if isinstance(compaction, str):
return compaction
@@ -193,7 +193,7 @@ def babel_format_date(date: datetime, format: str, locale: str,
def format_date(
- format: str, date: Optional[datetime] = None, language: Optional[str] = None
+ format: str, date: datetime | None = None, language: str | None = None
) -> str:
if date is None:
# If time is not specified, try to use $SOURCE_DATE_EPOCH variable
diff --git a/sphinx/util/images.py b/sphinx/util/images.py
index bbf947d4b..b3d37802b 100644
--- a/sphinx/util/images.py
+++ b/sphinx/util/images.py
@@ -6,7 +6,7 @@ import base64
import imghdr
from collections import OrderedDict
from os import path
-from typing import IO, BinaryIO, NamedTuple, Optional
+from typing import IO, BinaryIO, NamedTuple
import imagesize
@@ -32,7 +32,7 @@ class DataURI(NamedTuple):
data: bytes
-def get_image_size(filename: str) -> Optional[tuple[int, int]]:
+def get_image_size(filename: str) -> tuple[int, int] | None:
try:
size = imagesize.get(filename)
if size[0] == -1:
@@ -49,7 +49,7 @@ def get_image_size(filename: str) -> Optional[tuple[int, int]]:
return None
-def guess_mimetype_for_stream(stream: IO, default: Optional[str] = None) -> Optional[str]:
+def guess_mimetype_for_stream(stream: IO, default: str | None = None) -> str | None:
imgtype = imghdr.what(stream)
if imgtype:
return 'image/' + imgtype
@@ -57,7 +57,7 @@ def guess_mimetype_for_stream(stream: IO, default: Optional[str] = None) -> Opti
return default
-def guess_mimetype(filename: str = '', default: Optional[str] = None) -> Optional[str]:
+def guess_mimetype(filename: str = '', default: str | None = None) -> str | None:
_, ext = path.splitext(filename.lower())
if ext in mime_suffixes:
return mime_suffixes[ext]
@@ -68,7 +68,7 @@ def guess_mimetype(filename: str = '', default: Optional[str] = None) -> Optiona
return default
-def get_image_extension(mimetype: str) -> Optional[str]:
+def get_image_extension(mimetype: str) -> str | None:
for ext, _mimetype in mime_suffixes.items():
if mimetype == _mimetype:
return ext
@@ -76,7 +76,7 @@ def get_image_extension(mimetype: str) -> Optional[str]:
return None
-def parse_data_uri(uri: str) -> Optional[DataURI]:
+def parse_data_uri(uri: str) -> DataURI | None:
if not uri.startswith('data:'):
return None
@@ -97,7 +97,7 @@ def parse_data_uri(uri: str) -> Optional[DataURI]:
return DataURI(mimetype, charset, image_data)
-def test_svg(h: bytes, f: Optional[BinaryIO]) -> Optional[str]:
+def test_svg(h: bytes, f: BinaryIO | None) -> str | None:
"""An additional imghdr library helper; test the header is SVG's or not."""
try:
if '<svg' in h.decode().lower():
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py
index 3ce719db1..4fb2503ee 100644
--- a/sphinx/util/inspect.py
+++ b/sphinx/util/inspect.py
@@ -18,7 +18,7 @@ from inspect import (Parameter, isasyncgenfunction, isclass, ismethod, # noqa:
from io import StringIO
from types import (ClassMethodDescriptorType, MethodDescriptorType, MethodType, ModuleType,
WrapperDescriptorType)
-from typing import Any, Callable, Dict, Mapping, Optional, Sequence, cast
+from typing import Any, Callable, Dict, Mapping, Sequence, cast
from sphinx.pycode.ast import unparse as ast_unparse
from sphinx.util import logging
@@ -43,7 +43,7 @@ def unwrap(obj: Any) -> Any:
return obj
-def unwrap_all(obj: Any, *, stop: Optional[Callable] = None) -> Any:
+def unwrap_all(obj: Any, *, stop: Callable | None = None) -> Any:
"""
Get an original object from wrapped object (unwrapping partials, wrapped
functions, and other decorators).
@@ -63,7 +63,7 @@ def unwrap_all(obj: Any, *, stop: Optional[Callable] = None) -> Any:
return obj
-def getall(obj: Any) -> Optional[Sequence[str]]:
+def getall(obj: Any) -> Sequence[str] | None:
"""Get __all__ attribute of the module as dict.
Return None if given *obj* does not have __all__.
@@ -106,7 +106,7 @@ def getmro(obj: Any) -> tuple[type, ...]:
return ()
-def getorigbases(obj: Any) -> Optional[tuple[Any, ...]]:
+def getorigbases(obj: Any) -> tuple[Any, ...] | None:
"""Get __orig_bases__ from *obj* safely."""
if not inspect.isclass(obj):
return None
@@ -121,7 +121,7 @@ def getorigbases(obj: Any) -> Optional[tuple[Any, ...]]:
return None
-def getslots(obj: Any) -> Optional[dict]:
+def getslots(obj: Any) -> dict | None:
"""Get __slots__ attribute of the class as dict.
Return None if gienv *obj* does not have __slots__.
@@ -183,7 +183,7 @@ def ispartial(obj: Any) -> bool:
return isinstance(obj, (partial, partialmethod))
-def isclassmethod(obj: Any, cls: Any = None, name: Optional[str] = None) -> bool:
+def isclassmethod(obj: Any, cls: Any = None, name: str | None = None) -> bool:
"""Check if the object is classmethod."""
if isinstance(obj, classmethod):
return True
@@ -199,7 +199,7 @@ def isclassmethod(obj: Any, cls: Any = None, name: Optional[str] = None) -> bool
return False
-def isstaticmethod(obj: Any, cls: Any = None, name: Optional[str] = None) -> bool:
+def isstaticmethod(obj: Any, cls: Any = None, name: str | None = None) -> bool:
"""Check if the object is staticmethod."""
if isinstance(obj, staticmethod):
return True
@@ -474,7 +474,7 @@ class TypeAliasModule:
self.__modname = modname
self.__mapping = mapping
- self.__module: Optional[ModuleType] = None
+ self.__module: ModuleType | None = None
def __getattr__(self, name: str) -> Any:
fullname = '.'.join(filter(None, [self.__modname, name]))
@@ -590,8 +590,8 @@ def signature(subject: Callable, bound_method: bool = False, type_aliases: dict
__validate_parameters__=False)
-def evaluate_signature(sig: inspect.Signature, globalns: Optional[dict] = None,
- localns: Optional[dict] = None
+def evaluate_signature(sig: inspect.Signature, globalns: dict | None = None,
+ localns: dict | None = None
) -> inspect.Signature:
"""Evaluate unresolved type annotations in a signature object."""
def evaluate_forwardref(ref: ForwardRef, globalns: dict, localns: dict) -> Any:
@@ -775,8 +775,8 @@ def getdoc(
attrgetter: Callable = safe_getattr,
allow_inherited: bool = False,
cls: Any = None,
- name: Optional[str] = None
-) -> Optional[str]:
+ name: str | None = None
+) -> str | None:
"""Get the docstring for the object.
This tries to obtain the docstring for some kind of objects additionally:
@@ -785,7 +785,7 @@ def getdoc(
* inherited docstring
* inherited decorated methods
"""
- def getdoc_internal(obj: Any, attrgetter: Callable = safe_getattr) -> Optional[str]:
+ def getdoc_internal(obj: Any, attrgetter: Callable = safe_getattr) -> str | None:
doc = attrgetter(obj, '__doc__', None)
if isinstance(doc, str):
return doc
@@ -796,7 +796,7 @@ def getdoc(
for basecls in getmro(cls):
meth = basecls.__dict__.get(name)
if meth and hasattr(meth, '__func__'):
- doc: Optional[str] = getdoc(meth.__func__)
+ doc: str | None = getdoc(meth.__func__)
if doc is not None or not allow_inherited:
return doc
diff --git a/sphinx/util/jsdump.py b/sphinx/util/jsdump.py
index 4b40c2bb9..5d8a32781 100644
--- a/sphinx/util/jsdump.py
+++ b/sphinx/util/jsdump.py
@@ -7,7 +7,7 @@ from __future__ import annotations
import re
import warnings
-from typing import IO, Any, Union
+from typing import IO, Any
from sphinx.deprecation import RemovedInSphinx70Warning
@@ -111,7 +111,7 @@ def loads(x: str) -> Any:
nothing = object()
i = 0
n = len(x)
- stack: list[Union[list, dict]] = []
+ stack: list[list | dict] = []
obj: Any = nothing
key = False
keys = []
diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py
index f3ed45343..9fad129d7 100644
--- a/sphinx/util/logging.py
+++ b/sphinx/util/logging.py
@@ -6,7 +6,7 @@ import logging
import logging.handlers
from collections import defaultdict
from contextlib import contextmanager
-from typing import IO, TYPE_CHECKING, Any, Generator, Optional, Union
+from typing import IO, TYPE_CHECKING, Any, Generator
from docutils import nodes
from docutils.nodes import Node
@@ -121,7 +121,7 @@ class SphinxLoggerAdapter(logging.LoggerAdapter):
KEYWORDS = ['type', 'subtype', 'location', 'nonl', 'color', 'once']
def log( # type: ignore[override]
- self, level: Union[int, str], msg: str, *args: Any, **kwargs: Any
+ self, level: int | str, msg: str, *args: Any, **kwargs: Any
) -> None:
if isinstance(level, int):
super().log(level, msg, *args, **kwargs)
@@ -364,7 +364,7 @@ def is_suppressed_warning(type: str, subtype: str, suppress_warnings: list[str])
if type is None:
return False
- subtarget: Optional[str]
+ subtarget: str | None
for warning_type in suppress_warnings:
if '.' in warning_type:
@@ -517,7 +517,7 @@ class WarningLogRecordTranslator(SphinxLogRecordTranslator):
LogRecordClass = SphinxWarningLogRecord
-def get_node_location(node: Node) -> Optional[str]:
+def get_node_location(node: Node) -> str | None:
(source, line) = get_source_line(node)
if source:
source = abspath(source)
diff --git a/sphinx/util/matching.py b/sphinx/util/matching.py
index b40c9f66a..5350b623a 100644
--- a/sphinx/util/matching.py
+++ b/sphinx/util/matching.py
@@ -4,7 +4,7 @@ from __future__ import annotations
import os.path
import re
-from typing import Callable, Iterable, Iterator, Optional
+from typing import Callable, Iterable, Iterator
from sphinx.util.osutil import canon_path, path_stabilize
@@ -57,7 +57,7 @@ def _translate_pattern(pat: str) -> str:
def compile_matchers(
patterns: Iterable[str],
-) -> list[Callable[[str], Optional[re.Match[str]]]]:
+) -> list[Callable[[str], re.Match[str] | None]]:
return [re.compile(_translate_pattern(pat)).match for pat in patterns]
@@ -86,7 +86,7 @@ DOTFILES = Matcher(['**/.*'])
_pat_cache: dict[str, re.Pattern] = {}
-def patmatch(name: str, pat: str) -> Optional[re.Match[str]]:
+def patmatch(name: str, pat: str) -> re.Match[str] | None:
"""Return if name matches the regular expression (pattern)
``pat```. Adapted from fnmatch module."""
if pat not in _pat_cache:
diff --git a/sphinx/util/math.py b/sphinx/util/math.py
index bac197d7a..cd06dc249 100644
--- a/sphinx/util/math.py
+++ b/sphinx/util/math.py
@@ -2,8 +2,6 @@
from __future__ import annotations
-from typing import Optional
-
from docutils import nodes
from sphinx.builders.html import HTML5Translator
@@ -24,7 +22,7 @@ def get_node_equation_number(writer: HTML5Translator, node: nodes.math_block) ->
return node['number']
-def wrap_displaymath(text: str, label: Optional[str], numbering: bool) -> str:
+def wrap_displaymath(text: str, label: str | None, numbering: bool) -> str:
def is_equation(part: str) -> str:
return part.strip()
diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py
index 9b10007a1..bd1c924e2 100644
--- a/sphinx/util/nodes.py
+++ b/sphinx/util/nodes.py
@@ -4,7 +4,7 @@ from __future__ import annotations
import re
import unicodedata
-from typing import TYPE_CHECKING, Any, Callable, Iterable, Optional, Union
+from typing import TYPE_CHECKING, Any, Callable, Iterable
from docutils import nodes
from docutils.nodes import Element, Node
@@ -264,14 +264,14 @@ def extract_messages(doctree: Element) -> Iterable[tuple[Element, str]]:
yield node, msg
-def get_node_source(node: Element) -> Optional[str]:
+def get_node_source(node: Element) -> str | None:
for pnode in traverse_parent(node):
if pnode.source:
return pnode.source
return None
-def get_node_line(node: Element) -> Optional[int]:
+def get_node_line(node: Element) -> int | None:
for pnode in traverse_parent(node):
if pnode.line:
return pnode.line
@@ -285,7 +285,7 @@ def traverse_parent(node: Element, cls: Any = None) -> Iterable[Element]:
node = node.parent
-def get_prev_node(node: Node) -> Optional[Node]:
+def get_prev_node(node: Node) -> Node | None:
pos = node.parent.index(node)
if pos > 0:
return node.parent[pos - 1]
@@ -349,10 +349,10 @@ indextypes = [
def process_index_entry(entry: str, targetid: str
- ) -> list[tuple[str, str, str, str, Optional[str]]]:
+ ) -> list[tuple[str, str, str, str, str | None]]:
from sphinx.domains.python import pairindextypes
- indexentries: list[tuple[str, str, str, str, Optional[str]]] = []
+ indexentries: list[tuple[str, str, str, str, str | None]] = []
entry = entry.strip()
oentry = entry
main = ''
@@ -495,7 +495,7 @@ _non_id_translate_digraphs = {
def make_id(env: "BuildEnvironment", document: nodes.document,
- prefix: str = '', term: Optional[str] = None) -> str:
+ prefix: str = '', term: str | None = None) -> str:
"""Generate an appropriate node_id for given *prefix* and *term*."""
node_id = None
if prefix:
@@ -521,7 +521,7 @@ def make_id(env: "BuildEnvironment", document: nodes.document,
def find_pending_xref_condition(node: addnodes.pending_xref, condition: str
- ) -> Optional[Element]:
+ ) -> Element | None:
"""Pick matched pending_xref_condition node up from the pending_xref."""
for subnode in node:
if (isinstance(subnode, addnodes.pending_xref_condition) and
@@ -531,7 +531,7 @@ def find_pending_xref_condition(node: addnodes.pending_xref, condition: str
def make_refnode(builder: "Builder", fromdocname: str, todocname: str, targetid: str,
- child: Union[Node, list[Node]], title: Optional[str] = None
+ child: Node | list[Node], title: str | None = None
) -> nodes.reference:
"""Shortcut to create a reference node."""
node = nodes.reference('', '', internal=True)
diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py
index b8cff73bd..d495876cf 100644
--- a/sphinx/util/osutil.py
+++ b/sphinx/util/osutil.py
@@ -11,7 +11,7 @@ import sys
import unicodedata
from io import StringIO
from os import path
-from typing import Any, Generator, Iterator, Optional
+from typing import Any, Generator, Iterator
try:
# for ALT Linux (#6712)
@@ -114,7 +114,7 @@ def make_filename_from_project(project: str) -> str:
return make_filename(project_suffix_re.sub('', project)).lower()
-def relpath(path: str, start: Optional[str] = os.curdir) -> str:
+def relpath(path: str, start: str | None = os.curdir) -> str:
"""Return a relative filepath to *path* either from the current directory or
from an optional *start* directory.
@@ -170,7 +170,7 @@ class FileAvoidWrite:
"""
def __init__(self, path: str) -> None:
self._path = path
- self._io: Optional[StringIO] = None
+ self._io: StringIO | None = None
def write(self, data: str) -> None:
if not self._io:
diff --git a/sphinx/util/parallel.py b/sphinx/util/parallel.py
index 55386c56a..fec275572 100644
--- a/sphinx/util/parallel.py
+++ b/sphinx/util/parallel.py
@@ -6,7 +6,7 @@ import os
import time
import traceback
from math import sqrt
-from typing import Any, Callable, Optional, Sequence
+from typing import Any, Callable, Sequence
try:
import multiprocessing
@@ -30,7 +30,7 @@ class SerialTasks:
pass
def add_task(
- self, task_func: Callable, arg: Any = None, result_func: Optional[Callable] = None
+ self, task_func: Callable, arg: Any = None, result_func: Callable | None = None
) -> None:
if arg is not None:
res = task_func(arg)
@@ -51,7 +51,7 @@ class ParallelTasks:
# (optional) function performed by each task on the result of main task
self._result_funcs: dict[int, Callable] = {}
# task arguments
- self._args: dict[int, Optional[list[Any]]] = {}
+ self._args: dict[int, list[Any] | None] = {}
# list of subprocesses (both started and waiting)
self._procs: dict[int, Any] = {}
# list of receiving pipe connections of running subprocesses
@@ -80,7 +80,7 @@ class ParallelTasks:
pipe.send((failed, collector.logs, ret))
def add_task(
- self, task_func: Callable, arg: Any = None, result_func: Optional[Callable] = None
+ self, task_func: Callable, arg: Any = None, result_func: Callable | None = None
) -> None:
tid = self._taskid
self._taskid += 1
diff --git a/sphinx/util/png.py b/sphinx/util/png.py
index d2718da18..6c942194e 100644
--- a/sphinx/util/png.py
+++ b/sphinx/util/png.py
@@ -4,7 +4,6 @@ from __future__ import annotations
import binascii
import struct
-from typing import Optional
LEN_IEND = 12
LEN_DEPTH = 22
@@ -14,7 +13,7 @@ DEPTH_CHUNK_START = b'tEXtDepth\x00'
IEND_CHUNK = b'\x00\x00\x00\x00IEND\xAE\x42\x60\x82'
-def read_png_depth(filename: str) -> Optional[int]:
+def read_png_depth(filename: str) -> int | None:
"""Read the special tEXt chunk indicating the depth from a PNG file."""
with open(filename, 'rb') as f:
f.seek(- (LEN_IEND + LEN_DEPTH), 2)
diff --git a/sphinx/util/requests.py b/sphinx/util/requests.py
index 0b1058b88..c64754fa2 100644
--- a/sphinx/util/requests.py
+++ b/sphinx/util/requests.py
@@ -5,7 +5,7 @@ from __future__ import annotations
import sys
import warnings
from contextlib import contextmanager
-from typing import Any, Generator, Union
+from typing import Any, Generator
from urllib.parse import urlsplit
import requests
@@ -27,7 +27,7 @@ def ignore_insecure_warning(**kwargs: Any) -> Generator[None, None, None]:
yield
-def _get_tls_cacert(url: str, config: Config) -> Union[str, bool]:
+def _get_tls_cacert(url: str, config: Config) -> str | bool:
"""Get additional CA cert for a specific URL.
This also returns ``False`` if verification is disabled.
diff --git a/sphinx/util/tags.py b/sphinx/util/tags.py
index d6cbac97b..b44d97b3b 100644
--- a/sphinx/util/tags.py
+++ b/sphinx/util/tags.py
@@ -1,6 +1,6 @@
from __future__ import annotations
-from typing import Iterator, Optional
+from typing import Iterator
from jinja2 import nodes
from jinja2.environment import Environment
@@ -37,7 +37,7 @@ class BooleanParser(Parser):
class Tags:
- def __init__(self, tags: Optional[list[str]] = None) -> None:
+ def __init__(self, tags: list[str] | None = None) -> None:
self.tags = dict.fromkeys(tags or [], True)
def has(self, tag: str) -> bool:
diff --git a/sphinx/util/template.py b/sphinx/util/template.py
index 3b7fbf106..557795053 100644
--- a/sphinx/util/template.py
+++ b/sphinx/util/template.py
@@ -5,7 +5,7 @@ from __future__ import annotations
import os
from functools import partial
from os import path
-from typing import Any, Callable, Optional, Union
+from typing import Any, Callable
from jinja2 import TemplateNotFound
from jinja2.environment import Environment
@@ -19,7 +19,7 @@ from sphinx.util import rst, texescape
class BaseRenderer:
- def __init__(self, loader: Optional[BaseLoader] = None) -> None:
+ def __init__(self, loader: BaseLoader | None = None) -> None:
self.env = SandboxedEnvironment(loader=loader, extensions=['jinja2.ext.i18n'])
self.env.filters['repr'] = repr
self.env.install_gettext_translations(get_translator())
@@ -32,7 +32,7 @@ class BaseRenderer:
class FileRenderer(BaseRenderer):
- def __init__(self, search_path: Union[str, list[str]]) -> None:
+ def __init__(self, search_path: str | list[str]) -> None:
if isinstance(search_path, str):
search_path = [search_path]
else:
@@ -50,7 +50,7 @@ class FileRenderer(BaseRenderer):
class SphinxRenderer(FileRenderer):
- def __init__(self, template_path: Union[None, str, list[str]] = None) -> None:
+ def __init__(self, template_path: None | str | list[str] = None) -> None:
if template_path is None:
template_path = os.path.join(package_dir, 'templates')
super().__init__(template_path)
@@ -62,7 +62,7 @@ class SphinxRenderer(FileRenderer):
class LaTeXRenderer(SphinxRenderer):
def __init__(
- self, template_path: Optional[str] = None, latex_engine: Optional[str] = None
+ self, template_path: str | None = None, latex_engine: str | None = None
) -> None:
if template_path is None:
template_path = os.path.join(package_dir, 'templates', 'latex')
@@ -86,7 +86,7 @@ class LaTeXRenderer(SphinxRenderer):
class ReSTRenderer(SphinxRenderer):
def __init__(
- self, template_path: Union[None, str, list[str]] = None, language: Optional[str] = None
+ self, template_path: None | str | list[str] = None, language: str | None = None
) -> None:
super().__init__(template_path)
diff --git a/sphinx/util/texescape.py b/sphinx/util/texescape.py
index 7dc7f7582..8527441d7 100644
--- a/sphinx/util/texescape.py
+++ b/sphinx/util/texescape.py
@@ -3,7 +3,6 @@
from __future__ import annotations
import re
-from typing import Optional
tex_replacements = [
# map TeX special chars
@@ -102,7 +101,7 @@ _tex_hlescape_map: dict[int, str] = {}
_tex_hlescape_map_without_unicode: dict[int, str] = {}
-def escape(s: str, latex_engine: Optional[str] = None) -> str:
+def escape(s: str, latex_engine: str | None = None) -> str:
"""Escape text for LaTeX output."""
if latex_engine in ('lualatex', 'xelatex'):
# unicode based LaTeX engine
@@ -111,7 +110,7 @@ def escape(s: str, latex_engine: Optional[str] = None) -> str:
return s.translate(_tex_escape_map)
-def hlescape(s: str, latex_engine: Optional[str] = None) -> str:
+def hlescape(s: str, latex_engine: str | None = None) -> str:
"""Escape text for LaTeX highlighter."""
if latex_engine in ('lualatex', 'xelatex'):
# unicode based LaTeX engine
diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py
index b8bc2fd0a..5c44eed01 100644
--- a/sphinx/util/typing.py
+++ b/sphinx/util/typing.py
@@ -6,7 +6,7 @@ import sys
import typing
from struct import Struct
from types import TracebackType
-from typing import Any, Callable, Dict, ForwardRef, List, Optional, Tuple, TypeVar, Union
+from typing import Any, Callable, Dict, ForwardRef, List, Tuple, TypeVar, Union
from docutils import nodes
from docutils.parsers.rst.states import Inliner
@@ -56,7 +56,7 @@ Inventory = Dict[str, Dict[str, InventoryItem]]
def get_type_hints(
- obj: Any, globalns: Optional[dict[str, Any]] = None, localns: Optional[dict] = None
+ obj: Any, globalns: dict[str, Any] | None = None, localns: dict | None = None
) -> dict[str, Any]:
"""Return a dictionary containing type hints for a function, method, module or class
object.
@@ -89,7 +89,7 @@ def is_system_TypeVar(typ: Any) -> bool:
return modname == 'typing' and isinstance(typ, TypeVar)
-def restify(cls: Optional[type], mode: str = 'fully-qualified-except-typing') -> str:
+def restify(cls: type | None, mode: str = 'fully-qualified-except-typing') -> str:
"""Convert python class to a reST reference.
:param mode: Specify a method how annotations will be stringified.
diff --git a/sphinx/writers/_html4.py b/sphinx/writers/_html4.py
index 00a31e859..56ad5b554 100644
--- a/sphinx/writers/_html4.py
+++ b/sphinx/writers/_html4.py
@@ -6,7 +6,7 @@ import os
import posixpath
import re
import urllib.parse
-from typing import TYPE_CHECKING, Iterable, Optional, cast
+from typing import TYPE_CHECKING, Iterable, cast
from docutils import nodes
from docutils.nodes import Element, Node, Text
@@ -246,7 +246,7 @@ class HTML4Translator(SphinxTranslator, BaseTranslator):
node.insert(0, nodes.title(name, admonitionlabels[name]))
self.set_first_last(node)
- def depart_admonition(self, node: Optional[Element] = None) -> None:
+ def depart_admonition(self, node: Element | None = None) -> None:
self.body.append('</div>\n')
def visit_seealso(self, node: Element) -> None:
@@ -255,7 +255,7 @@ class HTML4Translator(SphinxTranslator, BaseTranslator):
def depart_seealso(self, node: Element) -> None:
self.depart_admonition(node)
- def get_secnumber(self, node: Element) -> Optional[tuple[int, ...]]:
+ def get_secnumber(self, node: Element) -> tuple[int, ...] | None:
if node.get('secnumber'):
return node['secnumber']
elif isinstance(node.parent, nodes.section):
diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py
index bfb2515a5..e07e86ab4 100644
--- a/sphinx/writers/html5.py
+++ b/sphinx/writers/html5.py
@@ -6,7 +6,7 @@ import os
import posixpath
import re
import urllib.parse
-from typing import TYPE_CHECKING, Iterable, Optional, cast
+from typing import TYPE_CHECKING, Iterable, cast
from docutils import nodes
from docutils.nodes import Element, Node, Text
@@ -251,7 +251,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
if name:
node.insert(0, nodes.title(name, admonitionlabels[name]))
- def depart_admonition(self, node: Optional[Element] = None) -> None:
+ def depart_admonition(self, node: Element | None = None) -> None:
self.body.append('</div>\n')
def visit_seealso(self, node: Element) -> None:
@@ -260,7 +260,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
def depart_seealso(self, node: Element) -> None:
self.depart_admonition(node)
- def get_secnumber(self, node: Element) -> Optional[tuple[int, ...]]:
+ def get_secnumber(self, node: Element) -> tuple[int, ...] | None:
if node.get('secnumber'):
return node['secnumber']
diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py
index b379697ad..f5be84f76 100644
--- a/sphinx/writers/latex.py
+++ b/sphinx/writers/latex.py
@@ -198,7 +198,7 @@ class Table:
self.cells[(self.row + row, self.col + col)] = self.cell_id
def cell(
- self, row: Optional[int] = None, col: Optional[int] = None
+ self, row: int | None = None, col: int | None = None
) -> Optional["TableCell"]:
"""Returns a cell object (i.e. rectangular area) containing given position.
@@ -414,9 +414,9 @@ class LaTeXTranslator(SphinxTranslator):
self.context: list[Any] = []
self.descstack: list[str] = []
self.tables: list[Table] = []
- self.next_table_colspec: Optional[str] = None
+ self.next_table_colspec: str | None = None
self.bodystack: list[list[str]] = []
- self.footnote_restricted: Optional[Element] = None
+ self.footnote_restricted: Element | None = None
self.pending_footnotes: list[nodes.footnote_reference] = []
self.curfilestack: list[str] = []
self.handled_abbrs: set[str] = set()
@@ -523,7 +523,7 @@ class LaTeXTranslator(SphinxTranslator):
return renderer.render(template_name, variables)
@property
- def table(self) -> Optional[Table]:
+ def table(self) -> Table | None:
"""Get current table."""
if self.tables:
return self.tables[-1]
@@ -1241,7 +1241,7 @@ class LaTeXTranslator(SphinxTranslator):
# self.body.append(r'\columnbreak\n')
pass
- def latex_image_length(self, width_str: str, scale: int = 100) -> Optional[str]:
+ def latex_image_length(self, width_str: str, scale: int = 100) -> str | None:
try:
return rstdim_to_latexdim(width_str, scale)
except ValueError:
diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py
index d8fa4af32..08d030443 100644
--- a/sphinx/writers/texinfo.py
+++ b/sphinx/writers/texinfo.py
@@ -5,7 +5,7 @@ from __future__ import annotations
import re
import textwrap
from os import path
-from typing import TYPE_CHECKING, Any, Iterable, Iterator, Optional, Union, cast
+from typing import TYPE_CHECKING, Any, Iterable, Iterator, cast
from docutils import nodes, writers
from docutils.nodes import Element, Node, Text
@@ -92,7 +92,7 @@ def find_subsections(section: Element) -> list[nodes.section]:
return result
-def smart_capwords(s: str, sep: Optional[str] = None) -> str:
+def smart_capwords(s: str, sep: str | None = None) -> str:
"""Like string.capwords() but does not capitalize words that already
contain a capital letter."""
words = s.split(sep)
@@ -116,7 +116,7 @@ class TexinfoWriter(writers.Writer):
settings_defaults: dict = {}
- output: Optional[str] = None # type: ignore[assignment]
+ output: str | None = None # type: ignore[assignment]
visitor_attributes = ('output', 'fragment')
@@ -174,14 +174,14 @@ class TexinfoTranslator(SphinxTranslator):
self.body: list[str] = []
self.context: list[str] = []
self.descs: list[addnodes.desc] = []
- self.previous_section: Optional[nodes.section] = None
+ self.previous_section: nodes.section | None = None
self.section_level = 0
self.seen_title = False
self.next_section_ids: set[str] = set()
self.escape_newlines = 0
self.escape_hyphens = 0
self.curfilestack: list[str] = []
- self.footnotestack: list[dict[str, list[Union[collected_footnote, bool]]]] = []
+ self.footnotestack: list[dict[str, list[collected_footnote | bool]]] = []
self.in_footnote = 0
self.in_samp = 0
self.handled_abbrs: set[str] = set()
@@ -493,7 +493,7 @@ class TexinfoTranslator(SphinxTranslator):
def collect_footnotes(
self, node: Element
- ) -> dict[str, list[Union[collected_footnote, bool]]]:
+ ) -> dict[str, list[collected_footnote | bool]]:
def footnotes_under(n: Element) -> Iterator[nodes.footnote]:
if isinstance(n, nodes.footnote):
yield n
@@ -503,7 +503,7 @@ class TexinfoTranslator(SphinxTranslator):
continue
elif isinstance(c, nodes.Element):
yield from footnotes_under(c)
- fnotes: dict[str, list[Union[collected_footnote, bool]]] = {}
+ fnotes: dict[str, list[collected_footnote | bool]] = {}
for fn in footnotes_under(node):
label = cast(nodes.label, fn[0])
num = label.astext().strip()
@@ -768,10 +768,10 @@ class TexinfoTranslator(SphinxTranslator):
self.ensure_eol()
self.body.append('@end quotation\n')
- def visit_literal_block(self, node: Optional[Element]) -> None:
+ def visit_literal_block(self, node: Element | None) -> None:
self.body.append('\n@example\n')
- def depart_literal_block(self, node: Optional[Element]) -> None:
+ def depart_literal_block(self, node: Element | None) -> None:
self.ensure_eol()
self.body.append('@end example\n')
@@ -1407,7 +1407,7 @@ class TexinfoTranslator(SphinxTranslator):
category = self.escape_arg(smart_capwords(name))
self.body.append('\n%s {%s} ' % (self.at_deffnx, category))
self.at_deffnx = '@deffnx'
- self.desc_type_name: Optional[str] = name
+ self.desc_type_name: str | None = name
def depart_desc_signature(self, node: Element) -> None:
self.body.append("\n")
diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py
index 37c003559..d437fb3d5 100644
--- a/sphinx/writers/text.py
+++ b/sphinx/writers/text.py
@@ -6,7 +6,7 @@ import os
import re
import textwrap
from itertools import chain, groupby
-from typing import TYPE_CHECKING, Any, Generator, Iterable, Optional, Union, cast
+from typing import TYPE_CHECKING, Any, Generator, Iterable, cast
from docutils import nodes, writers
from docutils.nodes import Element, Text
@@ -29,8 +29,8 @@ class Cell:
self.wrapped: list[str] = []
self.rowspan = rowspan
self.colspan = colspan
- self.col: Optional[int] = None
- self.row: Optional[int] = None
+ self.col: int | None = None
+ self.row: int | None = None
def __repr__(self) -> str:
return "<Cell {!r} {}v{}/{}>{}>".format(
@@ -192,7 +192,7 @@ class Table:
out = []
self.rewrap()
- def writesep(char: str = "-", lineno: Optional[int] = None) -> str:
+ def writesep(char: str = "-", lineno: int | None = None) -> str:
"""Called on the line *before* lineno.
Called with no *lineno* for the last sep.
"""
@@ -388,7 +388,7 @@ class TextTranslator(SphinxTranslator):
self.sectionchars = self.config.text_sectionchars
self.add_secnumbers = self.config.text_add_secnumbers
self.secnumber_suffix = self.config.text_secnumber_suffix
- self.states: list[list[tuple[int, Union[str, list[str]]]]] = [[]]
+ self.states: list[list[tuple[int, str | list[str]]]] = [[]]
self.stateindent = [0]
self.list_counter: list[int] = []
self.sectionlevel = 0