diff --git a/sphinx/application.py b/sphinx/application.py index 141fcdae8..975dc2a70 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -19,8 +19,12 @@ from collections import deque from inspect import isclass from io import StringIO from os import path +from typing import Any, Callable, Dict, IO, List, Tuple, Union +from docutils import nodes +from docutils.nodes import Element, TextElement from docutils.parsers.rst import Directive, roles +from docutils.transforms import Transform from pygments.lexer import Lexer import sphinx @@ -29,13 +33,18 @@ from sphinx.config import Config from sphinx.deprecation import ( RemovedInSphinx30Warning, RemovedInSphinx40Warning, deprecated_alias ) +from sphinx.domains import Domain, Index from sphinx.environment import BuildEnvironment +from sphinx.environment.collectors import EnvironmentCollector from sphinx.errors import ApplicationError, ConfigError, VersionRequirementError from sphinx.events import EventManager +from sphinx.extension import Extension from sphinx.highlighting import lexer_classes, lexers from sphinx.locale import __ from sphinx.project import Project from sphinx.registry import SphinxComponentRegistry +from sphinx.roles import XRefRole +from sphinx.theming import Theme from sphinx.util import docutils from sphinx.util import import_object, progress_message from sphinx.util import logging @@ -46,21 +55,14 @@ from sphinx.util.i18n import CatalogRepository from sphinx.util.logging import prefixed_warnings from sphinx.util.osutil import abspath, ensuredir, relpath from sphinx.util.tags import Tags +from sphinx.util.typing import RoleFunction, TitleGetter if False: # For type annotation - from typing import Any, Callable, Dict, IO, Iterable, Iterator, List, Tuple, Union # NOQA + from docutils.nodes import Node # NOQA from typing import Type # for python3.5.1 - from docutils import nodes # NOQA - from docutils.parsers import Parser # NOQA - from docutils.transforms import Transform # NOQA - from sphinx.builders import Builder # NOQA - from sphinx.domains import Domain, Index # NOQA - from sphinx.environment.collectors import EnvironmentCollector # NOQA - from sphinx.extension import Extension # NOQA - from sphinx.roles import XRefRole # NOQA - from sphinx.theming import Theme # NOQA - from sphinx.util.typing import RoleFunction, TitleGetter # NOQA + from sphinx.builders import Builder + builtin_extensions = ( 'sphinx.addnodes', @@ -137,11 +139,11 @@ class Sphinx: :ivar outdir: Directory for storing build documents. """ - def __init__(self, srcdir, confdir, outdir, doctreedir, buildername, - confoverrides=None, status=sys.stdout, warning=sys.stderr, - freshenv=False, warningiserror=False, tags=None, verbosity=0, - parallel=0, keep_going=False): - # type: (str, str, str, str, str, Dict, IO, IO, bool, bool, List[str], int, int, bool) -> None # NOQA + def __init__(self, srcdir: str, confdir: str, outdir: str, doctreedir: str, + buildername: str, confoverrides: Dict = None, + status: IO = sys.stdout, warning: IO = sys.stderr, + freshenv: bool = False, warningiserror: bool = False, tags: List[str] = None, + verbosity: int = 0, parallel: int = 0, keep_going: bool = False) -> None: self.phase = BuildPhase.INITIALIZATION self.verbosity = verbosity self.extensions = {} # type: Dict[str, Extension] @@ -275,8 +277,7 @@ class Sphinx: # set up the builder self._init_builder() - def _init_i18n(self): - # type: () -> None + def _init_i18n(self) -> None: """Load translated strings from the configured localedirs if enabled in the configuration. """ @@ -301,8 +302,7 @@ class Sphinx: else: logger.info(__('not available for built-in messages')) - def _init_env(self, freshenv): - # type: (bool) -> None + def _init_env(self, freshenv: bool) -> None: filename = path.join(self.doctreedir, ENV_PICKLE_FILENAME) if freshenv or not os.path.exists(filename): self.env = BuildEnvironment() @@ -318,28 +318,24 @@ class Sphinx: logger.info(__('failed: %s'), err) self._init_env(freshenv=True) - def preload_builder(self, name): - # type: (str) -> None + def preload_builder(self, name: str) -> None: self.registry.preload_builder(self, name) - def create_builder(self, name): - # type: (str) -> Builder + def create_builder(self, name: str) -> "Builder": if name is None: logger.info(__('No builder selected, using default: html')) name = 'html' return self.registry.create_builder(self, name) - def _init_builder(self): - # type: () -> None + def _init_builder(self) -> None: self.builder.set_environment(self.env) self.builder.init() self.events.emit('builder-inited') # ---- main "build" method ------------------------------------------------- - def build(self, force_all=False, filenames=None): - # type: (bool, List[str]) -> None + def build(self, force_all: bool = False, filenames: List[str] = None) -> None: self.phase = BuildPhase.READING try: if force_all: @@ -390,8 +386,7 @@ class Sphinx: # ---- general extensibility interface ------------------------------------- - def setup_extension(self, extname): - # type: (str) -> None + def setup_extension(self, extname: str) -> None: """Import and setup a Sphinx extension module. Load the extension given by the module *name*. Use this if your @@ -401,8 +396,7 @@ class Sphinx: logger.debug('[app] setting up extension: %r', extname) self.registry.load_extension(self, extname) - def require_sphinx(self, version): - # type: (str) -> None + def require_sphinx(self, version: str) -> None: """Check the Sphinx version if requested. Compare *version* (which must be a ``major.minor`` version string, e.g. @@ -414,8 +408,7 @@ class Sphinx: if version > sphinx.__display_version__[:3]: raise VersionRequirementError(version) - def import_object(self, objname, source=None): - # type: (str, str) -> Any + def import_object(self, objname: str, source: str = None) -> Any: """Import an object from a ``module.name`` string. .. deprecated:: 1.8 @@ -427,8 +420,7 @@ class Sphinx: return import_object(objname, source=None) # event interface - def connect(self, event, callback): - # type: (str, Callable) -> int + def connect(self, event: str, callback: Callable) -> int: """Register *callback* to be called when *event* is emitted. For details on available core events and the arguments of callback @@ -441,14 +433,12 @@ class Sphinx: logger.debug('[app] connecting event %r: %r [id=%s]', event, callback, listener_id) return listener_id - def disconnect(self, listener_id): - # type: (int) -> None + def disconnect(self, listener_id: int) -> None: """Unregister callback by *listener_id*.""" logger.debug('[app] disconnecting event: [id=%s]', listener_id) self.events.disconnect(listener_id) - def emit(self, event, *args): - # type: (str, Any) -> List + def emit(self, event: str, *args) -> List: """Emit *event* and pass *arguments* to the callback functions. Return the return values of all callbacks as a list. Do not emit core @@ -456,8 +446,7 @@ class Sphinx: """ return self.events.emit(event, *args) - def emit_firstresult(self, event, *args): - # type: (str, Any) -> Any + def emit_firstresult(self, event: str, *args) -> Any: """Emit *event* and pass *arguments* to the callback functions. Return the result of the first callback that doesn't return ``None``. @@ -468,8 +457,7 @@ class Sphinx: # registering addon parts - def add_builder(self, builder, override=False): - # type: (Type[Builder], bool) -> None + def add_builder(self, builder: "Type[Builder]", override: bool = False) -> None: """Register a new builder. *builder* must be a class that inherits from @@ -481,8 +469,8 @@ class Sphinx: self.registry.add_builder(builder, override=override) # TODO(stephenfin): Describe 'types' parameter - def add_config_value(self, name, default, rebuild, types=()): - # type: (str, Any, Union[bool, str], Any) -> None + def add_config_value(self, name: str, default: Any, rebuild: Union[bool, str], + types: Any = ()) -> None: """Register a configuration value. This is necessary for Sphinx to recognize new values and set default @@ -514,8 +502,7 @@ class Sphinx: rebuild = 'env' if rebuild else '' self.config.add(name, default, rebuild, types) - def add_event(self, name): - # type: (str) -> None + def add_event(self, name: str) -> None: """Register an event called *name*. This is needed to be able to emit it. @@ -523,8 +510,8 @@ class Sphinx: logger.debug('[app] adding event: %r', name) self.events.add(name) - def set_translator(self, name, translator_class, override=False): - # type: (str, Type[nodes.NodeVisitor], bool) -> None + def set_translator(self, name: str, translator_class: "Type[nodes.NodeVisitor]", + override: bool = False) -> None: """Register or override a Docutils translator class. This is used to register a custom output translator or to replace a @@ -537,8 +524,7 @@ class Sphinx: """ self.registry.add_translator(name, translator_class, override=override) - def add_node(self, node, override=False, **kwds): - # type: (Type[nodes.Element], bool, Any) -> None + def add_node(self, node: "Type[Element]", override: bool = False, **kwds) -> None: """Register a Docutils node class. This is necessary for Docutils internals. It may also be used in the @@ -576,8 +562,9 @@ class Sphinx: docutils.register_node(node) self.registry.add_translation_handlers(node, **kwds) - def add_enumerable_node(self, node, figtype, title_getter=None, override=False, **kwds): - # type: (Type[nodes.Element], str, TitleGetter, bool, Any) -> None + def add_enumerable_node(self, node: "Type[Element]", figtype: str, + title_getter: TitleGetter = None, override: bool = False, + **kwds) -> None: """Register a Docutils node class as a numfig target. Sphinx numbers the node automatically. And then the users can refer it @@ -605,15 +592,15 @@ class Sphinx: self.add_node(node, override=override, **kwds) @property - def enumerable_nodes(self): - # type: () -> Dict[Type[nodes.Node], Tuple[str, TitleGetter]] + def enumerable_nodes(self) -> Dict["Type[Node]", Tuple[str, TitleGetter]]: warnings.warn('app.enumerable_nodes() is deprecated. ' 'Use app.get_domain("std").enumerable_nodes instead.', RemovedInSphinx30Warning, stacklevel=2) return self.registry.enumerable_nodes - def add_directive(self, name, obj, content=None, arguments=None, override=False, **options): # NOQA - # type: (str, Any, bool, Tuple[int, int, bool], bool, Any) -> None + def add_directive(self, name: str, obj: Any, content: bool = None, + arguments: Tuple[int, int, bool] = None, override: bool = False, + **options) -> None: """Register a Docutils directive. *name* must be the prospective directive name. There are two possible @@ -676,8 +663,7 @@ class Sphinx: else: docutils.register_directive(name, obj) - def add_role(self, name, role, override=False): - # type: (str, Any, bool) -> None + def add_role(self, name: str, role: Any, override: bool = False) -> None: """Register a Docutils role. *name* must be the role name that occurs in the source, *role* the role @@ -694,8 +680,7 @@ class Sphinx: name, type='app', subtype='add_role') docutils.register_role(name, role) - def add_generic_role(self, name, nodeclass, override=False): - # type: (str, Any, bool) -> None + def add_generic_role(self, name: str, nodeclass: Any, override: bool = False) -> None: """Register a generic Docutils role. Register a Docutils role that does nothing but wrap its contents in the @@ -714,8 +699,7 @@ class Sphinx: role = roles.GenericRole(name, nodeclass) docutils.register_role(name, role) - def add_domain(self, domain, override=False): - # type: (Type[Domain], bool) -> None + def add_domain(self, domain: "Type[Domain]", override: bool = False) -> None: """Register a domain. Make the given *domain* (which must be a class; more precisely, a @@ -727,8 +711,7 @@ class Sphinx: """ self.registry.add_domain(domain, override=override) - def override_domain(self, domain): - # type: (Type[Domain]) -> None + def override_domain(self, domain: "Type[Domain]") -> None: """Override a registered domain. Make the given *domain* class known to Sphinx, assuming that there is @@ -744,9 +727,9 @@ class Sphinx: RemovedInSphinx30Warning, stacklevel=2) self.registry.add_domain(domain, override=True) - def add_directive_to_domain(self, domain, name, obj, has_content=None, argument_spec=None, - override=False, **option_spec): - # type: (str, str, Any, bool, Any, bool, Any) -> None + def add_directive_to_domain(self, domain: str, name: str, obj: Any, + has_content: bool = None, argument_spec: Any = None, + override: bool = False, **option_spec) -> None: """Register a Docutils directive in a domain. Like :meth:`add_directive`, but the directive is added to the domain @@ -760,8 +743,8 @@ class Sphinx: has_content, argument_spec, override=override, **option_spec) - def add_role_to_domain(self, domain, name, role, override=False): - # type: (str, str, Union[RoleFunction, XRefRole], bool) -> None + def add_role_to_domain(self, domain: str, name: str, role: Union[RoleFunction, XRefRole], + override: bool = False) -> None: """Register a Docutils role in a domain. Like :meth:`add_role`, but the role is added to the domain named @@ -773,8 +756,8 @@ class Sphinx: """ self.registry.add_role_to_domain(domain, name, role, override=override) - def add_index_to_domain(self, domain, index, override=False): - # type: (str, Type[Index], bool) -> None + def add_index_to_domain(self, domain: str, index: "Type[Index]", override: bool = False + ) -> None: """Register a custom index for a domain. Add a custom *index* class to the domain named *domain*. *index* must @@ -786,10 +769,10 @@ class Sphinx: """ self.registry.add_index_to_domain(domain, index) - def add_object_type(self, directivename, rolename, indextemplate='', - parse_node=None, ref_nodeclass=None, objname='', - doc_field_types=[], override=False): - # type: (str, str, str, Callable, Type[nodes.TextElement], str, List, bool) -> None + def add_object_type(self, directivename: str, rolename: str, indextemplate: str = '', + parse_node: Callable = None, ref_nodeclass: "Type[TextElement]" = None, + objname: str = '', doc_field_types: List = [], override: bool = False + ) -> None: """Register a new object type. This method is a very convenient way to add a new :term:`object` type @@ -850,9 +833,9 @@ class Sphinx: ref_nodeclass, objname, doc_field_types, override=override) - def add_crossref_type(self, directivename, rolename, indextemplate='', - ref_nodeclass=None, objname='', override=False): - # type: (str, str, str, Type[nodes.TextElement], str, bool) -> None + def add_crossref_type(self, directivename: str, rolename: str, indextemplate: str = '', + ref_nodeclass: "Type[TextElement]" = None, objname: str = '', + override: bool = False) -> None: """Register a new crossref object type. This method is very similar to :meth:`add_object_type` except that the @@ -886,8 +869,7 @@ class Sphinx: indextemplate, ref_nodeclass, objname, override=override) - def add_transform(self, transform): - # type: (Type[Transform]) -> None + def add_transform(self, transform: "Type[Transform]") -> None: """Register a Docutils transform to be applied after parsing. Add the standard docutils :class:`Transform` subclass *transform* to @@ -920,8 +902,7 @@ class Sphinx: """ # NOQA self.registry.add_transform(transform) - def add_post_transform(self, transform): - # type: (Type[Transform]) -> None + def add_post_transform(self, transform: "Type[Transform]") -> None: """Register a Docutils transform to be applied before writing. Add the standard docutils :class:`Transform` subclass *transform* to @@ -930,16 +911,14 @@ class Sphinx: """ self.registry.add_post_transform(transform) - def add_javascript(self, filename, **kwargs): - # type: (str, **str) -> None + def add_javascript(self, filename: str, **kwargs: str) -> None: """An alias of :meth:`add_js_file`.""" warnings.warn('The app.add_javascript() is deprecated. ' 'Please use app.add_js_file() instead.', RemovedInSphinx40Warning, stacklevel=2) self.add_js_file(filename, **kwargs) - def add_js_file(self, filename, **kwargs): - # type: (str, **str) -> None + def add_js_file(self, filename: str, **kwargs: str) -> None: """Register a JavaScript file to include in the HTML output. Add *filename* to the list of JavaScript files that the default HTML @@ -965,8 +944,7 @@ class Sphinx: if hasattr(self.builder, 'add_js_file'): self.builder.add_js_file(filename, **kwargs) # type: ignore - def add_css_file(self, filename, **kwargs): - # type: (str, **str) -> None + def add_css_file(self, filename: str, **kwargs: str) -> None: """Register a stylesheet to include in the HTML output. Add *filename* to the list of CSS files that the default HTML template @@ -1005,8 +983,8 @@ class Sphinx: if hasattr(self.builder, 'add_css_file'): self.builder.add_css_file(filename, **kwargs) # type: ignore - def add_stylesheet(self, filename, alternate=False, title=None): - # type: (str, bool, str) -> None + def add_stylesheet(self, filename: str, alternate: bool = False, title: str = None + ) -> None: """An alias of :meth:`add_css_file`.""" warnings.warn('The app.add_stylesheet() is deprecated. ' 'Please use app.add_css_file() instead.', @@ -1023,8 +1001,7 @@ class Sphinx: self.add_css_file(filename, **attributes) - def add_latex_package(self, packagename, options=None): - # type: (str, str) -> None + def add_latex_package(self, packagename: str, options: str = None) -> None: r"""Register a package to include in the LaTeX source code. Add *packagename* to the list of packages that LaTeX source code will @@ -1042,8 +1019,7 @@ class Sphinx: """ self.registry.add_latex_package(packagename, options) - def add_lexer(self, alias, lexer): - # type: (str, Union[Lexer, Type[Lexer]]) -> None + def add_lexer(self, alias: str, lexer: Union[Lexer, "Type[Lexer]"]) -> None: """Register a new lexer for source code. Use *lexer* to highlight code blocks with the given language *alias*. @@ -1062,8 +1038,7 @@ class Sphinx: else: lexer_classes[alias] = lexer - def add_autodocumenter(self, cls, override=False): - # type: (Any, bool) -> None + def add_autodocumenter(self, cls: Any, override: bool = False) -> None: """Register a new documenter class for the autodoc extension. Add *cls* as a new documenter class for the :mod:`sphinx.ext.autodoc` @@ -1083,8 +1058,8 @@ class Sphinx: self.registry.add_documenter(cls.objtype, cls) self.add_directive('auto' + cls.objtype, AutodocDirective, override=override) - def add_autodoc_attrgetter(self, typ, getter): - # type: (Type, Callable[[Any, str, Any], Any]) -> None + def add_autodoc_attrgetter(self, typ: "Type", getter: Callable[[Any, str, Any], Any] + ) -> None: """Register a new ``getattr``-like function for the autodoc extension. Add *getter*, which must be a function with an interface compatible to @@ -1098,8 +1073,7 @@ class Sphinx: logger.debug('[app] adding autodoc attrgetter: %r', (typ, getter)) self.registry.add_autodoc_attrgetter(typ, getter) - def add_search_language(self, cls): - # type: (Any) -> None + def add_search_language(self, cls: Any) -> None: """Register a new language for the HTML search index. Add *cls*, which must be a subclass of @@ -1115,8 +1089,7 @@ class Sphinx: assert issubclass(cls, SearchLanguage) languages[cls.lang] = cls - def add_source_suffix(self, suffix, filetype, override=False): - # type: (str, str, bool) -> None + def add_source_suffix(self, suffix: str, filetype: str, override: bool = False) -> None: """Register a suffix of source files. Same as :confval:`source_suffix`. The users can override this @@ -1126,8 +1099,7 @@ class Sphinx: """ self.registry.add_source_suffix(suffix, filetype, override=override) - def add_source_parser(self, *args, **kwargs): - # type: (Any, Any) -> None + def add_source_parser(self, *args, **kwargs) -> None: """Register a parser class. .. versionadded:: 1.4 @@ -1139,8 +1111,7 @@ class Sphinx: """ self.registry.add_source_parser(*args, **kwargs) - def add_env_collector(self, collector): - # type: (Type[EnvironmentCollector]) -> None + def add_env_collector(self, collector: "Type[EnvironmentCollector]") -> None: """Register an environment collector class. Refer to :ref:`collector-api`. @@ -1150,8 +1121,7 @@ class Sphinx: logger.debug('[app] adding environment collector: %r', collector) collector().enable(self) - def add_html_theme(self, name, theme_path): - # type: (str, str) -> None + def add_html_theme(self, name: str, theme_path: str) -> None: """Register a HTML Theme. The *name* is a name of theme, and *path* is a full path to the theme @@ -1162,8 +1132,9 @@ class Sphinx: logger.debug('[app] adding HTML theme: %r, %r', name, theme_path) self.html_themes[name] = theme_path - def add_html_math_renderer(self, name, inline_renderers=None, block_renderers=None): - # type: (str, Tuple[Callable, Callable], Tuple[Callable, Callable]) -> None + def add_html_math_renderer(self, name: str, + inline_renderers: Tuple[Callable, Callable] = None, + block_renderers: Tuple[Callable, Callable] = None) -> None: """Register a math renderer for HTML. The *name* is a name of math renderer. Both *inline_renderers* and @@ -1177,8 +1148,7 @@ class Sphinx: """ self.registry.add_html_math_renderer(name, inline_renderers, block_renderers) - def add_message_catalog(self, catalog, locale_dir): - # type: (str, str) -> None + def add_message_catalog(self, catalog: str, locale_dir: str) -> None: """Register a message catalog. The *catalog* is a name of catalog, and *locale_dir* is a base path @@ -1191,8 +1161,7 @@ class Sphinx: locale.init_console(locale_dir, catalog) # ---- other methods ------------------------------------------------- - def is_parallel_allowed(self, typ): - # type: (str) -> bool + def is_parallel_allowed(self, typ: str) -> bool: """Check parallel processing is allowed or not. ``typ`` is a type of processing; ``'read'`` or ``'write'``. @@ -1228,8 +1197,7 @@ class Sphinx: return True @property - def _setting_up_extension(self): - # type: () -> List[str] + def _setting_up_extension(self) -> List[str]: warnings.warn('app._setting_up_extension is deprecated.', RemovedInSphinx30Warning) return ['?'] @@ -1241,8 +1209,7 @@ class TemplateBridge: that renders templates given a template name and a context. """ - def init(self, builder, theme=None, dirs=None): - # type: (Builder, Theme, List[str]) -> None + def init(self, builder: "Builder", theme: Theme = None, dirs: List[str] = None) -> None: """Called by the builder to initialize the template system. *builder* is the builder object; you'll probably want to look at the @@ -1253,23 +1220,20 @@ class TemplateBridge: """ raise NotImplementedError('must be implemented in subclasses') - def newest_template_mtime(self): - # type: () -> float + def newest_template_mtime(self) -> float: """Called by the builder to determine if output files are outdated because of template changes. Return the mtime of the newest template file that was changed. The default implementation returns ``0``. """ return 0 - def render(self, template, context): - # type: (str, Dict) -> None + def render(self, template: str, context: Dict) -> None: """Called by the builder to render a template given as a filename with a specified context (a Python dictionary). """ raise NotImplementedError('must be implemented in subclasses') - def render_string(self, template, context): - # type: (str, Dict) -> str + def render_string(self, template: str, context: Dict) -> str: """Called by the builder to render a template given as a string with a specified context (a Python dictionary). """ diff --git a/sphinx/environment/collectors/__init__.py b/sphinx/environment/collectors/__init__.py index eb16a9f25..137a10302 100644 --- a/sphinx/environment/collectors/__init__.py +++ b/sphinx/environment/collectors/__init__.py @@ -12,9 +12,12 @@ from typing import Dict, List, Set from docutils import nodes -from sphinx.application import Sphinx from sphinx.environment import BuildEnvironment +if False: + # For type annotation + from sphinx.application import Sphinx + class EnvironmentCollector: """An EnvironmentCollector is a specific data collector from each document. @@ -27,7 +30,7 @@ class EnvironmentCollector: listener_ids = None # type: Dict[str, int] - def enable(self, app: Sphinx) -> None: + def enable(self, app: "Sphinx") -> None: assert self.listener_ids is None self.listener_ids = { 'doctree-read': app.connect('doctree-read', self.process_doc), @@ -37,38 +40,38 @@ class EnvironmentCollector: 'env-get-outdated': app.connect('env-get-outdated', self.get_outdated_docs), } - def disable(self, app: Sphinx) -> None: + def disable(self, app: "Sphinx") -> None: assert self.listener_ids is not None for listener_id in self.listener_ids.values(): app.disconnect(listener_id) self.listener_ids = None - def clear_doc(self, app: Sphinx, env: BuildEnvironment, docname: str) -> None: + def clear_doc(self, app: "Sphinx", env: BuildEnvironment, docname: str) -> None: """Remove specified data of a document. This method is called on the removal of the document.""" raise NotImplementedError - def merge_other(self, app: Sphinx, env: BuildEnvironment, + def merge_other(self, app: "Sphinx", env: BuildEnvironment, docnames: Set[str], other: BuildEnvironment) -> None: """Merge in specified data regarding docnames from a different `BuildEnvironment` object which coming from a subprocess in parallel builds.""" raise NotImplementedError - def process_doc(self, app: Sphinx, doctree: nodes.document) -> None: + def process_doc(self, app: "Sphinx", doctree: nodes.document) -> None: """Process a document and gather specific data from it. This method is called after the document is read.""" raise NotImplementedError - def get_updated_docs(self, app: Sphinx, env: BuildEnvironment) -> List[str]: + def get_updated_docs(self, app: "Sphinx", env: BuildEnvironment) -> List[str]: """Return a list of docnames to re-read. This methods is called after reading the whole of documents (experimental). """ return [] - def get_outdated_docs(self, app: Sphinx, env: BuildEnvironment, + def get_outdated_docs(self, app: "Sphinx", env: BuildEnvironment, added: Set[str], changed: Set[str], removed: Set[str]) -> List[str]: """Return a list of docnames to re-read.