diff options
author | Adam Turner <9087854+aa-turner@users.noreply.github.com> | 2023-01-01 20:43:59 +0000 |
---|---|---|
committer | Adam Turner <9087854+aa-turner@users.noreply.github.com> | 2023-01-01 20:48:39 +0000 |
commit | 14a9289d780240bbce78ad3640e8e1b1b12df43f (patch) | |
tree | fd753f5b0f8c7053923b78c8fef2b90b60f9c7fa | |
parent | 26f79b0d2dd88b353ac65623897bdfbe8bc07cab (diff) | |
download | sphinx-git-14a9289d780240bbce78ad3640e8e1b1b12df43f.tar.gz |
Use PEP 604 types
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 |