diff options
author | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2019-06-09 01:27:34 +0900 |
---|---|---|
committer | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2019-06-09 01:27:34 +0900 |
commit | 9f470cec6c943a9437dac2c09ea796e78e08156d (patch) | |
tree | 31e26a9be046f8b2e7499a93db1a5ee8dd6d4c3a /sphinx/util/docutils.py | |
parent | 5ce5c2c3156c53c1f1b758c38150e48080138b15 (diff) | |
parent | 5cabe8be35ee44ca9a9ddaf5d93e2dd9f62abdc9 (diff) | |
download | sphinx-git-9f470cec6c943a9437dac2c09ea796e78e08156d.tar.gz |
Merge branch '2.0'
Diffstat (limited to 'sphinx/util/docutils.py')
-rw-r--r-- | sphinx/util/docutils.py | 149 |
1 files changed, 57 insertions, 92 deletions
diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index d38c780f4..9f01a9f9f 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -14,31 +14,31 @@ from contextlib import contextmanager from copy import copy from distutils.version import LooseVersion from os import path -from typing import IO, cast +from types import ModuleType +from typing import Any, Callable, Dict, Generator, IO, List, Set, Tuple, Type +from typing import cast import docutils from docutils import nodes from docutils.io import FileOutput +from docutils.nodes import Element, Node, system_message from docutils.parsers.rst import Directive, directives, roles -from docutils.statemachine import StateMachine +from docutils.parsers.rst.states import Inliner +from docutils.statemachine import StateMachine, State, StringList from docutils.utils import Reporter, unescape from sphinx.errors import SphinxError from sphinx.util import logging +from sphinx.util.typing import RoleFunction logger = logging.getLogger(__name__) report_re = re.compile('^(.+?:(?:\\d+)?): \\((DEBUG|INFO|WARNING|ERROR|SEVERE)/(\\d+)?\\) ') if False: # For type annotation - from types import ModuleType # NOQA - from typing import Any, Callable, Dict, Generator, List, Set, Tuple, Type # NOQA - from docutils.parsers.rst.states import Inliner # NOQA - from docutils.statemachine import State, StringList # NOQA - from sphinx.builders import Builder # NOQA - from sphinx.config import Config # NOQA - from sphinx.environment import BuildEnvironment # NOQA - from sphinx.util.typing import RoleFunction # NOQA + from sphinx.builders import Builder + from sphinx.config import Config + from sphinx.environment import BuildEnvironment __version_info__ = tuple(LooseVersion(docutils.__version__).version) @@ -46,8 +46,7 @@ additional_nodes = set() # type: Set[Type[nodes.Element]] @contextmanager -def docutils_namespace(): - # type: () -> Generator[None, None, None] +def docutils_namespace() -> Generator[None, None, None]: """Create namespace for reST parsers.""" try: _directives = copy(directives._directives) # type: ignore @@ -63,14 +62,12 @@ def docutils_namespace(): additional_nodes.discard(node) -def is_directive_registered(name): - # type: (str) -> bool +def is_directive_registered(name: str) -> bool: """Check the *name* directive is already registered.""" return name in directives._directives # type: ignore -def register_directive(name, directive): - # type: (str, Type[Directive]) -> None +def register_directive(name: str, directive: Type[Directive]) -> None: """Register a directive to docutils. This modifies global state of docutils. So it is better to use this @@ -79,14 +76,12 @@ def register_directive(name, directive): directives.register_directive(name, directive) -def is_role_registered(name): - # type: (str) -> bool +def is_role_registered(name: str) -> bool: """Check the *name* role is already registered.""" return name in roles._roles # type: ignore -def register_role(name, role): - # type: (str, RoleFunction) -> None +def register_role(name: str, role: RoleFunction) -> None: """Register a role to docutils. This modifies global state of docutils. So it is better to use this @@ -95,20 +90,17 @@ def register_role(name, role): roles.register_local_role(name, role) -def unregister_role(name): - # type: (str) -> None +def unregister_role(name: str) -> None: """Unregister a role from docutils.""" roles._roles.pop(name, None) # type: ignore -def is_node_registered(node): - # type: (Type[nodes.Element]) -> bool +def is_node_registered(node: Type[Element]) -> bool: """Check the *node* is already registered.""" return hasattr(nodes.GenericNodeVisitor, 'visit_' + node.__name__) -def register_node(node): - # type: (Type[nodes.Element]) -> None +def register_node(node: Type[Element]) -> None: """Register a node to docutils. This modifies global state of some visitors. So it is better to use this @@ -119,8 +111,7 @@ def register_node(node): additional_nodes.add(node) -def unregister_node(node): - # type: (Type[nodes.Element]) -> None +def unregister_node(node: Type[Element]) -> None: """Unregister a node from docutils. This is inverse of ``nodes._add_nodes_class_names()``. @@ -133,8 +124,7 @@ def unregister_node(node): @contextmanager -def patched_get_language(): - # type: () -> Generator[None, None, None] +def patched_get_language() -> Generator[None, None, None]: """Patch docutils.languages.get_language() temporarily. This ignores the second argument ``reporter`` to suppress warnings. @@ -142,8 +132,7 @@ def patched_get_language(): """ from docutils.languages import get_language - def patched_get_language(language_code, reporter=None): - # type: (str, Reporter) -> Any + def patched_get_language(language_code: str, reporter: Reporter = None) -> Any: return get_language(language_code) try: @@ -155,8 +144,7 @@ def patched_get_language(): @contextmanager -def using_user_docutils_conf(confdir): - # type: (str) -> Generator[None, None, None] +def using_user_docutils_conf(confdir: str) -> Generator[None, None, None]: """Let docutils know the location of ``docutils.conf`` for Sphinx.""" try: docutilsconfig = os.environ.get('DOCUTILSCONFIG', None) @@ -172,8 +160,7 @@ def using_user_docutils_conf(confdir): @contextmanager -def patch_docutils(confdir=None): - # type: (str) -> Generator[None, None, None] +def patch_docutils(confdir: str = None) -> Generator[None, None, None]: """Patch to docutils temporarily.""" with patched_get_language(), using_user_docutils_conf(confdir): yield @@ -187,35 +174,30 @@ class sphinx_domains: """Monkey-patch directive and role dispatch, so that domain-specific markup takes precedence. """ - def __init__(self, env): - # type: (BuildEnvironment) -> None + def __init__(self, env: "BuildEnvironment") -> None: self.env = env self.directive_func = None # type: Callable self.roles_func = None # type: Callable - def __enter__(self): - # type: () -> None + def __enter__(self) -> None: self.enable() - def __exit__(self, type, value, traceback): - # type: (str, str, str) -> None + def __exit__(self, exc_type: Type[Exception], exc_value: Exception, traceback: Any) -> bool: # NOQA self.disable() + return True - def enable(self): - # type: () -> None + def enable(self) -> None: self.directive_func = directives.directive self.role_func = roles.role directives.directive = self.lookup_directive # type: ignore roles.role = self.lookup_role # type: ignore - def disable(self): - # type: () -> None + def disable(self) -> None: directives.directive = self.directive_func roles.role = self.role_func - def lookup_domain_element(self, type, name): - # type: (str, str) -> Any + def lookup_domain_element(self, type: str, name: str) -> Any: """Lookup a markup element (directive or role), given its name which can be a full name (with domain). """ @@ -243,15 +225,13 @@ class sphinx_domains: raise ElementLookupError - def lookup_directive(self, name, lang_module, document): - # type: (str, ModuleType, nodes.document) -> Tuple[Type[Directive], List[nodes.system_message]] # NOQA + def lookup_directive(self, name: str, lang_module: ModuleType, document: nodes.document) -> Tuple[Type[Directive], List[system_message]]: # NOQA try: return self.lookup_domain_element('directive', name) except ElementLookupError: return self.directive_func(name, lang_module, document) - def lookup_role(self, name, lang_module, lineno, reporter): - # type: (str, ModuleType, int, Reporter) -> Tuple[RoleFunction, List[nodes.system_message]] # NOQA + def lookup_role(self, name: str, lang_module: ModuleType, lineno: int, reporter: Reporter) -> Tuple[RoleFunction, List[system_message]]: # NOQA try: return self.lookup_domain_element('role', name) except ElementLookupError: @@ -259,8 +239,7 @@ class sphinx_domains: class WarningStream: - def write(self, text): - # type: (str) -> None + def write(self, text: str) -> None: matched = report_re.search(text) if not matched: logger.warning(text.rstrip("\r\n")) @@ -272,16 +251,14 @@ class WarningStream: class LoggingReporter(Reporter): @classmethod - def from_reporter(cls, reporter): - # type: (Reporter) -> LoggingReporter + def from_reporter(cls, reporter: Reporter) -> "LoggingReporter": """Create an instance of LoggingReporter from other reporter object.""" return cls(reporter.source, reporter.report_level, reporter.halt_level, reporter.debug_flag, reporter.error_handler) - def __init__(self, source, report_level=Reporter.WARNING_LEVEL, - halt_level=Reporter.SEVERE_LEVEL, debug=False, - error_handler='backslashreplace'): - # type: (str, int, int, bool, str) -> None + def __init__(self, source: str, report_level: int = Reporter.WARNING_LEVEL, + halt_level: int = Reporter.SEVERE_LEVEL, debug: bool = False, + error_handler: str = 'backslashreplace') -> None: stream = cast(IO, WarningStream()) super().__init__(source, report_level, halt_level, stream, debug, error_handler=error_handler) @@ -290,19 +267,16 @@ class LoggingReporter(Reporter): class NullReporter(Reporter): """A dummy reporter; write nothing.""" - def __init__(self): - # type: () -> None + def __init__(self) -> None: super().__init__('', 999, 4) -def is_html5_writer_available(): - # type: () -> bool +def is_html5_writer_available() -> bool: return __version_info__ > (0, 13, 0) @contextmanager -def switch_source_input(state, content): - # type: (State, StringList) -> Generator[None, None, None] +def switch_source_input(state: State, content: StringList) -> Generator[None, None, None]: """Switch current source input of state temporarily.""" try: # remember the original ``get_source_and_line()`` method @@ -322,13 +296,11 @@ def switch_source_input(state, content): class SphinxFileOutput(FileOutput): """Better FileOutput class for Sphinx.""" - def __init__(self, **kwargs): - # type: (Any) -> None + def __init__(self, **kwargs) -> None: self.overwrite_if_changed = kwargs.pop('overwrite_if_changed', False) super().__init__(**kwargs) - def write(self, data): - # type: (str) -> str + def write(self, data: str) -> str: if (self.destination_path and self.autoclose and 'b' not in self.mode and self.overwrite_if_changed and os.path.exists(self.destination_path)): with open(self.destination_path, encoding=self.encoding) as f: @@ -349,19 +321,16 @@ class SphinxDirective(Directive): """ @property - def env(self): - # type: () -> BuildEnvironment + def env(self) -> "BuildEnvironment": """Reference to the :class:`.BuildEnvironment` object.""" return self.state.document.settings.env @property - def config(self): - # type: () -> Config + def config(self) -> "Config": """Reference to the :class:`.Config` object.""" return self.env.config - def set_source_info(self, node): - # type: (nodes.Node) -> None + def set_source_info(self, node: Node) -> None: """Set source and line number to the node.""" node.source, node.line = self.state_machine.get_source_and_line(self.lineno) @@ -384,8 +353,9 @@ class SphinxRole: content = None #: A list of strings, the directive content for customization #: (from the "role" directive). - def __call__(self, name, rawtext, text, lineno, inliner, options={}, content=[]): - # type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA + def __call__(self, name: str, rawtext: str, text: str, lineno: int, + inliner: Inliner, options: Dict = {}, content: List[str] = [] + ) -> Tuple[List[Node], List[system_message]]: self.rawtext = rawtext self.text = unescape(text) self.lineno = lineno @@ -405,24 +375,20 @@ class SphinxRole: return self.run() - def run(self): - # type: () -> Tuple[List[nodes.Node], List[nodes.system_message]] + def run(self) -> Tuple[List[Node], List[system_message]]: raise NotImplementedError @property - def env(self): - # type: () -> BuildEnvironment + def env(self) -> "BuildEnvironment": """Reference to the :class:`.BuildEnvironment` object.""" return self.inliner.document.settings.env @property - def config(self): - # type: () -> Config + def config(self) -> "Config": """Reference to the :class:`.Config` object.""" return self.env.config - def set_source_info(self, node, lineno=None): - # type: (nodes.Node, int) -> None + def set_source_info(self, node: Node, lineno: int = None) -> None: if lineno is None: lineno = self.lineno @@ -444,8 +410,9 @@ class ReferenceRole(SphinxRole): # \x00 means the "<" was backslash-escaped explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<(.*?)>$', re.DOTALL) - def __call__(self, name, rawtext, text, lineno, inliner, options={}, content=[]): - # type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA + def __call__(self, name: str, rawtext: str, text: str, lineno: int, + inliner: Inliner, options: Dict = {}, content: List[str] = [] + ) -> Tuple[List[Node], List[system_message]]: matched = self.explicit_title_re.match(text) if matched: self.has_explicit_title = True @@ -468,8 +435,7 @@ class SphinxTranslator(nodes.NodeVisitor): This class is strongly coupled with Sphinx. """ - def __init__(self, document, builder): - # type: (nodes.document, Builder) -> None + def __init__(self, document: nodes.document, builder: "Builder") -> None: super().__init__(document) self.builder = builder self.config = builder.config @@ -481,8 +447,7 @@ class SphinxTranslator(nodes.NodeVisitor): __document_cache__ = None # type: nodes.document -def new_document(source_path, settings=None): - # type: (str, Any) -> nodes.document +def new_document(source_path: str, settings: Any = None) -> nodes.document: """Return a new empty document object. This is an alternative of docutils'. This is a simple wrapper for ``docutils.utils.new_document()``. It |