mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Migrate to py3 style type annotation: sphinx.environment
This commit is contained in:
@@ -15,14 +15,22 @@ from collections import defaultdict
|
||||
from copy import copy
|
||||
from io import BytesIO
|
||||
from os import path
|
||||
from typing import Any, Callable, Dict, Generator, IO, Iterator, List, Set, Tuple, Union
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.nodes import Node
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.config import Config
|
||||
from sphinx.deprecation import (
|
||||
RemovedInSphinx30Warning, RemovedInSphinx40Warning, deprecated_alias
|
||||
)
|
||||
from sphinx.domains import Domain
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
from sphinx.errors import SphinxError, BuildEnvironmentError, DocumentError, ExtensionError
|
||||
from sphinx.events import EventManager
|
||||
from sphinx.locale import __
|
||||
from sphinx.project import Project
|
||||
from sphinx.transforms import SphinxTransformer
|
||||
from sphinx.util import DownloadFiles, FilenameUniqDict
|
||||
from sphinx.util import logging
|
||||
@@ -32,14 +40,8 @@ from sphinx.util.nodes import is_translatable
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Callable, Dict, IO, Iterator, List, Optional, Set, Tuple, Union # NOQA
|
||||
from docutils import nodes # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.builders import Builder # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
from sphinx.event import EventManager # NOQA
|
||||
from sphinx.domains import Domain # NOQA
|
||||
from sphinx.project import Project # NOQA
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -92,8 +94,7 @@ class BuildEnvironment:
|
||||
|
||||
# --------- ENVIRONMENT INITIALIZATION -------------------------------------
|
||||
|
||||
def __init__(self, app=None):
|
||||
# type: (Sphinx) -> None
|
||||
def __init__(self, app: "Sphinx" = None):
|
||||
self.app = None # type: Sphinx
|
||||
self.doctreedir = None # type: str
|
||||
self.srcdir = None # type: str
|
||||
@@ -191,19 +192,16 @@ class BuildEnvironment:
|
||||
if app:
|
||||
self.setup(app)
|
||||
|
||||
def __getstate__(self):
|
||||
# type: () -> Dict
|
||||
def __getstate__(self) -> Dict:
|
||||
"""Obtains serializable data for pickling."""
|
||||
__dict__ = self.__dict__.copy()
|
||||
__dict__.update(app=None, domains={}, events=None) # clear unpickable attributes
|
||||
return __dict__
|
||||
|
||||
def __setstate__(self, state):
|
||||
# type: (Dict) -> None
|
||||
def __setstate__(self, state: Dict) -> None:
|
||||
self.__dict__.update(state)
|
||||
|
||||
def setup(self, app):
|
||||
# type: (Sphinx) -> None
|
||||
def setup(self, app: "Sphinx") -> None:
|
||||
"""Set up BuildEnvironment object."""
|
||||
if self.version and self.version != app.registry.get_envversion(app):
|
||||
raise BuildEnvironmentError(__('build environment version not current'))
|
||||
@@ -231,8 +229,7 @@ class BuildEnvironment:
|
||||
# initialie settings
|
||||
self._update_settings(app.config)
|
||||
|
||||
def _update_config(self, config):
|
||||
# type: (Config) -> None
|
||||
def _update_config(self, config: Config) -> None:
|
||||
"""Update configurations by new one."""
|
||||
self.config_status = CONFIG_OK
|
||||
if self.config is None:
|
||||
@@ -249,8 +246,7 @@ class BuildEnvironment:
|
||||
|
||||
self.config = config
|
||||
|
||||
def _update_settings(self, config):
|
||||
# type: (Config) -> None
|
||||
def _update_settings(self, config: Config) -> None:
|
||||
"""Update settings by new config."""
|
||||
self.settings['input_encoding'] = config.source_encoding
|
||||
self.settings['trim_footnote_reference_space'] = config.trim_footnote_reference_space
|
||||
@@ -259,8 +255,7 @@ class BuildEnvironment:
|
||||
# Allow to disable by 3rd party extension (workaround)
|
||||
self.settings.setdefault('smart_quotes', True)
|
||||
|
||||
def set_versioning_method(self, method, compare):
|
||||
# type: (Union[str, Callable], bool) -> None
|
||||
def set_versioning_method(self, method: Union[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
|
||||
@@ -283,8 +278,7 @@ class BuildEnvironment:
|
||||
self.versioning_condition = condition
|
||||
self.versioning_compare = compare
|
||||
|
||||
def clear_doc(self, docname):
|
||||
# type: (str) -> None
|
||||
def clear_doc(self, docname: str) -> None:
|
||||
"""Remove all traces of a source file in the inventory."""
|
||||
if docname in self.all_docs:
|
||||
self.all_docs.pop(docname, None)
|
||||
@@ -294,8 +288,8 @@ class BuildEnvironment:
|
||||
for domain in self.domains.values():
|
||||
domain.clear_doc(docname)
|
||||
|
||||
def merge_info_from(self, docnames, other, app):
|
||||
# type: (List[str], BuildEnvironment, Sphinx) -> None
|
||||
def merge_info_from(self, docnames: List[str], other: "BuildEnvironment",
|
||||
app: "Sphinx") -> None:
|
||||
"""Merge global information gathered about *docnames* while reading them
|
||||
from the *other* environment.
|
||||
|
||||
@@ -312,16 +306,14 @@ class BuildEnvironment:
|
||||
domain.merge_domaindata(docnames, other.domaindata[domainname])
|
||||
self.events.emit('env-merge-info', self, docnames, other)
|
||||
|
||||
def path2doc(self, filename):
|
||||
# type: (str) -> Optional[str]
|
||||
def path2doc(self, filename: str) -> str:
|
||||
"""Return the docname for the filename if the file is document.
|
||||
|
||||
*filename* should be absolute or relative to the source directory.
|
||||
"""
|
||||
return self.project.path2doc(filename)
|
||||
|
||||
def doc2path(self, docname, base=True, suffix=None):
|
||||
# type: (str, Union[bool, str], str) -> str
|
||||
def doc2path(self, docname: str, base: Union[bool, str] = True, suffix: str = None) -> str:
|
||||
"""Return the filename for the document name.
|
||||
|
||||
If *base* is True, return absolute path under self.srcdir.
|
||||
@@ -344,8 +336,7 @@ class BuildEnvironment:
|
||||
pathname = path.join(base, pathname) # type: ignore
|
||||
return pathname
|
||||
|
||||
def relfn2path(self, filename, docname=None):
|
||||
# type: (str, str) -> Tuple[str, str]
|
||||
def relfn2path(self, filename: str, docname: str = None) -> Tuple[str, str]:
|
||||
"""Return paths to a file referenced from a document, relative to
|
||||
documentation root and absolute.
|
||||
|
||||
@@ -364,13 +355,11 @@ class BuildEnvironment:
|
||||
return rel_fn, path.abspath(path.join(self.srcdir, rel_fn))
|
||||
|
||||
@property
|
||||
def found_docs(self):
|
||||
# type: () -> Set[str]
|
||||
def found_docs(self) -> Set[str]:
|
||||
"""contains all existing docnames."""
|
||||
return self.project.docnames
|
||||
|
||||
def find_files(self, config, builder):
|
||||
# type: (Config, Builder) -> None
|
||||
def find_files(self, config: Config, builder: "Builder") -> None:
|
||||
"""Find all source files in the source dir and put them in
|
||||
self.found_docs.
|
||||
"""
|
||||
@@ -398,8 +387,7 @@ class BuildEnvironment:
|
||||
except OSError as exc:
|
||||
raise DocumentError(__('Failed to scan documents in %s: %r') % (self.srcdir, exc))
|
||||
|
||||
def get_outdated_files(self, config_changed):
|
||||
# type: (bool) -> Tuple[Set[str], Set[str], Set[str]]
|
||||
def get_outdated_files(self, config_changed: bool) -> Tuple[Set[str], Set[str], Set[str]]:
|
||||
"""Return (added, changed, removed) sets."""
|
||||
# clear all files no longer present
|
||||
removed = set(self.all_docs) - self.found_docs
|
||||
@@ -449,8 +437,7 @@ class BuildEnvironment:
|
||||
|
||||
return added, changed, removed
|
||||
|
||||
def check_dependents(self, app, already):
|
||||
# type: (Sphinx, Set[str]) -> Iterator[str]
|
||||
def check_dependents(self, app: "Sphinx", already: Set[str]) -> Generator[str, None, None]:
|
||||
to_rewrite = [] # type: List[str]
|
||||
for docnames in self.events.emit('env-get-updated', self):
|
||||
to_rewrite.extend(docnames)
|
||||
@@ -460,8 +447,7 @@ class BuildEnvironment:
|
||||
|
||||
# --------- SINGLE FILE READING --------------------------------------------
|
||||
|
||||
def prepare_settings(self, docname):
|
||||
# type: (str) -> None
|
||||
def prepare_settings(self, docname: str) -> None:
|
||||
"""Prepare to set up environment for reading."""
|
||||
self.temp_data['docname'] = docname
|
||||
# defaults to the global default, but can be re-set in a document
|
||||
@@ -472,13 +458,11 @@ class BuildEnvironment:
|
||||
# utilities to use while reading a document
|
||||
|
||||
@property
|
||||
def docname(self):
|
||||
# type: () -> str
|
||||
def docname(self) -> str:
|
||||
"""Returns the docname of the document currently being parsed."""
|
||||
return self.temp_data['docname']
|
||||
|
||||
def new_serialno(self, category=''):
|
||||
# type: (str) -> int
|
||||
def new_serialno(self, category: str = '') -> int:
|
||||
"""Return a serial number, e.g. for index entry targets.
|
||||
|
||||
The number is guaranteed to be unique in the current document.
|
||||
@@ -488,8 +472,7 @@ class BuildEnvironment:
|
||||
self.temp_data[key] = cur + 1
|
||||
return cur
|
||||
|
||||
def note_dependency(self, filename):
|
||||
# type: (str) -> None
|
||||
def note_dependency(self, filename: str) -> None:
|
||||
"""Add *filename* as a dependency of the current document.
|
||||
|
||||
This means that the document will be rebuilt if this file changes.
|
||||
@@ -498,8 +481,7 @@ class BuildEnvironment:
|
||||
"""
|
||||
self.dependencies[self.docname].add(filename)
|
||||
|
||||
def note_included(self, filename):
|
||||
# type: (str) -> None
|
||||
def note_included(self, filename: str) -> None:
|
||||
"""Add *filename* as a included from other document.
|
||||
|
||||
This means the document is not orphaned.
|
||||
@@ -508,15 +490,13 @@ class BuildEnvironment:
|
||||
"""
|
||||
self.included[self.docname].add(self.path2doc(filename))
|
||||
|
||||
def note_reread(self):
|
||||
# type: () -> None
|
||||
def note_reread(self) -> None:
|
||||
"""Add the current document to the list of documents that will
|
||||
automatically be re-read at the next build.
|
||||
"""
|
||||
self.reread_always.add(self.docname)
|
||||
|
||||
def get_domain(self, domainname):
|
||||
# type: (str) -> Domain
|
||||
def get_domain(self, domainname: str) -> Domain:
|
||||
"""Return the domain instance with the specified name.
|
||||
|
||||
Raises an ExtensionError if the domain is not registered.
|
||||
@@ -528,8 +508,7 @@ class BuildEnvironment:
|
||||
|
||||
# --------- RESOLVING REFERENCES AND TOCTREES ------------------------------
|
||||
|
||||
def get_doctree(self, docname):
|
||||
# type: (str) -> nodes.document
|
||||
def get_doctree(self, docname: str) -> nodes.document:
|
||||
"""Read the doctree for a file from the pickle and return it."""
|
||||
filename = path.join(self.doctreedir, docname + '.doctree')
|
||||
with open(filename, 'rb') as f:
|
||||
@@ -538,9 +517,9 @@ class BuildEnvironment:
|
||||
doctree.reporter = LoggingReporter(self.doc2path(docname))
|
||||
return doctree
|
||||
|
||||
def get_and_resolve_doctree(self, docname, builder, doctree=None,
|
||||
prune_toctrees=True, includehidden=False):
|
||||
# type: (str, Builder, nodes.document, bool, bool) -> nodes.document
|
||||
def get_and_resolve_doctree(self, docname: str, builder: "Builder",
|
||||
doctree: nodes.document = None, prune_toctrees: bool = True,
|
||||
includehidden: bool = False) -> nodes.document:
|
||||
"""Read the doctree from the pickle, resolve cross-references and
|
||||
toctrees and return it.
|
||||
"""
|
||||
@@ -562,9 +541,9 @@ class BuildEnvironment:
|
||||
|
||||
return doctree
|
||||
|
||||
def resolve_toctree(self, docname, builder, toctree, prune=True, maxdepth=0,
|
||||
titles_only=False, collapse=False, includehidden=False):
|
||||
# type: (str, Builder, addnodes.toctree, bool, int, bool, bool, bool) -> nodes.Node
|
||||
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) -> Node:
|
||||
"""Resolve a *toctree* node into individual bullet lists with titles
|
||||
as items, returning None (if no containing titles are found) or
|
||||
a new node.
|
||||
@@ -580,12 +559,11 @@ class BuildEnvironment:
|
||||
maxdepth, titles_only, collapse,
|
||||
includehidden)
|
||||
|
||||
def resolve_references(self, doctree, fromdocname, builder):
|
||||
# type: (nodes.document, str, Builder) -> None
|
||||
def resolve_references(self, doctree: nodes.document, fromdocname: str,
|
||||
builder: "Builder") -> None:
|
||||
self.apply_post_transforms(doctree, fromdocname)
|
||||
|
||||
def apply_post_transforms(self, doctree, docname):
|
||||
# type: (nodes.document, str) -> None
|
||||
def apply_post_transforms(self, doctree: nodes.document, docname: str) -> None:
|
||||
"""Apply all post-transforms."""
|
||||
try:
|
||||
# set env.docname during applying post-transforms
|
||||
@@ -602,12 +580,10 @@ class BuildEnvironment:
|
||||
# allow custom references to be resolved
|
||||
self.events.emit('doctree-resolved', doctree, docname)
|
||||
|
||||
def collect_relations(self):
|
||||
# type: () -> Dict[str, List[str]]
|
||||
def collect_relations(self) -> Dict[str, List[str]]:
|
||||
traversed = set()
|
||||
|
||||
def traverse_toctree(parent, docname):
|
||||
# type: (str, str) -> Iterator[Tuple[str, str]]
|
||||
def traverse_toctree(parent: str, docname: str) -> Iterator[Tuple[str, str]]:
|
||||
if parent == docname:
|
||||
logger.warning(__('self referenced toctree found. Ignored.'), location=docname)
|
||||
return
|
||||
@@ -636,8 +612,7 @@ class BuildEnvironment:
|
||||
|
||||
return relations
|
||||
|
||||
def check_consistency(self):
|
||||
# type: () -> None
|
||||
def check_consistency(self) -> None:
|
||||
"""Do consistency checks."""
|
||||
included = set().union(*self.included.values()) # type: ignore
|
||||
for docname in sorted(self.all_docs):
|
||||
@@ -660,48 +635,41 @@ class BuildEnvironment:
|
||||
|
||||
# --------- METHODS FOR COMPATIBILITY --------------------------------------
|
||||
|
||||
def update(self, config, srcdir, doctreedir):
|
||||
# type: (Config, str, str) -> List[str]
|
||||
def update(self, config: Config, srcdir: str, doctreedir: str) -> List[str]:
|
||||
warnings.warn('env.update() is deprecated. Please use builder.read() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
return self.app.builder.read()
|
||||
|
||||
def _read_serial(self, docnames, app):
|
||||
# type: (List[str], Sphinx) -> None
|
||||
def _read_serial(self, docnames: List[str], app: "Sphinx") -> None:
|
||||
warnings.warn('env._read_serial() is deprecated. Please use builder.read() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
return self.app.builder._read_serial(docnames)
|
||||
|
||||
def _read_parallel(self, docnames, app, nproc):
|
||||
# type: (List[str], Sphinx, int) -> None
|
||||
def _read_parallel(self, docnames: List[str], app: "Sphinx", nproc: int) -> None:
|
||||
warnings.warn('env._read_parallel() is deprecated. Please use builder.read() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
return self.app.builder._read_parallel(docnames, nproc)
|
||||
|
||||
def read_doc(self, docname, app=None):
|
||||
# type: (str, Sphinx) -> None
|
||||
def read_doc(self, docname: str, app: "Sphinx" = None) -> None:
|
||||
warnings.warn('env.read_doc() is deprecated. Please use builder.read_doc() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
self.app.builder.read_doc(docname)
|
||||
|
||||
def write_doctree(self, docname, doctree):
|
||||
# type: (str, nodes.document) -> None
|
||||
def write_doctree(self, docname: str, doctree: nodes.document) -> None:
|
||||
warnings.warn('env.write_doctree() is deprecated. '
|
||||
'Please use builder.write_doctree() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
self.app.builder.write_doctree(docname, doctree)
|
||||
|
||||
@property
|
||||
def _nitpick_ignore(self):
|
||||
# type: () -> List[str]
|
||||
def _nitpick_ignore(self) -> List[str]:
|
||||
warnings.warn('env._nitpick_ignore is deprecated. '
|
||||
'Please use config.nitpick_ignore instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
return self.config.nitpick_ignore
|
||||
|
||||
@staticmethod
|
||||
def load(f, app=None):
|
||||
# type: (IO, Sphinx) -> BuildEnvironment
|
||||
def load(f: IO, app: "Sphinx" = None) -> "BuildEnvironment":
|
||||
warnings.warn('BuildEnvironment.load() is deprecated. '
|
||||
'Please use pickle.load() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
@@ -717,8 +685,7 @@ class BuildEnvironment:
|
||||
return env
|
||||
|
||||
@classmethod
|
||||
def loads(cls, string, app=None):
|
||||
# type: (bytes, Sphinx) -> BuildEnvironment
|
||||
def loads(cls, string: bytes, app: "Sphinx" = None) -> "BuildEnvironment":
|
||||
warnings.warn('BuildEnvironment.loads() is deprecated. '
|
||||
'Please use pickle.loads() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
@@ -726,8 +693,7 @@ class BuildEnvironment:
|
||||
return cls.load(io, app)
|
||||
|
||||
@classmethod
|
||||
def frompickle(cls, filename, app):
|
||||
# type: (str, Sphinx) -> BuildEnvironment
|
||||
def frompickle(cls, filename: str, app: "Sphinx") -> "BuildEnvironment":
|
||||
warnings.warn('BuildEnvironment.frompickle() is deprecated. '
|
||||
'Please use pickle.load() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
@@ -735,16 +701,14 @@ class BuildEnvironment:
|
||||
return cls.load(f, app)
|
||||
|
||||
@staticmethod
|
||||
def dump(env, f):
|
||||
# type: (BuildEnvironment, IO) -> None
|
||||
def dump(env: "BuildEnvironment", f: IO) -> None:
|
||||
warnings.warn('BuildEnvironment.dump() is deprecated. '
|
||||
'Please use pickle.dump() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
pickle.dump(env, f, pickle.HIGHEST_PROTOCOL)
|
||||
|
||||
@classmethod
|
||||
def dumps(cls, env):
|
||||
# type: (BuildEnvironment) -> bytes
|
||||
def dumps(cls, env: "BuildEnvironment") -> bytes:
|
||||
warnings.warn('BuildEnvironment.dumps() is deprecated. '
|
||||
'Please use pickle.dumps() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
@@ -752,8 +716,7 @@ class BuildEnvironment:
|
||||
cls.dump(env, io)
|
||||
return io.getvalue()
|
||||
|
||||
def topickle(self, filename):
|
||||
# type: (str) -> None
|
||||
def topickle(self, filename: str) -> None:
|
||||
warnings.warn('env.topickle() is deprecated. '
|
||||
'Please use pickle.dump() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
@@ -761,15 +724,14 @@ class BuildEnvironment:
|
||||
self.dump(self, f)
|
||||
|
||||
@property
|
||||
def versionchanges(self):
|
||||
# type: () -> Dict[str, List[Tuple[str, str, int, str, str, str]]]
|
||||
def versionchanges(self) -> Dict[str, List[Tuple[str, str, int, str, str, str]]]:
|
||||
warnings.warn('env.versionchanges() is deprecated. '
|
||||
'Please use ChangeSetDomain instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
return self.domaindata['changeset']['changes']
|
||||
|
||||
def note_versionchange(self, type, version, node, lineno):
|
||||
# type: (str, str, addnodes.versionmodified, int) -> None
|
||||
def note_versionchange(self, type: str, version: str,
|
||||
node: addnodes.versionmodified, lineno: int) -> None:
|
||||
warnings.warn('env.note_versionchange() is deprecated. '
|
||||
'Please use ChangeSetDomain.note_changeset() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
|
||||
Reference in New Issue
Block a user