mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '2.0'
This commit is contained in:
commit
089046979f
@ -14,12 +14,20 @@ import warnings
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from os import path
|
from os import path
|
||||||
|
from typing import Any, Callable, Dict, Generator, Iterator, List, Set, Tuple, Union
|
||||||
|
|
||||||
|
from docutils import nodes
|
||||||
|
from docutils.nodes import Node
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
|
from sphinx.config import Config
|
||||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||||
|
from sphinx.domains import Domain
|
||||||
from sphinx.environment.adapters.toctree import TocTree
|
from sphinx.environment.adapters.toctree import TocTree
|
||||||
from sphinx.errors import SphinxError, BuildEnvironmentError, DocumentError, ExtensionError
|
from sphinx.errors import SphinxError, BuildEnvironmentError, DocumentError, ExtensionError
|
||||||
|
from sphinx.events import EventManager
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
|
from sphinx.project import Project
|
||||||
from sphinx.transforms import SphinxTransformer
|
from sphinx.transforms import SphinxTransformer
|
||||||
from sphinx.util import DownloadFiles, FilenameUniqDict
|
from sphinx.util import DownloadFiles, FilenameUniqDict
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
@ -29,14 +37,9 @@ from sphinx.util.nodes import is_translatable
|
|||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Callable, Dict, IO, Iterator, List, Optional, Set, Tuple, Union # NOQA
|
from sphinx.application import Sphinx
|
||||||
from docutils import nodes # NOQA
|
from sphinx.builders import Builder
|
||||||
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
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -89,8 +92,7 @@ class BuildEnvironment:
|
|||||||
|
|
||||||
# --------- ENVIRONMENT INITIALIZATION -------------------------------------
|
# --------- ENVIRONMENT INITIALIZATION -------------------------------------
|
||||||
|
|
||||||
def __init__(self, app=None):
|
def __init__(self, app: "Sphinx" = None):
|
||||||
# type: (Sphinx) -> None
|
|
||||||
self.app = None # type: Sphinx
|
self.app = None # type: Sphinx
|
||||||
self.doctreedir = None # type: str
|
self.doctreedir = None # type: str
|
||||||
self.srcdir = None # type: str
|
self.srcdir = None # type: str
|
||||||
@ -188,19 +190,16 @@ class BuildEnvironment:
|
|||||||
if app:
|
if app:
|
||||||
self.setup(app)
|
self.setup(app)
|
||||||
|
|
||||||
def __getstate__(self):
|
def __getstate__(self) -> Dict:
|
||||||
# type: () -> Dict
|
|
||||||
"""Obtains serializable data for pickling."""
|
"""Obtains serializable data for pickling."""
|
||||||
__dict__ = self.__dict__.copy()
|
__dict__ = self.__dict__.copy()
|
||||||
__dict__.update(app=None, domains={}, events=None) # clear unpickable attributes
|
__dict__.update(app=None, domains={}, events=None) # clear unpickable attributes
|
||||||
return __dict__
|
return __dict__
|
||||||
|
|
||||||
def __setstate__(self, state):
|
def __setstate__(self, state: Dict) -> None:
|
||||||
# type: (Dict) -> None
|
|
||||||
self.__dict__.update(state)
|
self.__dict__.update(state)
|
||||||
|
|
||||||
def setup(self, app):
|
def setup(self, app: "Sphinx") -> None:
|
||||||
# type: (Sphinx) -> None
|
|
||||||
"""Set up BuildEnvironment object."""
|
"""Set up BuildEnvironment object."""
|
||||||
if self.version and self.version != app.registry.get_envversion(app):
|
if self.version and self.version != app.registry.get_envversion(app):
|
||||||
raise BuildEnvironmentError(__('build environment version not current'))
|
raise BuildEnvironmentError(__('build environment version not current'))
|
||||||
@ -228,8 +227,7 @@ class BuildEnvironment:
|
|||||||
# initialie settings
|
# initialie settings
|
||||||
self._update_settings(app.config)
|
self._update_settings(app.config)
|
||||||
|
|
||||||
def _update_config(self, config):
|
def _update_config(self, config: Config) -> None:
|
||||||
# type: (Config) -> None
|
|
||||||
"""Update configurations by new one."""
|
"""Update configurations by new one."""
|
||||||
self.config_status = CONFIG_OK
|
self.config_status = CONFIG_OK
|
||||||
if self.config is None:
|
if self.config is None:
|
||||||
@ -246,8 +244,7 @@ class BuildEnvironment:
|
|||||||
|
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
def _update_settings(self, config):
|
def _update_settings(self, config: Config) -> None:
|
||||||
# type: (Config) -> None
|
|
||||||
"""Update settings by new config."""
|
"""Update settings by new config."""
|
||||||
self.settings['input_encoding'] = config.source_encoding
|
self.settings['input_encoding'] = config.source_encoding
|
||||||
self.settings['trim_footnote_reference_space'] = config.trim_footnote_reference_space
|
self.settings['trim_footnote_reference_space'] = config.trim_footnote_reference_space
|
||||||
@ -256,8 +253,7 @@ class BuildEnvironment:
|
|||||||
# Allow to disable by 3rd party extension (workaround)
|
# Allow to disable by 3rd party extension (workaround)
|
||||||
self.settings.setdefault('smart_quotes', True)
|
self.settings.setdefault('smart_quotes', True)
|
||||||
|
|
||||||
def set_versioning_method(self, method, compare):
|
def set_versioning_method(self, method: Union[str, Callable], compare: bool) -> None:
|
||||||
# type: (Union[str, Callable], bool) -> None
|
|
||||||
"""This sets the doctree versioning method for this environment.
|
"""This sets the doctree versioning method for this environment.
|
||||||
|
|
||||||
Versioning methods are a builder property; only builders with the same
|
Versioning methods are a builder property; only builders with the same
|
||||||
@ -280,8 +276,7 @@ class BuildEnvironment:
|
|||||||
self.versioning_condition = condition
|
self.versioning_condition = condition
|
||||||
self.versioning_compare = compare
|
self.versioning_compare = compare
|
||||||
|
|
||||||
def clear_doc(self, docname):
|
def clear_doc(self, docname: str) -> None:
|
||||||
# type: (str) -> None
|
|
||||||
"""Remove all traces of a source file in the inventory."""
|
"""Remove all traces of a source file in the inventory."""
|
||||||
if docname in self.all_docs:
|
if docname in self.all_docs:
|
||||||
self.all_docs.pop(docname, None)
|
self.all_docs.pop(docname, None)
|
||||||
@ -291,8 +286,8 @@ class BuildEnvironment:
|
|||||||
for domain in self.domains.values():
|
for domain in self.domains.values():
|
||||||
domain.clear_doc(docname)
|
domain.clear_doc(docname)
|
||||||
|
|
||||||
def merge_info_from(self, docnames, other, app):
|
def merge_info_from(self, docnames: List[str], other: "BuildEnvironment",
|
||||||
# type: (List[str], BuildEnvironment, Sphinx) -> None
|
app: "Sphinx") -> None:
|
||||||
"""Merge global information gathered about *docnames* while reading them
|
"""Merge global information gathered about *docnames* while reading them
|
||||||
from the *other* environment.
|
from the *other* environment.
|
||||||
|
|
||||||
@ -309,16 +304,14 @@ class BuildEnvironment:
|
|||||||
domain.merge_domaindata(docnames, other.domaindata[domainname])
|
domain.merge_domaindata(docnames, other.domaindata[domainname])
|
||||||
self.events.emit('env-merge-info', self, docnames, other)
|
self.events.emit('env-merge-info', self, docnames, other)
|
||||||
|
|
||||||
def path2doc(self, filename):
|
def path2doc(self, filename: str) -> str:
|
||||||
# type: (str) -> Optional[str]
|
|
||||||
"""Return the docname for the filename if the file is document.
|
"""Return the docname for the filename if the file is document.
|
||||||
|
|
||||||
*filename* should be absolute or relative to the source directory.
|
*filename* should be absolute or relative to the source directory.
|
||||||
"""
|
"""
|
||||||
return self.project.path2doc(filename)
|
return self.project.path2doc(filename)
|
||||||
|
|
||||||
def doc2path(self, docname, base=True, suffix=None):
|
def doc2path(self, docname: str, base: Union[bool, str] = True, suffix: str = None) -> str:
|
||||||
# type: (str, Union[bool, str], str) -> str
|
|
||||||
"""Return the filename for the document name.
|
"""Return the filename for the document name.
|
||||||
|
|
||||||
If *base* is True, return absolute path under self.srcdir.
|
If *base* is True, return absolute path under self.srcdir.
|
||||||
@ -341,8 +334,7 @@ class BuildEnvironment:
|
|||||||
pathname = path.join(base, pathname) # type: ignore
|
pathname = path.join(base, pathname) # type: ignore
|
||||||
return pathname
|
return pathname
|
||||||
|
|
||||||
def relfn2path(self, filename, docname=None):
|
def relfn2path(self, filename: str, docname: str = None) -> Tuple[str, str]:
|
||||||
# type: (str, str) -> Tuple[str, str]
|
|
||||||
"""Return paths to a file referenced from a document, relative to
|
"""Return paths to a file referenced from a document, relative to
|
||||||
documentation root and absolute.
|
documentation root and absolute.
|
||||||
|
|
||||||
@ -361,13 +353,11 @@ class BuildEnvironment:
|
|||||||
return rel_fn, path.abspath(path.join(self.srcdir, rel_fn))
|
return rel_fn, path.abspath(path.join(self.srcdir, rel_fn))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def found_docs(self):
|
def found_docs(self) -> Set[str]:
|
||||||
# type: () -> Set[str]
|
|
||||||
"""contains all existing docnames."""
|
"""contains all existing docnames."""
|
||||||
return self.project.docnames
|
return self.project.docnames
|
||||||
|
|
||||||
def find_files(self, config, builder):
|
def find_files(self, config: Config, builder: "Builder") -> None:
|
||||||
# type: (Config, Builder) -> None
|
|
||||||
"""Find all source files in the source dir and put them in
|
"""Find all source files in the source dir and put them in
|
||||||
self.found_docs.
|
self.found_docs.
|
||||||
"""
|
"""
|
||||||
@ -395,8 +385,7 @@ class BuildEnvironment:
|
|||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
raise DocumentError(__('Failed to scan documents in %s: %r') % (self.srcdir, exc))
|
raise DocumentError(__('Failed to scan documents in %s: %r') % (self.srcdir, exc))
|
||||||
|
|
||||||
def get_outdated_files(self, config_changed):
|
def get_outdated_files(self, config_changed: bool) -> Tuple[Set[str], Set[str], Set[str]]:
|
||||||
# type: (bool) -> Tuple[Set[str], Set[str], Set[str]]
|
|
||||||
"""Return (added, changed, removed) sets."""
|
"""Return (added, changed, removed) sets."""
|
||||||
# clear all files no longer present
|
# clear all files no longer present
|
||||||
removed = set(self.all_docs) - self.found_docs
|
removed = set(self.all_docs) - self.found_docs
|
||||||
@ -446,8 +435,7 @@ class BuildEnvironment:
|
|||||||
|
|
||||||
return added, changed, removed
|
return added, changed, removed
|
||||||
|
|
||||||
def check_dependents(self, app, already):
|
def check_dependents(self, app: "Sphinx", already: Set[str]) -> Generator[str, None, None]:
|
||||||
# type: (Sphinx, Set[str]) -> Iterator[str]
|
|
||||||
to_rewrite = [] # type: List[str]
|
to_rewrite = [] # type: List[str]
|
||||||
for docnames in self.events.emit('env-get-updated', self):
|
for docnames in self.events.emit('env-get-updated', self):
|
||||||
to_rewrite.extend(docnames)
|
to_rewrite.extend(docnames)
|
||||||
@ -457,8 +445,7 @@ class BuildEnvironment:
|
|||||||
|
|
||||||
# --------- SINGLE FILE READING --------------------------------------------
|
# --------- SINGLE FILE READING --------------------------------------------
|
||||||
|
|
||||||
def prepare_settings(self, docname):
|
def prepare_settings(self, docname: str) -> None:
|
||||||
# type: (str) -> None
|
|
||||||
"""Prepare to set up environment for reading."""
|
"""Prepare to set up environment for reading."""
|
||||||
self.temp_data['docname'] = docname
|
self.temp_data['docname'] = docname
|
||||||
# defaults to the global default, but can be re-set in a document
|
# defaults to the global default, but can be re-set in a document
|
||||||
@ -469,13 +456,11 @@ class BuildEnvironment:
|
|||||||
# utilities to use while reading a document
|
# utilities to use while reading a document
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def docname(self):
|
def docname(self) -> str:
|
||||||
# type: () -> str
|
|
||||||
"""Returns the docname of the document currently being parsed."""
|
"""Returns the docname of the document currently being parsed."""
|
||||||
return self.temp_data['docname']
|
return self.temp_data['docname']
|
||||||
|
|
||||||
def new_serialno(self, category=''):
|
def new_serialno(self, category: str = '') -> int:
|
||||||
# type: (str) -> int
|
|
||||||
"""Return a serial number, e.g. for index entry targets.
|
"""Return a serial number, e.g. for index entry targets.
|
||||||
|
|
||||||
The number is guaranteed to be unique in the current document.
|
The number is guaranteed to be unique in the current document.
|
||||||
@ -485,8 +470,7 @@ class BuildEnvironment:
|
|||||||
self.temp_data[key] = cur + 1
|
self.temp_data[key] = cur + 1
|
||||||
return cur
|
return cur
|
||||||
|
|
||||||
def note_dependency(self, filename):
|
def note_dependency(self, filename: str) -> None:
|
||||||
# type: (str) -> None
|
|
||||||
"""Add *filename* as a dependency of the current document.
|
"""Add *filename* as a dependency of the current document.
|
||||||
|
|
||||||
This means that the document will be rebuilt if this file changes.
|
This means that the document will be rebuilt if this file changes.
|
||||||
@ -495,8 +479,7 @@ class BuildEnvironment:
|
|||||||
"""
|
"""
|
||||||
self.dependencies[self.docname].add(filename)
|
self.dependencies[self.docname].add(filename)
|
||||||
|
|
||||||
def note_included(self, filename):
|
def note_included(self, filename: str) -> None:
|
||||||
# type: (str) -> None
|
|
||||||
"""Add *filename* as a included from other document.
|
"""Add *filename* as a included from other document.
|
||||||
|
|
||||||
This means the document is not orphaned.
|
This means the document is not orphaned.
|
||||||
@ -505,15 +488,13 @@ class BuildEnvironment:
|
|||||||
"""
|
"""
|
||||||
self.included[self.docname].add(self.path2doc(filename))
|
self.included[self.docname].add(self.path2doc(filename))
|
||||||
|
|
||||||
def note_reread(self):
|
def note_reread(self) -> None:
|
||||||
# type: () -> None
|
|
||||||
"""Add the current document to the list of documents that will
|
"""Add the current document to the list of documents that will
|
||||||
automatically be re-read at the next build.
|
automatically be re-read at the next build.
|
||||||
"""
|
"""
|
||||||
self.reread_always.add(self.docname)
|
self.reread_always.add(self.docname)
|
||||||
|
|
||||||
def get_domain(self, domainname):
|
def get_domain(self, domainname: str) -> Domain:
|
||||||
# type: (str) -> Domain
|
|
||||||
"""Return the domain instance with the specified name.
|
"""Return the domain instance with the specified name.
|
||||||
|
|
||||||
Raises an ExtensionError if the domain is not registered.
|
Raises an ExtensionError if the domain is not registered.
|
||||||
@ -525,8 +506,7 @@ class BuildEnvironment:
|
|||||||
|
|
||||||
# --------- RESOLVING REFERENCES AND TOCTREES ------------------------------
|
# --------- RESOLVING REFERENCES AND TOCTREES ------------------------------
|
||||||
|
|
||||||
def get_doctree(self, docname):
|
def get_doctree(self, docname: str) -> nodes.document:
|
||||||
# type: (str) -> nodes.document
|
|
||||||
"""Read the doctree for a file from the pickle and return it."""
|
"""Read the doctree for a file from the pickle and return it."""
|
||||||
filename = path.join(self.doctreedir, docname + '.doctree')
|
filename = path.join(self.doctreedir, docname + '.doctree')
|
||||||
with open(filename, 'rb') as f:
|
with open(filename, 'rb') as f:
|
||||||
@ -535,9 +515,9 @@ class BuildEnvironment:
|
|||||||
doctree.reporter = LoggingReporter(self.doc2path(docname))
|
doctree.reporter = LoggingReporter(self.doc2path(docname))
|
||||||
return doctree
|
return doctree
|
||||||
|
|
||||||
def get_and_resolve_doctree(self, docname, builder, doctree=None,
|
def get_and_resolve_doctree(self, docname: str, builder: "Builder",
|
||||||
prune_toctrees=True, includehidden=False):
|
doctree: nodes.document = None, prune_toctrees: bool = True,
|
||||||
# type: (str, Builder, nodes.document, bool, bool) -> nodes.document
|
includehidden: bool = False) -> nodes.document:
|
||||||
"""Read the doctree from the pickle, resolve cross-references and
|
"""Read the doctree from the pickle, resolve cross-references and
|
||||||
toctrees and return it.
|
toctrees and return it.
|
||||||
"""
|
"""
|
||||||
@ -559,9 +539,9 @@ class BuildEnvironment:
|
|||||||
|
|
||||||
return doctree
|
return doctree
|
||||||
|
|
||||||
def resolve_toctree(self, docname, builder, toctree, prune=True, maxdepth=0,
|
def resolve_toctree(self, docname: str, builder: "Builder", toctree: addnodes.toctree,
|
||||||
titles_only=False, collapse=False, includehidden=False):
|
prune: bool = True, maxdepth: int = 0, titles_only: bool = False,
|
||||||
# type: (str, Builder, addnodes.toctree, bool, int, bool, bool, bool) -> nodes.Node
|
collapse: bool = False, includehidden: bool = False) -> Node:
|
||||||
"""Resolve a *toctree* node into individual bullet lists with titles
|
"""Resolve a *toctree* node into individual bullet lists with titles
|
||||||
as items, returning None (if no containing titles are found) or
|
as items, returning None (if no containing titles are found) or
|
||||||
a new node.
|
a new node.
|
||||||
@ -577,12 +557,11 @@ class BuildEnvironment:
|
|||||||
maxdepth, titles_only, collapse,
|
maxdepth, titles_only, collapse,
|
||||||
includehidden)
|
includehidden)
|
||||||
|
|
||||||
def resolve_references(self, doctree, fromdocname, builder):
|
def resolve_references(self, doctree: nodes.document, fromdocname: str,
|
||||||
# type: (nodes.document, str, Builder) -> None
|
builder: "Builder") -> None:
|
||||||
self.apply_post_transforms(doctree, fromdocname)
|
self.apply_post_transforms(doctree, fromdocname)
|
||||||
|
|
||||||
def apply_post_transforms(self, doctree, docname):
|
def apply_post_transforms(self, doctree: nodes.document, docname: str) -> None:
|
||||||
# type: (nodes.document, str) -> None
|
|
||||||
"""Apply all post-transforms."""
|
"""Apply all post-transforms."""
|
||||||
try:
|
try:
|
||||||
# set env.docname during applying post-transforms
|
# set env.docname during applying post-transforms
|
||||||
@ -599,12 +578,10 @@ class BuildEnvironment:
|
|||||||
# allow custom references to be resolved
|
# allow custom references to be resolved
|
||||||
self.events.emit('doctree-resolved', doctree, docname)
|
self.events.emit('doctree-resolved', doctree, docname)
|
||||||
|
|
||||||
def collect_relations(self):
|
def collect_relations(self) -> Dict[str, List[str]]:
|
||||||
# type: () -> Dict[str, List[str]]
|
|
||||||
traversed = set()
|
traversed = set()
|
||||||
|
|
||||||
def traverse_toctree(parent, docname):
|
def traverse_toctree(parent: str, docname: str) -> Iterator[Tuple[str, str]]:
|
||||||
# type: (str, str) -> Iterator[Tuple[str, str]]
|
|
||||||
if parent == docname:
|
if parent == docname:
|
||||||
logger.warning(__('self referenced toctree found. Ignored.'), location=docname)
|
logger.warning(__('self referenced toctree found. Ignored.'), location=docname)
|
||||||
return
|
return
|
||||||
@ -633,8 +610,7 @@ class BuildEnvironment:
|
|||||||
|
|
||||||
return relations
|
return relations
|
||||||
|
|
||||||
def check_consistency(self):
|
def check_consistency(self) -> None:
|
||||||
# type: () -> None
|
|
||||||
"""Do consistency checks."""
|
"""Do consistency checks."""
|
||||||
included = set().union(*self.included.values()) # type: ignore
|
included = set().union(*self.included.values()) # type: ignore
|
||||||
for docname in sorted(self.all_docs):
|
for docname in sorted(self.all_docs):
|
||||||
|
@ -8,18 +8,14 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if False:
|
from sphinx.environment import BuildEnvironment
|
||||||
# For type annotation
|
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
|
||||||
|
|
||||||
|
|
||||||
class ImageAdapter:
|
class ImageAdapter:
|
||||||
def __init__(self, env):
|
def __init__(self, env: BuildEnvironment) -> None:
|
||||||
# type: (BuildEnvironment) -> None
|
|
||||||
self.env = env
|
self.env = env
|
||||||
|
|
||||||
def get_original_image_uri(self, name):
|
def get_original_image_uri(self, name: str) -> str:
|
||||||
# type: (str) -> str
|
|
||||||
"""Get the original image URI."""
|
"""Get the original image URI."""
|
||||||
while name in self.env.original_image_uri:
|
while name in self.env.original_image_uri:
|
||||||
name = self.env.original_image_uri[name]
|
name = self.env.original_image_uri[name]
|
||||||
|
@ -11,33 +11,30 @@ import bisect
|
|||||||
import re
|
import re
|
||||||
import unicodedata
|
import unicodedata
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
|
from typing import Any, Dict, Pattern, List, Tuple
|
||||||
|
|
||||||
|
from sphinx.builders import Builder
|
||||||
|
from sphinx.environment import BuildEnvironment
|
||||||
from sphinx.errors import NoUri
|
from sphinx.errors import NoUri
|
||||||
from sphinx.locale import _, __
|
from sphinx.locale import _, __
|
||||||
from sphinx.util import split_into, logging
|
from sphinx.util import split_into, logging
|
||||||
|
|
||||||
if False:
|
|
||||||
# For type annotation
|
|
||||||
from typing import Any, Dict, Pattern, List, Tuple # NOQA
|
|
||||||
from sphinx.builders import Builder # NOQA
|
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class IndexEntries:
|
class IndexEntries:
|
||||||
def __init__(self, env):
|
def __init__(self, env: BuildEnvironment) -> None:
|
||||||
# type: (BuildEnvironment) -> None
|
|
||||||
self.env = env
|
self.env = env
|
||||||
|
|
||||||
def create_index(self, builder, group_entries=True,
|
def create_index(self, builder: Builder, group_entries: bool = True,
|
||||||
_fixre=re.compile(r'(.*) ([(][^()]*[)])')):
|
_fixre: Pattern = re.compile(r'(.*) ([(][^()]*[)])')
|
||||||
# type: (Builder, bool, Pattern) -> List[Tuple[str, List[Tuple[str, Any]]]]
|
) -> List[Tuple[str, List[Tuple[str, Any]]]]:
|
||||||
"""Create the real index from the collected index entries."""
|
"""Create the real index from the collected index entries."""
|
||||||
new = {} # type: Dict[str, List]
|
new = {} # type: Dict[str, List]
|
||||||
|
|
||||||
def add_entry(word, subword, main, link=True, dic=new, key=None):
|
def add_entry(word: str, subword: str, main: str, link: bool = True,
|
||||||
# type: (str, str, str, bool, Dict, str) -> None
|
dic: Dict = new, key: str = None) -> None:
|
||||||
# Force the word to be unicode if it's a ASCII bytestring.
|
# Force the word to be unicode if it's a ASCII bytestring.
|
||||||
# This will solve problems with unicode normalization later.
|
# This will solve problems with unicode normalization later.
|
||||||
# For instance the RFC role will add bytestrings at the moment
|
# For instance the RFC role will add bytestrings at the moment
|
||||||
@ -91,8 +88,7 @@ class IndexEntries:
|
|||||||
|
|
||||||
# sort the index entries; put all symbols at the front, even those
|
# sort the index entries; put all symbols at the front, even those
|
||||||
# following the letters in ASCII, this is where the chr(127) comes from
|
# following the letters in ASCII, this is where the chr(127) comes from
|
||||||
def keyfunc(entry):
|
def keyfunc(entry: Tuple[str, List]) -> Tuple[str, str]:
|
||||||
# type: (Tuple[str, List]) -> Tuple[str, str]
|
|
||||||
key, (void, void, category_key) = entry
|
key, (void, void, category_key) = entry
|
||||||
if category_key:
|
if category_key:
|
||||||
# using specified category key to sort
|
# using specified category key to sort
|
||||||
@ -138,8 +134,7 @@ class IndexEntries:
|
|||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
# group the entries by letter
|
# group the entries by letter
|
||||||
def keyfunc2(item):
|
def keyfunc2(item: Tuple[str, List]) -> str:
|
||||||
# type: (Tuple[str, List]) -> str
|
|
||||||
# hack: mutating the subitems dicts to a list in the keyfunc
|
# hack: mutating the subitems dicts to a list in the keyfunc
|
||||||
k, v = item
|
k, v = item
|
||||||
v[1] = sorted((si, se) for (si, (se, void, void)) in v[1].items())
|
v[1] = sorted((si, se) for (si, (se, void, void)) in v[1].items())
|
||||||
|
@ -8,9 +8,11 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Iterable, cast
|
from typing import cast
|
||||||
|
from typing import Iterable, List
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
|
from docutils.nodes import Element, Node
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
@ -20,20 +22,18 @@ from sphinx.util.nodes import clean_astext, process_only_nodes
|
|||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Dict, List # NOQA
|
from sphinx.builders import Builder
|
||||||
from sphinx.builders import Builder # NOQA
|
from sphinx.environment import BuildEnvironment
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class TocTree:
|
class TocTree:
|
||||||
def __init__(self, env):
|
def __init__(self, env: "BuildEnvironment") -> None:
|
||||||
# type: (BuildEnvironment) -> None
|
|
||||||
self.env = env
|
self.env = env
|
||||||
|
|
||||||
def note(self, docname, toctreenode):
|
def note(self, docname: str, toctreenode: addnodes.toctree) -> None:
|
||||||
# type: (str, addnodes.toctree) -> None
|
|
||||||
"""Note a TOC tree directive in a document and gather information about
|
"""Note a TOC tree directive in a document and gather information about
|
||||||
file relations from it.
|
file relations from it.
|
||||||
"""
|
"""
|
||||||
@ -48,9 +48,9 @@ class TocTree:
|
|||||||
self.env.files_to_rebuild.setdefault(includefile, set()).add(docname)
|
self.env.files_to_rebuild.setdefault(includefile, set()).add(docname)
|
||||||
self.env.toctree_includes.setdefault(docname, []).extend(includefiles)
|
self.env.toctree_includes.setdefault(docname, []).extend(includefiles)
|
||||||
|
|
||||||
def resolve(self, docname, builder, toctree, prune=True, maxdepth=0,
|
def resolve(self, docname: str, builder: "Builder", toctree: addnodes.toctree,
|
||||||
titles_only=False, collapse=False, includehidden=False):
|
prune: bool = True, maxdepth: int = 0, titles_only: bool = False,
|
||||||
# type: (str, Builder, addnodes.toctree, bool, int, bool, bool, bool) -> nodes.Element
|
collapse: bool = False, includehidden: bool = False) -> Element:
|
||||||
"""Resolve a *toctree* node into individual bullet lists with titles
|
"""Resolve a *toctree* node into individual bullet lists with titles
|
||||||
as items, returning None (if no containing titles are found) or
|
as items, returning None (if no containing titles are found) or
|
||||||
a new node.
|
a new node.
|
||||||
@ -86,8 +86,7 @@ class TocTree:
|
|||||||
toctree_ancestors = self.get_toctree_ancestors(docname)
|
toctree_ancestors = self.get_toctree_ancestors(docname)
|
||||||
excluded = Matcher(self.env.config.exclude_patterns)
|
excluded = Matcher(self.env.config.exclude_patterns)
|
||||||
|
|
||||||
def _toctree_add_classes(node, depth):
|
def _toctree_add_classes(node: Element, depth: int) -> None:
|
||||||
# type: (nodes.Element, int) -> None
|
|
||||||
"""Add 'toctree-l%d' and 'current' classes to the toctree."""
|
"""Add 'toctree-l%d' and 'current' classes to the toctree."""
|
||||||
for subnode in node.children:
|
for subnode in node.children:
|
||||||
if isinstance(subnode, (addnodes.compact_paragraph,
|
if isinstance(subnode, (addnodes.compact_paragraph,
|
||||||
@ -105,7 +104,7 @@ class TocTree:
|
|||||||
if not subnode['anchorname']:
|
if not subnode['anchorname']:
|
||||||
# give the whole branch a 'current' class
|
# give the whole branch a 'current' class
|
||||||
# (useful for styling it differently)
|
# (useful for styling it differently)
|
||||||
branchnode = subnode # type: nodes.Element
|
branchnode = subnode # type: Element
|
||||||
while branchnode:
|
while branchnode:
|
||||||
branchnode['classes'].append('current')
|
branchnode['classes'].append('current')
|
||||||
branchnode = branchnode.parent
|
branchnode = branchnode.parent
|
||||||
@ -117,11 +116,12 @@ class TocTree:
|
|||||||
subnode['iscurrent'] = True
|
subnode['iscurrent'] = True
|
||||||
subnode = subnode.parent
|
subnode = subnode.parent
|
||||||
|
|
||||||
def _entries_from_toctree(toctreenode, parents, separate=False, subtree=False):
|
def _entries_from_toctree(toctreenode: addnodes.toctree, parents: List[str],
|
||||||
# type: (addnodes.toctree, List[str], bool, bool) -> List[nodes.Element]
|
separate: bool = False, subtree: bool = False
|
||||||
|
) -> List[Element]:
|
||||||
"""Return TOC entries for a toctree node."""
|
"""Return TOC entries for a toctree node."""
|
||||||
refs = [(e[0], e[1]) for e in toctreenode['entries']]
|
refs = [(e[0], e[1]) for e in toctreenode['entries']]
|
||||||
entries = [] # type: List[nodes.Element]
|
entries = [] # type: List[Element]
|
||||||
for (title, ref) in refs:
|
for (title, ref) in refs:
|
||||||
try:
|
try:
|
||||||
refdoc = None
|
refdoc = None
|
||||||
@ -265,8 +265,7 @@ class TocTree:
|
|||||||
docname, refnode['refuri']) + refnode['anchorname']
|
docname, refnode['refuri']) + refnode['anchorname']
|
||||||
return newnode
|
return newnode
|
||||||
|
|
||||||
def get_toctree_ancestors(self, docname):
|
def get_toctree_ancestors(self, docname: str) -> List[str]:
|
||||||
# type: (str) -> List[str]
|
|
||||||
parent = {}
|
parent = {}
|
||||||
for p, children in self.env.toctree_includes.items():
|
for p, children in self.env.toctree_includes.items():
|
||||||
for child in children:
|
for child in children:
|
||||||
@ -278,8 +277,8 @@ class TocTree:
|
|||||||
d = parent[d]
|
d = parent[d]
|
||||||
return ancestors
|
return ancestors
|
||||||
|
|
||||||
def _toctree_prune(self, node, depth, maxdepth, collapse=False):
|
def _toctree_prune(self, node: Element, depth: int, maxdepth: int, collapse: bool = False
|
||||||
# type: (nodes.Element, int, int, bool) -> None
|
) -> None:
|
||||||
"""Utility: Cut a TOC at a specified depth."""
|
"""Utility: Cut a TOC at a specified depth."""
|
||||||
for subnode in node.children[:]:
|
for subnode in node.children[:]:
|
||||||
if isinstance(subnode, (addnodes.compact_paragraph,
|
if isinstance(subnode, (addnodes.compact_paragraph,
|
||||||
@ -300,8 +299,7 @@ class TocTree:
|
|||||||
# recurse on visible children
|
# recurse on visible children
|
||||||
self._toctree_prune(subnode, depth + 1, maxdepth, collapse)
|
self._toctree_prune(subnode, depth + 1, maxdepth, collapse)
|
||||||
|
|
||||||
def get_toc_for(self, docname, builder):
|
def get_toc_for(self, docname: str, builder: "Builder") -> Node:
|
||||||
# type: (str, Builder) -> nodes.Node
|
|
||||||
"""Return a TOC nodetree -- for use on the same page only!"""
|
"""Return a TOC nodetree -- for use on the same page only!"""
|
||||||
tocdepth = self.env.metadata[docname].get('tocdepth', 0)
|
tocdepth = self.env.metadata[docname].get('tocdepth', 0)
|
||||||
try:
|
try:
|
||||||
@ -316,11 +314,11 @@ class TocTree:
|
|||||||
node['refuri'] = node['anchorname'] or '#'
|
node['refuri'] = node['anchorname'] or '#'
|
||||||
return toc
|
return toc
|
||||||
|
|
||||||
def get_toctree_for(self, docname, builder, collapse, **kwds):
|
def get_toctree_for(self, docname: str, builder: "Builder", collapse: bool, **kwds
|
||||||
# type: (str, Builder, bool, Any) -> nodes.Element
|
) -> Element:
|
||||||
"""Return the global TOC nodetree."""
|
"""Return the global TOC nodetree."""
|
||||||
doctree = self.env.get_doctree(self.env.config.master_doc)
|
doctree = self.env.get_doctree(self.env.config.master_doc)
|
||||||
toctrees = [] # type: List[nodes.Element]
|
toctrees = [] # type: List[Element]
|
||||||
if 'includehidden' not in kwds:
|
if 'includehidden' not in kwds:
|
||||||
kwds['includehidden'] = True
|
kwds['includehidden'] = True
|
||||||
if 'maxdepth' not in kwds:
|
if 'maxdepth' not in kwds:
|
||||||
|
@ -8,12 +8,12 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if False:
|
from typing import Dict, List, Set
|
||||||
# For type annotation
|
|
||||||
from typing import Dict, List, Set # NOQA
|
from docutils import nodes
|
||||||
from docutils import nodes # NOQA
|
|
||||||
from sphinx.sphinx import Sphinx # NOQA
|
from sphinx.application import Sphinx
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
from sphinx.environment import BuildEnvironment
|
||||||
|
|
||||||
|
|
||||||
class EnvironmentCollector:
|
class EnvironmentCollector:
|
||||||
@ -27,8 +27,7 @@ class EnvironmentCollector:
|
|||||||
|
|
||||||
listener_ids = None # type: Dict[str, int]
|
listener_ids = None # type: Dict[str, int]
|
||||||
|
|
||||||
def enable(self, app):
|
def enable(self, app: Sphinx) -> None:
|
||||||
# type: (Sphinx) -> None
|
|
||||||
assert self.listener_ids is None
|
assert self.listener_ids is None
|
||||||
self.listener_ids = {
|
self.listener_ids = {
|
||||||
'doctree-read': app.connect('doctree-read', self.process_doc),
|
'doctree-read': app.connect('doctree-read', self.process_doc),
|
||||||
@ -38,43 +37,39 @@ class EnvironmentCollector:
|
|||||||
'env-get-outdated': app.connect('env-get-outdated', self.get_outdated_docs),
|
'env-get-outdated': app.connect('env-get-outdated', self.get_outdated_docs),
|
||||||
}
|
}
|
||||||
|
|
||||||
def disable(self, app):
|
def disable(self, app: Sphinx) -> None:
|
||||||
# type: (Sphinx) -> None
|
|
||||||
assert self.listener_ids is not None
|
assert self.listener_ids is not None
|
||||||
for listener_id in self.listener_ids.values():
|
for listener_id in self.listener_ids.values():
|
||||||
app.disconnect(listener_id)
|
app.disconnect(listener_id)
|
||||||
self.listener_ids = None
|
self.listener_ids = None
|
||||||
|
|
||||||
def clear_doc(self, app, env, docname):
|
def clear_doc(self, app: Sphinx, env: BuildEnvironment, docname: str) -> None:
|
||||||
# type: (Sphinx, BuildEnvironment, str) -> None
|
|
||||||
"""Remove specified data of a document.
|
"""Remove specified data of a document.
|
||||||
|
|
||||||
This method is called on the removal of the document."""
|
This method is called on the removal of the document."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def merge_other(self, app, env, docnames, other):
|
def merge_other(self, app: Sphinx, env: BuildEnvironment,
|
||||||
# type: (Sphinx, BuildEnvironment, Set[str], BuildEnvironment) -> None
|
docnames: Set[str], other: BuildEnvironment) -> None:
|
||||||
"""Merge in specified data regarding docnames from a different `BuildEnvironment`
|
"""Merge in specified data regarding docnames from a different `BuildEnvironment`
|
||||||
object which coming from a subprocess in parallel builds."""
|
object which coming from a subprocess in parallel builds."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def process_doc(self, app, doctree):
|
def process_doc(self, app: Sphinx, doctree: nodes.document) -> None:
|
||||||
# type: (Sphinx, nodes.document) -> None
|
|
||||||
"""Process a document and gather specific data from it.
|
"""Process a document and gather specific data from it.
|
||||||
|
|
||||||
This method is called after the document is read."""
|
This method is called after the document is read."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_updated_docs(self, app, env):
|
def get_updated_docs(self, app: Sphinx, env: BuildEnvironment) -> List[str]:
|
||||||
# type: (Sphinx, BuildEnvironment) -> List[str]
|
|
||||||
"""Return a list of docnames to re-read.
|
"""Return a list of docnames to re-read.
|
||||||
|
|
||||||
This methods is called after reading the whole of documents (experimental).
|
This methods is called after reading the whole of documents (experimental).
|
||||||
"""
|
"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def get_outdated_docs(self, app, env, added, changed, removed):
|
def get_outdated_docs(self, app: Sphinx, env: BuildEnvironment,
|
||||||
# type: (Sphinx, BuildEnvironment, str, Set[str], Set[str], Set[str]) -> List[str]
|
added: Set[str], changed: Set[str], removed: Set[str]) -> List[str]:
|
||||||
"""Return a list of docnames to re-read.
|
"""Return a list of docnames to re-read.
|
||||||
|
|
||||||
This methods is called before reading the documents.
|
This methods is called before reading the documents.
|
||||||
|
@ -11,22 +11,21 @@
|
|||||||
import os
|
import os
|
||||||
from glob import glob
|
from glob import glob
|
||||||
from os import path
|
from os import path
|
||||||
|
from typing import Any, Dict, List, Set
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
|
from docutils.nodes import Node
|
||||||
from docutils.utils import relative_path
|
from docutils.utils import relative_path
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
|
from sphinx.application import Sphinx
|
||||||
|
from sphinx.environment import BuildEnvironment
|
||||||
from sphinx.environment.collectors import EnvironmentCollector
|
from sphinx.environment.collectors import EnvironmentCollector
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.i18n import get_image_filename_for_language, search_image_for_language
|
from sphinx.util.i18n import get_image_filename_for_language, search_image_for_language
|
||||||
from sphinx.util.images import guess_mimetype
|
from sphinx.util.images import guess_mimetype
|
||||||
|
|
||||||
if False:
|
|
||||||
# For type annotation
|
|
||||||
from typing import Dict, List, Set # NOQA
|
|
||||||
from sphinx.sphinx import Sphinx # NOQA
|
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -34,16 +33,14 @@ logger = logging.getLogger(__name__)
|
|||||||
class ImageCollector(EnvironmentCollector):
|
class ImageCollector(EnvironmentCollector):
|
||||||
"""Image files collector for sphinx.environment."""
|
"""Image files collector for sphinx.environment."""
|
||||||
|
|
||||||
def clear_doc(self, app, env, docname):
|
def clear_doc(self, app: Sphinx, env: BuildEnvironment, docname: str) -> None:
|
||||||
# type: (Sphinx, BuildEnvironment, str) -> None
|
|
||||||
env.images.purge_doc(docname)
|
env.images.purge_doc(docname)
|
||||||
|
|
||||||
def merge_other(self, app, env, docnames, other):
|
def merge_other(self, app: Sphinx, env: BuildEnvironment,
|
||||||
# type: (Sphinx, BuildEnvironment, Set[str], BuildEnvironment) -> None
|
docnames: Set[str], other: BuildEnvironment) -> None:
|
||||||
env.images.merge_other(docnames, other.images)
|
env.images.merge_other(docnames, other.images)
|
||||||
|
|
||||||
def process_doc(self, app, doctree):
|
def process_doc(self, app: Sphinx, doctree: nodes.document) -> None:
|
||||||
# type: (Sphinx, nodes.document) -> None
|
|
||||||
"""Process and rewrite image URIs."""
|
"""Process and rewrite image URIs."""
|
||||||
docname = app.env.docname
|
docname = app.env.docname
|
||||||
|
|
||||||
@ -92,8 +89,8 @@ class ImageCollector(EnvironmentCollector):
|
|||||||
continue
|
continue
|
||||||
app.env.images.add_file(docname, imgpath)
|
app.env.images.add_file(docname, imgpath)
|
||||||
|
|
||||||
def collect_candidates(self, env, imgpath, candidates, node):
|
def collect_candidates(self, env: BuildEnvironment, imgpath: str,
|
||||||
# type: (BuildEnvironment, str, Dict[str, str], nodes.Node) -> None
|
candidates: Dict[str, str], node: Node) -> None:
|
||||||
globbed = {} # type: Dict[str, List[str]]
|
globbed = {} # type: Dict[str, List[str]]
|
||||||
for filename in glob(imgpath):
|
for filename in glob(imgpath):
|
||||||
new_imgpath = relative_path(path.join(env.srcdir, 'dummy'),
|
new_imgpath = relative_path(path.join(env.srcdir, 'dummy'),
|
||||||
@ -115,16 +112,14 @@ class ImageCollector(EnvironmentCollector):
|
|||||||
class DownloadFileCollector(EnvironmentCollector):
|
class DownloadFileCollector(EnvironmentCollector):
|
||||||
"""Download files collector for sphinx.environment."""
|
"""Download files collector for sphinx.environment."""
|
||||||
|
|
||||||
def clear_doc(self, app, env, docname):
|
def clear_doc(self, app: Sphinx, env: BuildEnvironment, docname: str) -> None:
|
||||||
# type: (Sphinx, BuildEnvironment, str) -> None
|
|
||||||
env.dlfiles.purge_doc(docname)
|
env.dlfiles.purge_doc(docname)
|
||||||
|
|
||||||
def merge_other(self, app, env, docnames, other):
|
def merge_other(self, app: Sphinx, env: BuildEnvironment,
|
||||||
# type: (Sphinx, BuildEnvironment, Set[str], BuildEnvironment) -> None
|
docnames: Set[str], other: BuildEnvironment) -> None:
|
||||||
env.dlfiles.merge_other(docnames, other.dlfiles)
|
env.dlfiles.merge_other(docnames, other.dlfiles)
|
||||||
|
|
||||||
def process_doc(self, app, doctree):
|
def process_doc(self, app: Sphinx, doctree: nodes.document) -> None:
|
||||||
# type: (Sphinx, nodes.document) -> None
|
|
||||||
"""Process downloadable file paths. """
|
"""Process downloadable file paths. """
|
||||||
for node in doctree.traverse(addnodes.download_reference):
|
for node in doctree.traverse(addnodes.download_reference):
|
||||||
targetname = node['reftarget']
|
targetname = node['reftarget']
|
||||||
@ -140,8 +135,7 @@ class DownloadFileCollector(EnvironmentCollector):
|
|||||||
node['filename'] = app.env.dlfiles.add_file(app.env.docname, rel_filename)
|
node['filename'] = app.env.dlfiles.add_file(app.env.docname, rel_filename)
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||||
# type: (Sphinx) -> Dict
|
|
||||||
app.add_env_collector(ImageCollector)
|
app.add_env_collector(ImageCollector)
|
||||||
app.add_env_collector(DownloadFileCollector)
|
app.add_env_collector(DownloadFileCollector)
|
||||||
|
|
||||||
|
@ -10,35 +10,30 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
from os import path
|
from os import path
|
||||||
|
from typing import Any, Dict, Set
|
||||||
|
|
||||||
|
from docutils import nodes
|
||||||
from docutils.utils import relative_path
|
from docutils.utils import relative_path
|
||||||
|
|
||||||
|
from sphinx.application import Sphinx
|
||||||
|
from sphinx.environment import BuildEnvironment
|
||||||
from sphinx.environment.collectors import EnvironmentCollector
|
from sphinx.environment.collectors import EnvironmentCollector
|
||||||
from sphinx.util.osutil import fs_encoding
|
from sphinx.util.osutil import fs_encoding
|
||||||
|
|
||||||
if False:
|
|
||||||
# For type annotation
|
|
||||||
from typing import Dict, Set # NOQA
|
|
||||||
from docutils import nodes # NOQA
|
|
||||||
from sphinx.sphinx import Sphinx # NOQA
|
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
|
||||||
|
|
||||||
|
|
||||||
class DependenciesCollector(EnvironmentCollector):
|
class DependenciesCollector(EnvironmentCollector):
|
||||||
"""dependencies collector for sphinx.environment."""
|
"""dependencies collector for sphinx.environment."""
|
||||||
|
|
||||||
def clear_doc(self, app, env, docname):
|
def clear_doc(self, app: Sphinx, env: BuildEnvironment, docname: str) -> None:
|
||||||
# type: (Sphinx, BuildEnvironment, str) -> None
|
|
||||||
env.dependencies.pop(docname, None)
|
env.dependencies.pop(docname, None)
|
||||||
|
|
||||||
def merge_other(self, app, env, docnames, other):
|
def merge_other(self, app: Sphinx, env: BuildEnvironment,
|
||||||
# type: (Sphinx, BuildEnvironment, Set[str], BuildEnvironment) -> None
|
docnames: Set[str], other: BuildEnvironment) -> None:
|
||||||
for docname in docnames:
|
for docname in docnames:
|
||||||
if docname in other.dependencies:
|
if docname in other.dependencies:
|
||||||
env.dependencies[docname] = other.dependencies[docname]
|
env.dependencies[docname] = other.dependencies[docname]
|
||||||
|
|
||||||
def process_doc(self, app, doctree):
|
def process_doc(self, app: Sphinx, doctree: nodes.document) -> None:
|
||||||
# type: (Sphinx, nodes.document) -> None
|
|
||||||
"""Process docutils-generated dependency info."""
|
"""Process docutils-generated dependency info."""
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
frompath = path.join(path.normpath(app.srcdir), 'dummy')
|
frompath = path.join(path.normpath(app.srcdir), 'dummy')
|
||||||
@ -55,8 +50,7 @@ class DependenciesCollector(EnvironmentCollector):
|
|||||||
app.env.dependencies[app.env.docname].add(relpath)
|
app.env.dependencies[app.env.docname].add(relpath)
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||||
# type: (Sphinx) -> Dict
|
|
||||||
app.add_env_collector(DependenciesCollector)
|
app.add_env_collector(DependenciesCollector)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -8,34 +8,31 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from typing import Any, Dict, Set
|
||||||
|
|
||||||
|
from docutils import nodes
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
|
from sphinx.application import Sphinx
|
||||||
|
from sphinx.environment import BuildEnvironment
|
||||||
from sphinx.environment.collectors import EnvironmentCollector
|
from sphinx.environment.collectors import EnvironmentCollector
|
||||||
from sphinx.util import split_index_msg, logging
|
from sphinx.util import split_index_msg, logging
|
||||||
|
|
||||||
if False:
|
|
||||||
# For type annotation
|
|
||||||
from typing import Dict, Set # NOQA
|
|
||||||
from docutils import nodes # NOQA
|
|
||||||
from sphinx.applicatin import Sphinx # NOQA
|
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class IndexEntriesCollector(EnvironmentCollector):
|
class IndexEntriesCollector(EnvironmentCollector):
|
||||||
name = 'indices'
|
name = 'indices'
|
||||||
|
|
||||||
def clear_doc(self, app, env, docname):
|
def clear_doc(self, app: Sphinx, env: BuildEnvironment, docname: str) -> None:
|
||||||
# type: (Sphinx, BuildEnvironment, str) -> None
|
|
||||||
env.indexentries.pop(docname, None)
|
env.indexentries.pop(docname, None)
|
||||||
|
|
||||||
def merge_other(self, app, env, docnames, other):
|
def merge_other(self, app: Sphinx, env: BuildEnvironment,
|
||||||
# type: (Sphinx, BuildEnvironment, Set[str], BuildEnvironment) -> None
|
docnames: Set[str], other: BuildEnvironment) -> None:
|
||||||
for docname in docnames:
|
for docname in docnames:
|
||||||
env.indexentries[docname] = other.indexentries[docname]
|
env.indexentries[docname] = other.indexentries[docname]
|
||||||
|
|
||||||
def process_doc(self, app, doctree):
|
def process_doc(self, app: Sphinx, doctree: nodes.document) -> None:
|
||||||
# type: (Sphinx, nodes.document) -> None
|
|
||||||
docname = app.env.docname
|
docname = app.env.docname
|
||||||
entries = app.env.indexentries[docname] = []
|
entries = app.env.indexentries[docname] = []
|
||||||
for node in doctree.traverse(addnodes.index):
|
for node in doctree.traverse(addnodes.index):
|
||||||
@ -50,8 +47,7 @@ class IndexEntriesCollector(EnvironmentCollector):
|
|||||||
entries.append(entry)
|
entries.append(entry)
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||||
# type: (Sphinx) -> Dict
|
|
||||||
app.add_env_collector(IndexEntriesCollector)
|
app.add_env_collector(IndexEntriesCollector)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -8,33 +8,28 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import List, cast
|
from typing import Any, Dict, List, Set
|
||||||
|
from typing import cast
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
|
|
||||||
|
from sphinx.application import Sphinx
|
||||||
|
from sphinx.environment import BuildEnvironment
|
||||||
from sphinx.environment.collectors import EnvironmentCollector
|
from sphinx.environment.collectors import EnvironmentCollector
|
||||||
|
|
||||||
if False:
|
|
||||||
# For type annotation
|
|
||||||
from typing import Dict, Set # NOQA
|
|
||||||
from sphinx.sphinx import Sphinx # NOQA
|
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
|
||||||
|
|
||||||
|
|
||||||
class MetadataCollector(EnvironmentCollector):
|
class MetadataCollector(EnvironmentCollector):
|
||||||
"""metadata collector for sphinx.environment."""
|
"""metadata collector for sphinx.environment."""
|
||||||
|
|
||||||
def clear_doc(self, app, env, docname):
|
def clear_doc(self, app: Sphinx, env: BuildEnvironment, docname: str) -> None:
|
||||||
# type: (Sphinx, BuildEnvironment, str) -> None
|
|
||||||
env.metadata.pop(docname, None)
|
env.metadata.pop(docname, None)
|
||||||
|
|
||||||
def merge_other(self, app, env, docnames, other):
|
def merge_other(self, app: Sphinx, env: BuildEnvironment,
|
||||||
# type: (Sphinx, BuildEnvironment, Set[str], BuildEnvironment) -> None
|
docnames: Set[str], other: BuildEnvironment) -> None:
|
||||||
for docname in docnames:
|
for docname in docnames:
|
||||||
env.metadata[docname] = other.metadata[docname]
|
env.metadata[docname] = other.metadata[docname]
|
||||||
|
|
||||||
def process_doc(self, app, doctree):
|
def process_doc(self, app: Sphinx, doctree: nodes.document) -> None:
|
||||||
# type: (Sphinx, nodes.document) -> None
|
|
||||||
"""Process the docinfo part of the doctree as metadata.
|
"""Process the docinfo part of the doctree as metadata.
|
||||||
|
|
||||||
Keep processing minimal -- just return what docutils says.
|
Keep processing minimal -- just return what docutils says.
|
||||||
@ -67,8 +62,7 @@ class MetadataCollector(EnvironmentCollector):
|
|||||||
doctree.pop(0)
|
doctree.pop(0)
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||||
# type: (Sphinx) -> Dict
|
|
||||||
app.add_env_collector(MetadataCollector)
|
app.add_env_collector(MetadataCollector)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -8,34 +8,30 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from typing import Any, Dict, Set
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
|
|
||||||
|
from sphinx.application import Sphinx
|
||||||
|
from sphinx.environment import BuildEnvironment
|
||||||
from sphinx.environment.collectors import EnvironmentCollector
|
from sphinx.environment.collectors import EnvironmentCollector
|
||||||
from sphinx.transforms import SphinxContentsFilter
|
from sphinx.transforms import SphinxContentsFilter
|
||||||
|
|
||||||
if False:
|
|
||||||
# For type annotation
|
|
||||||
from typing import Dict, Set # NOQA
|
|
||||||
from sphinx.sphinx import Sphinx # NOQA
|
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
|
||||||
|
|
||||||
|
|
||||||
class TitleCollector(EnvironmentCollector):
|
class TitleCollector(EnvironmentCollector):
|
||||||
"""title collector for sphinx.environment."""
|
"""title collector for sphinx.environment."""
|
||||||
|
|
||||||
def clear_doc(self, app, env, docname):
|
def clear_doc(self, app: Sphinx, env: BuildEnvironment, docname: str) -> None:
|
||||||
# type: (Sphinx, BuildEnvironment, str) -> None
|
|
||||||
env.titles.pop(docname, None)
|
env.titles.pop(docname, None)
|
||||||
env.longtitles.pop(docname, None)
|
env.longtitles.pop(docname, None)
|
||||||
|
|
||||||
def merge_other(self, app, env, docnames, other):
|
def merge_other(self, app: Sphinx, env: BuildEnvironment,
|
||||||
# type: (Sphinx, BuildEnvironment, Set[str], BuildEnvironment) -> None
|
docnames: Set[str], other: BuildEnvironment) -> None:
|
||||||
for docname in docnames:
|
for docname in docnames:
|
||||||
env.titles[docname] = other.titles[docname]
|
env.titles[docname] = other.titles[docname]
|
||||||
env.longtitles[docname] = other.longtitles[docname]
|
env.longtitles[docname] = other.longtitles[docname]
|
||||||
|
|
||||||
def process_doc(self, app, doctree):
|
def process_doc(self, app: Sphinx, doctree: nodes.document) -> None:
|
||||||
# type: (Sphinx, nodes.document) -> None
|
|
||||||
"""Add a title node to the document (just copy the first section title),
|
"""Add a title node to the document (just copy the first section title),
|
||||||
and store that title in the environment.
|
and store that title in the environment.
|
||||||
"""
|
"""
|
||||||
@ -59,8 +55,7 @@ class TitleCollector(EnvironmentCollector):
|
|||||||
app.env.longtitles[app.env.docname] = longtitlenode
|
app.env.longtitles[app.env.docname] = longtitlenode
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||||
# type: (Sphinx) -> Dict
|
|
||||||
app.add_env_collector(TitleCollector)
|
app.add_env_collector(TitleCollector)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -8,31 +8,29 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from typing import Any, Dict, List, Set, Tuple, Type, TypeVar
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
|
from docutils.nodes import Element, Node
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
|
from sphinx.application import Sphinx
|
||||||
|
from sphinx.environment import BuildEnvironment
|
||||||
from sphinx.environment.adapters.toctree import TocTree
|
from sphinx.environment.adapters.toctree import TocTree
|
||||||
from sphinx.environment.collectors import EnvironmentCollector
|
from sphinx.environment.collectors import EnvironmentCollector
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.transforms import SphinxContentsFilter
|
from sphinx.transforms import SphinxContentsFilter
|
||||||
from sphinx.util import url_re, logging
|
from sphinx.util import url_re, logging
|
||||||
|
|
||||||
if False:
|
|
||||||
# For type annotation
|
|
||||||
from typing import Dict, List, Set, Tuple, Type, TypeVar # NOQA
|
|
||||||
from sphinx.application import Sphinx # NOQA
|
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
|
||||||
|
|
||||||
N = TypeVar('N')
|
N = TypeVar('N')
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class TocTreeCollector(EnvironmentCollector):
|
class TocTreeCollector(EnvironmentCollector):
|
||||||
def clear_doc(self, app, env, docname):
|
def clear_doc(self, app: Sphinx, env: BuildEnvironment, docname: str) -> None:
|
||||||
# type: (Sphinx, BuildEnvironment, str) -> None
|
|
||||||
env.tocs.pop(docname, None)
|
env.tocs.pop(docname, None)
|
||||||
env.toc_secnumbers.pop(docname, None)
|
env.toc_secnumbers.pop(docname, None)
|
||||||
env.toc_fignumbers.pop(docname, None)
|
env.toc_fignumbers.pop(docname, None)
|
||||||
@ -46,8 +44,8 @@ class TocTreeCollector(EnvironmentCollector):
|
|||||||
if not fnset:
|
if not fnset:
|
||||||
del env.files_to_rebuild[subfn]
|
del env.files_to_rebuild[subfn]
|
||||||
|
|
||||||
def merge_other(self, app, env, docnames, other):
|
def merge_other(self, app: Sphinx, env: BuildEnvironment, docnames: Set[str],
|
||||||
# type: (Sphinx, BuildEnvironment, Set[str], BuildEnvironment) -> None
|
other: BuildEnvironment) -> None:
|
||||||
for docname in docnames:
|
for docname in docnames:
|
||||||
env.tocs[docname] = other.tocs[docname]
|
env.tocs[docname] = other.tocs[docname]
|
||||||
env.toc_num_entries[docname] = other.toc_num_entries[docname]
|
env.toc_num_entries[docname] = other.toc_num_entries[docname]
|
||||||
@ -61,14 +59,12 @@ class TocTreeCollector(EnvironmentCollector):
|
|||||||
for subfn, fnset in other.files_to_rebuild.items():
|
for subfn, fnset in other.files_to_rebuild.items():
|
||||||
env.files_to_rebuild.setdefault(subfn, set()).update(fnset & set(docnames))
|
env.files_to_rebuild.setdefault(subfn, set()).update(fnset & set(docnames))
|
||||||
|
|
||||||
def process_doc(self, app, doctree):
|
def process_doc(self, app: Sphinx, doctree: nodes.document) -> None:
|
||||||
# type: (Sphinx, nodes.document) -> None
|
|
||||||
"""Build a TOC from the doctree and store it in the inventory."""
|
"""Build a TOC from the doctree and store it in the inventory."""
|
||||||
docname = app.env.docname
|
docname = app.env.docname
|
||||||
numentries = [0] # nonlocal again...
|
numentries = [0] # nonlocal again...
|
||||||
|
|
||||||
def traverse_in_section(node, cls):
|
def traverse_in_section(node: Element, cls: Type[N]) -> List[N]:
|
||||||
# type: (nodes.Element, Type[N]) -> List[N]
|
|
||||||
"""Like traverse(), but stay within the same section."""
|
"""Like traverse(), but stay within the same section."""
|
||||||
result = [] # type: List[N]
|
result = [] # type: List[N]
|
||||||
if isinstance(node, cls):
|
if isinstance(node, cls):
|
||||||
@ -80,9 +76,8 @@ class TocTreeCollector(EnvironmentCollector):
|
|||||||
result.extend(traverse_in_section(child, cls))
|
result.extend(traverse_in_section(child, cls))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def build_toc(node, depth=1):
|
def build_toc(node: Element, depth: int = 1) -> nodes.bullet_list:
|
||||||
# type: (nodes.Element, int) -> nodes.bullet_list
|
entries = [] # type: List[Element]
|
||||||
entries = [] # type: List[nodes.Element]
|
|
||||||
for sectionnode in node:
|
for sectionnode in node:
|
||||||
# find all toctree nodes in this section and add them
|
# find all toctree nodes in this section and add them
|
||||||
# to the toc (just copying the toctree node which is then
|
# to the toc (just copying the toctree node which is then
|
||||||
@ -107,7 +102,7 @@ class TocTreeCollector(EnvironmentCollector):
|
|||||||
'', '', internal=True, refuri=docname,
|
'', '', internal=True, refuri=docname,
|
||||||
anchorname=anchorname, *nodetext)
|
anchorname=anchorname, *nodetext)
|
||||||
para = addnodes.compact_paragraph('', '', reference)
|
para = addnodes.compact_paragraph('', '', reference)
|
||||||
item = nodes.list_item('', para) # type: nodes.Element
|
item = nodes.list_item('', para) # type: Element
|
||||||
sub_item = build_toc(sectionnode, depth + 1)
|
sub_item = build_toc(sectionnode, depth + 1)
|
||||||
if sub_item:
|
if sub_item:
|
||||||
item += sub_item
|
item += sub_item
|
||||||
@ -135,12 +130,10 @@ class TocTreeCollector(EnvironmentCollector):
|
|||||||
app.env.tocs[docname] = nodes.bullet_list('')
|
app.env.tocs[docname] = nodes.bullet_list('')
|
||||||
app.env.toc_num_entries[docname] = numentries[0]
|
app.env.toc_num_entries[docname] = numentries[0]
|
||||||
|
|
||||||
def get_updated_docs(self, app, env):
|
def get_updated_docs(self, app: Sphinx, env: BuildEnvironment) -> List[str]:
|
||||||
# type: (Sphinx, BuildEnvironment) -> List[str]
|
|
||||||
return self.assign_section_numbers(env) + self.assign_figure_numbers(env)
|
return self.assign_section_numbers(env) + self.assign_figure_numbers(env)
|
||||||
|
|
||||||
def assign_section_numbers(self, env):
|
def assign_section_numbers(self, env: BuildEnvironment) -> List[str]:
|
||||||
# type: (BuildEnvironment) -> List[str]
|
|
||||||
"""Assign a section number to each heading under a numbered toctree."""
|
"""Assign a section number to each heading under a numbered toctree."""
|
||||||
# a list of all docnames whose section numbers changed
|
# a list of all docnames whose section numbers changed
|
||||||
rewrite_needed = []
|
rewrite_needed = []
|
||||||
@ -149,8 +142,7 @@ class TocTreeCollector(EnvironmentCollector):
|
|||||||
old_secnumbers = env.toc_secnumbers
|
old_secnumbers = env.toc_secnumbers
|
||||||
env.toc_secnumbers = {}
|
env.toc_secnumbers = {}
|
||||||
|
|
||||||
def _walk_toc(node, secnums, depth, titlenode=None):
|
def _walk_toc(node: Element, secnums: Dict, depth: int, titlenode: nodes.title = None) -> None: # NOQA
|
||||||
# type: (nodes.Element, Dict, int, nodes.title) -> None
|
|
||||||
# titlenode is the title of the document, it will get assigned a
|
# titlenode is the title of the document, it will get assigned a
|
||||||
# secnumber too, so that it shows up in next/prev/parent rellinks
|
# secnumber too, so that it shows up in next/prev/parent rellinks
|
||||||
for subnode in node.children:
|
for subnode in node.children:
|
||||||
@ -184,8 +176,7 @@ class TocTreeCollector(EnvironmentCollector):
|
|||||||
elif isinstance(subnode, addnodes.toctree):
|
elif isinstance(subnode, addnodes.toctree):
|
||||||
_walk_toctree(subnode, depth)
|
_walk_toctree(subnode, depth)
|
||||||
|
|
||||||
def _walk_toctree(toctreenode, depth):
|
def _walk_toctree(toctreenode: addnodes.toctree, depth: int) -> None:
|
||||||
# type: (addnodes.toctree, int) -> None
|
|
||||||
if depth == 0:
|
if depth == 0:
|
||||||
return
|
return
|
||||||
for (title, ref) in toctreenode['entries']:
|
for (title, ref) in toctreenode['entries']:
|
||||||
@ -216,8 +207,7 @@ class TocTreeCollector(EnvironmentCollector):
|
|||||||
|
|
||||||
return rewrite_needed
|
return rewrite_needed
|
||||||
|
|
||||||
def assign_figure_numbers(self, env):
|
def assign_figure_numbers(self, env: BuildEnvironment) -> List[str]:
|
||||||
# type: (BuildEnvironment) -> List[str]
|
|
||||||
"""Assign a figure number to each figure under a numbered toctree."""
|
"""Assign a figure number to each figure under a numbered toctree."""
|
||||||
|
|
||||||
rewrite_needed = []
|
rewrite_needed = []
|
||||||
@ -227,8 +217,7 @@ class TocTreeCollector(EnvironmentCollector):
|
|||||||
env.toc_fignumbers = {}
|
env.toc_fignumbers = {}
|
||||||
fignum_counter = {} # type: Dict[str, Dict[Tuple[int, ...], int]]
|
fignum_counter = {} # type: Dict[str, Dict[Tuple[int, ...], int]]
|
||||||
|
|
||||||
def get_figtype(node):
|
def get_figtype(node: Node) -> str:
|
||||||
# type: (nodes.Node) -> str
|
|
||||||
for domain in env.domains.values():
|
for domain in env.domains.values():
|
||||||
figtype = domain.get_enumerable_node_type(node)
|
figtype = domain.get_enumerable_node_type(node)
|
||||||
if figtype:
|
if figtype:
|
||||||
@ -236,8 +225,7 @@ class TocTreeCollector(EnvironmentCollector):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_section_number(docname, section):
|
def get_section_number(docname: str, section: nodes.section) -> Tuple[int, ...]:
|
||||||
# type: (str, nodes.section) -> Tuple[int, ...]
|
|
||||||
anchorname = '#' + section['ids'][0]
|
anchorname = '#' + section['ids'][0]
|
||||||
secnumbers = env.toc_secnumbers.get(docname, {})
|
secnumbers = env.toc_secnumbers.get(docname, {})
|
||||||
if anchorname in secnumbers:
|
if anchorname in secnumbers:
|
||||||
@ -247,24 +235,22 @@ class TocTreeCollector(EnvironmentCollector):
|
|||||||
|
|
||||||
return secnum or tuple()
|
return secnum or tuple()
|
||||||
|
|
||||||
def get_next_fignumber(figtype, secnum):
|
def get_next_fignumber(figtype: str, secnum: Tuple[int, ...]) -> Tuple[int, ...]:
|
||||||
# type: (str, Tuple[int, ...]) -> Tuple[int, ...]
|
|
||||||
counter = fignum_counter.setdefault(figtype, {})
|
counter = fignum_counter.setdefault(figtype, {})
|
||||||
|
|
||||||
secnum = secnum[:env.config.numfig_secnum_depth]
|
secnum = secnum[:env.config.numfig_secnum_depth]
|
||||||
counter[secnum] = counter.get(secnum, 0) + 1
|
counter[secnum] = counter.get(secnum, 0) + 1
|
||||||
return secnum + (counter[secnum],)
|
return secnum + (counter[secnum],)
|
||||||
|
|
||||||
def register_fignumber(docname, secnum, figtype, fignode):
|
def register_fignumber(docname: str, secnum: Tuple[int, ...],
|
||||||
# type: (str, Tuple[int, ...], str, nodes.Element) -> None
|
figtype: str, fignode: Element) -> None:
|
||||||
env.toc_fignumbers.setdefault(docname, {})
|
env.toc_fignumbers.setdefault(docname, {})
|
||||||
fignumbers = env.toc_fignumbers[docname].setdefault(figtype, {})
|
fignumbers = env.toc_fignumbers[docname].setdefault(figtype, {})
|
||||||
figure_id = fignode['ids'][0]
|
figure_id = fignode['ids'][0]
|
||||||
|
|
||||||
fignumbers[figure_id] = get_next_fignumber(figtype, secnum)
|
fignumbers[figure_id] = get_next_fignumber(figtype, secnum)
|
||||||
|
|
||||||
def _walk_doctree(docname, doctree, secnum):
|
def _walk_doctree(docname: str, doctree: Element, secnum: Tuple[int, ...]) -> None:
|
||||||
# type: (str, nodes.Element, Tuple[int, ...]) -> None
|
|
||||||
for subnode in doctree.children:
|
for subnode in doctree.children:
|
||||||
if isinstance(subnode, nodes.section):
|
if isinstance(subnode, nodes.section):
|
||||||
next_secnum = get_section_number(docname, subnode)
|
next_secnum = get_section_number(docname, subnode)
|
||||||
@ -286,8 +272,7 @@ class TocTreeCollector(EnvironmentCollector):
|
|||||||
|
|
||||||
_walk_doctree(docname, subnode, secnum)
|
_walk_doctree(docname, subnode, secnum)
|
||||||
|
|
||||||
def _walk_doc(docname, secnum):
|
def _walk_doc(docname: str, secnum: Tuple[int, ...]) -> None:
|
||||||
# type: (str, Tuple[int, ...]) -> None
|
|
||||||
if docname not in assigned:
|
if docname not in assigned:
|
||||||
assigned.add(docname)
|
assigned.add(docname)
|
||||||
doctree = env.get_doctree(docname)
|
doctree = env.get_doctree(docname)
|
||||||
@ -302,8 +287,7 @@ class TocTreeCollector(EnvironmentCollector):
|
|||||||
return rewrite_needed
|
return rewrite_needed
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||||
# type: (Sphinx) -> Dict
|
|
||||||
app.add_env_collector(TocTreeCollector)
|
app.add_env_collector(TocTreeCollector)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -166,7 +166,7 @@ class DownloadFiles(dict):
|
|||||||
Hence don't hack this directly.
|
Hence don't hack this directly.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def add_file(self, docname: str, filename: str) -> None:
|
def add_file(self, docname: str, filename: str) -> str:
|
||||||
if filename not in self:
|
if filename not in self:
|
||||||
digest = md5(filename.encode()).hexdigest()
|
digest = md5(filename.encode()).hexdigest()
|
||||||
dest = '%s/%s' % (digest, os.path.basename(filename))
|
dest = '%s/%s' % (digest, os.path.basename(filename))
|
||||||
|
Loading…
Reference in New Issue
Block a user