Merge pull request #6534 from tk0miya/refactor_type_annotation_ext

Migrate to py3 style type annotation: sphinx.ext (Part 1)
This commit is contained in:
Takeshi KOMIYA authored and GitHub committed 2019-07-01 01:14:03 +09:00
commit e25d77e999
14 files changed
+308 -506

No files matched your search

+20 -33
View File
@@ -22,6 +22,7 @@ import sys
import warnings
from fnmatch import fnmatch
from os import path
from typing import Any, List, Tuple
import sphinx.locale
from sphinx import __display_version__, package_dir
@@ -32,10 +33,6 @@ from sphinx.util import rst
from sphinx.util.osutil import FileAvoidWrite, ensuredir
from sphinx.util.template import ReSTRenderer
if False:
# For type annotation
from typing import Any, List, Tuple # NOQA
# automodule options
if 'SPHINX_APIDOC_OPTIONS' in os.environ:
OPTIONS = os.environ['SPHINX_APIDOC_OPTIONS'].split(',')
@@ -53,8 +50,7 @@ PY_SUFFIXES = {'.py', '.pyx'}
template_dir = path.join(package_dir, 'templates', 'apidoc')
def makename(package, module):
# type: (str, str) -> str
def makename(package: str, module: str) -> str:
"""Join package and module with a dot."""
warnings.warn('makename() is deprecated.',
RemovedInSphinx40Warning)
@@ -68,14 +64,12 @@ def makename(package, module):
return name
def module_join(*modnames):
# type: (*str) -> str
def module_join(*modnames: str) -> str:
"""Join module names with dots."""
return '.'.join(filter(None, modnames))
def write_file(name, text, opts):
# type: (str, str, Any) -> None
def write_file(name: str, text: str, opts: Any) -> None:
"""Write the output file for module/package <name>."""
fname = path.join(opts.destdir, '%s.%s' % (name, opts.suffix))
if opts.dryrun:
@@ -89,8 +83,7 @@ def write_file(name, text, opts):
f.write(text)
def format_heading(level, text, escape=True):
# type: (int, str, bool) -> str
def format_heading(level: int, text: str, escape: bool = True) -> str:
"""Create a heading of <level> [1, 2 or 3 supported]."""
warnings.warn('format_warning() is deprecated.',
RemovedInSphinx40Warning)
@@ -100,8 +93,7 @@ def format_heading(level, text, escape=True):
return '%s\n%s\n\n' % (text, underlining)
def format_directive(module, package=None):
# type: (str, str) -> str
def format_directive(module: str, package: str = None) -> str:
"""Create the automodule directive and add the options."""
warnings.warn('format_directive() is deprecated.',
RemovedInSphinx40Warning)
@@ -111,8 +103,8 @@ def format_directive(module, package=None):
return directive
def create_module_file(package, basename, opts, user_template_dir=None):
# type: (str, str, Any, str) -> None
def create_module_file(package: str, basename: str, opts: Any,
user_template_dir: str = None) -> None:
"""Build the text of the file and write the file."""
qualname = module_join(package, basename)
context = {
@@ -125,9 +117,9 @@ def create_module_file(package, basename, opts, user_template_dir=None):
write_file(qualname, text, opts)
def create_package_file(root, master_package, subroot, py_files, opts, subs,
is_namespace, excludes=[], user_template_dir=None):
# type: (str, str, str, List[str], Any, List[str], bool, List[str], str) -> None
def create_package_file(root: str, master_package: str, subroot: str, py_files: List[str],
opts: Any, subs: List[str], is_namespace: bool,
excludes: List[str] = [], user_template_dir: str = None) -> None:
"""Build the text of the file and write the file."""
# build a list of sub packages (directories containing an INITPY file)
subpackages = [sub for sub in subs if not
@@ -160,8 +152,8 @@ def create_package_file(root, master_package, subroot, py_files, opts, subs,
create_module_file(None, submodule, opts, user_template_dir)
def create_modules_toc_file(modules, opts, name='modules', user_template_dir=None):
# type: (List[str], Any, str, str) -> None
def create_modules_toc_file(modules: List[str], opts: Any, name: str = 'modules',
user_template_dir: str = None) -> None:
"""Create the module's index."""
modules.sort()
prev_module = ''
@@ -181,8 +173,7 @@ def create_modules_toc_file(modules, opts, name='modules', user_template_dir=Non
write_file(name, text, opts)
def shall_skip(module, opts, excludes=[]):
# type: (str, Any, List[str]) -> bool
def shall_skip(module: str, opts: Any, excludes: List[str] = []) -> bool:
"""Check if we want to skip this module."""
# skip if the file doesn't exist and not using implicit namespaces
if not opts.implicit_namespaces and not path.exists(module):
@@ -208,8 +199,7 @@ def shall_skip(module, opts, excludes=[]):
return False
def is_skipped_module(filename, opts, excludes):
# type: (str, Any, List[str]) -> bool
def is_skipped_module(filename: str, opts: Any, excludes: List[str]) -> bool:
"""Check if we want to skip this module."""
if not path.exists(filename):
# skip if the file doesn't exist
@@ -221,8 +211,8 @@ def is_skipped_module(filename, opts, excludes):
return False
def recurse_tree(rootpath, excludes, opts, user_template_dir=None):
# type: (str, List[str], Any, str) -> List[str]
def recurse_tree(rootpath: str, excludes: List[str], opts: Any,
user_template_dir: str = None) -> List[str]:
"""
Look for every file in the directory tree and create the corresponding
ReST files.
@@ -287,8 +277,7 @@ def recurse_tree(rootpath, excludes, opts, user_template_dir=None):
return toplevels
def is_excluded(root, excludes):
# type: (str, List[str]) -> bool
def is_excluded(root: str, excludes: List[str]) -> bool:
"""Check if the directory is in the exclude list.
Note: by having trailing slashes, we avoid common prefix issues, like
@@ -300,8 +289,7 @@ def is_excluded(root, excludes):
return False
def get_parser():
# type: () -> argparse.ArgumentParser
def get_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
usage='%(prog)s [OPTIONS] -o <OUTPUT_PATH> <MODULE_PATH> '
'[EXCLUDE_PATTERN, ...]',
@@ -396,8 +384,7 @@ Note: By default this script will not overwrite already created files."""))
return parser
def main(argv=sys.argv[1:]):
# type: (List[str]) -> int
def main(argv: List[str] = sys.argv[1:]) -> int:
"""Parse and check the command line arguments."""
sphinx.locale.setlocale(locale.LC_ALL, '')
sphinx.locale.init_console(os.path.join(package_dir, 'locale'), 'sphinx')
+119 -192
View File
@@ -12,15 +12,18 @@
import re
import warnings
from typing import Any
from types import ModuleType
from typing import Any, Callable, Dict, Iterator, List, Sequence, Set, Tuple, Type, Union
from docutils.statemachine import StringList
import sphinx
from sphinx.config import ENUM
from sphinx.application import Sphinx
from sphinx.config import Config, ENUM
from sphinx.deprecation import (
RemovedInSphinx30Warning, RemovedInSphinx40Warning, deprecated_alias
)
from sphinx.environment import BuildEnvironment
from sphinx.ext.autodoc.importer import import_object, get_object_members
from sphinx.ext.autodoc.mock import mock
from sphinx.locale import _, __
@@ -35,12 +38,8 @@ from sphinx.util.inspect import (
if False:
# For type annotation
from types import ModuleType # NOQA
from typing import Callable, Dict, Iterator, List, Sequence, Set, Tuple, Type, Union # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
from sphinx.environment import BuildEnvironment # NOQA
from sphinx.ext.autodoc.directive import DocumenterBridge # NOQA
from sphinx.ext.autodoc.directive import DocumenterBridge
logger = logging.getLogger(__name__)
@@ -61,8 +60,7 @@ py_ext_sig_re = re.compile(
''', re.VERBOSE)
def identity(x):
# type: (Any) -> Any
def identity(x: Any) -> Any:
return x
@@ -71,16 +69,14 @@ INSTANCEATTR = object()
SLOTSATTR = object()
def members_option(arg):
# type: (Any) -> Union[object, List[str]]
def members_option(arg: Any) -> Union[object, List[str]]:
"""Used to convert the :members: option to auto directives."""
if arg is None or arg is True:
return ALL
return [x.strip() for x in arg.split(',')]
def members_set_option(arg):
# type: (Any) -> Union[object, Set[str]]
def members_set_option(arg: Any) -> Union[object, Set[str]]:
"""Used to convert the :members: option to auto directives."""
if arg is None:
return ALL
@@ -90,8 +86,7 @@ def members_set_option(arg):
SUPPRESS = object()
def annotation_option(arg):
# type: (Any) -> Any
def annotation_option(arg: Any) -> Any:
if arg is None:
# suppress showing the representation of the object
return SUPPRESS
@@ -99,16 +94,14 @@ def annotation_option(arg):
return arg
def bool_option(arg):
# type: (Any) -> bool
def bool_option(arg: Any) -> bool:
"""Used to convert flag options to auto directives. (Instead of
directives.flag(), which returns None).
"""
return True
def merge_special_members_option(options):
# type: (Dict) -> None
def merge_special_members_option(options: Dict) -> None:
"""Merge :special-members: option to :members: option."""
if 'special-members' in options and options['special-members'] is not ALL:
if options.get('members') is ALL:
@@ -123,8 +116,7 @@ def merge_special_members_option(options):
# Some useful event listener factories for autodoc-process-docstring.
def cut_lines(pre, post=0, what=None):
# type: (int, int, str) -> Callable
def cut_lines(pre: int, post: int = 0, what: str = None) -> Callable:
"""Return a listener that removes the first *pre* and last *post*
lines of every docstring. If *what* is a sequence of strings,
only docstrings of a type in *what* will be processed.
@@ -136,8 +128,8 @@ def cut_lines(pre, post=0, what=None):
This can (and should) be used in place of :confval:`automodule_skip_lines`.
"""
def process(app, what_, name, obj, options, lines):
# type: (Sphinx, str, str, Any, Any, List[str]) -> None
def process(app: Sphinx, what_: str, name: str, obj: Any, options: Any, lines: List[str]
) -> None:
if what and what_ not in what:
return
del lines[:pre]
@@ -152,8 +144,8 @@ def cut_lines(pre, post=0, what=None):
return process
def between(marker, what=None, keepempty=False, exclude=False):
# type: (str, Sequence[str], bool, bool) -> Callable
def between(marker: str, what: Sequence[str] = None, keepempty: bool = False,
exclude: bool = False) -> Callable:
"""Return a listener that either keeps, or if *exclude* is True excludes,
lines between lines that match the *marker* regular expression. If no line
matches, the resulting docstring would be empty, so no change will be made
@@ -164,8 +156,8 @@ def between(marker, what=None, keepempty=False, exclude=False):
"""
marker_re = re.compile(marker)
def process(app, what_, name, obj, options, lines):
# type: (Sphinx, str, str, Any, Any, List[str]) -> None
def process(app: Sphinx, what_: str, name: str, obj: Any, options: Any, lines: List[str]
) -> None:
if what and what_ not in what:
return
deleted = 0
@@ -192,8 +184,7 @@ def between(marker, what=None, keepempty=False, exclude=False):
# But we define this class here to keep compatibility (see #4538)
class Options(dict):
"""A dict/attribute hybrid that returns None on nonexisting keys."""
def __getattr__(self, name):
# type: (str) -> Any
def __getattr__(self, name: str) -> Any:
try:
return self[name.replace('_', '-')]
except KeyError:
@@ -229,19 +220,17 @@ class Documenter:
option_spec = {'noindex': bool_option} # type: Dict[str, Callable]
def get_attr(self, obj, name, *defargs):
# type: (Any, str, Any) -> Any
def get_attr(self, obj: Any, name: str, *defargs) -> Any:
"""getattr() override for types such as Zope interfaces."""
return autodoc_attrgetter(self.env.app, obj, name, *defargs)
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, str, bool, Any) -> bool
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
"""Called to see if a member can be documented by this documenter."""
raise NotImplementedError('must be implemented in subclasses')
def __init__(self, directive, name, indent=''):
# type: (DocumenterBridge, str, str) -> None
def __init__(self, directive: "DocumenterBridge", name: str, indent: str = '') -> None:
self.directive = directive
self.env = directive.env # type: BuildEnvironment
self.options = directive.genopt
@@ -266,18 +255,16 @@ class Documenter:
self.analyzer = None # type: ModuleAnalyzer
@property
def documenters(self):
# type: () -> Dict[str, Type[Documenter]]
def documenters(self) -> Dict[str, Type["Documenter"]]:
"""Returns registered Documenter classes"""
return get_documenters(self.env.app)
def add_line(self, line, source, *lineno):
# type: (str, str, int) -> None
def add_line(self, line: str, source: str, *lineno: int) -> None:
"""Append one line of generated reST to the output."""
self.directive.result.append(self.indent + line, source, *lineno)
def resolve_name(self, modname, parents, path, base):
# type: (str, Any, str, Any) -> Tuple[str, List[str]]
def resolve_name(self, modname: str, parents: Any, path: str, base: Any
) -> Tuple[str, List[str]]:
"""Resolve the module and name of the object to document given by the
arguments and the current module/class.
@@ -287,8 +274,7 @@ class Documenter:
"""
raise NotImplementedError('must be implemented in subclasses')
def parse_name(self):
# type: () -> bool
def parse_name(self) -> bool:
"""Determine what module to import and what attribute to document.
Returns True and sets *self.modname*, *self.objpath*, *self.fullname*,
@@ -324,8 +310,7 @@ class Documenter:
(self.objpath and '.' + '.'.join(self.objpath) or '')
return True
def import_object(self):
# type: () -> bool
def import_object(self) -> bool:
"""Import the object given by *self.modname* and *self.objpath* and set
it as *self.object*.
@@ -343,8 +328,7 @@ class Documenter:
self.env.note_reread()
return False
def get_real_modname(self):
# type: () -> str
def get_real_modname(self) -> str:
"""Get the real module name of an object to document.
It can differ from the name of the module through which the object was
@@ -352,8 +336,7 @@ class Documenter:
"""
return self.get_attr(self.object, '__module__', None) or self.modname
def check_module(self):
# type: () -> bool
def check_module(self) -> bool:
"""Check if *self.object* is really defined in the module given by
*self.modname*.
"""
@@ -367,16 +350,14 @@ class Documenter:
return False
return True
def format_args(self, **kwargs):
# type: (Any) -> str
def format_args(self, **kwargs) -> str:
"""Format the argument signature of *self.object*.
Should return None if the object does not have a signature.
"""
return None
def format_name(self):
# type: () -> str
def format_name(self) -> str:
"""Format the name of *self.object*.
This normally should be something that can be parsed by the generated
@@ -387,8 +368,7 @@ class Documenter:
# directives of course)
return '.'.join(self.objpath) or self.modname
def format_signature(self, **kwargs):
# type: (Any) -> str
def format_signature(self, **kwargs) -> str:
"""Format the signature (arguments and return annotation) of the object.
Let the user process it via the ``autodoc-process-signature`` event.
@@ -422,8 +402,7 @@ class Documenter:
else:
return ''
def add_directive_header(self, sig):
# type: (str) -> None
def add_directive_header(self, sig: str) -> None:
"""Add the directive header and options to the generated content."""
domain = getattr(self, 'domain', 'py')
directive = getattr(self, 'directivetype', self.objtype)
@@ -438,8 +417,7 @@ class Documenter:
# etc. don't support a prepended module name
self.add_line(' :module: %s' % self.modname, sourcename)
def get_doc(self, encoding=None, ignore=1):
# type: (str, int) -> List[List[str]]
def get_doc(self, encoding: str = None, ignore: int = 1) -> List[List[str]]:
"""Decode and return lines of the docstring(s) for the object."""
if encoding is not None:
warnings.warn("The 'encoding' argument to autodoc.%s.get_doc() is deprecated."
@@ -452,8 +430,7 @@ class Documenter:
return [prepare_docstring(docstring, ignore, tab_width)]
return []
def process_doc(self, docstrings):
# type: (List[List[str]]) -> Iterator[str]
def process_doc(self, docstrings: List[List[str]]) -> Iterator[str]:
"""Let the user process the docstrings before adding them."""
for docstringlines in docstrings:
if self.env.app:
@@ -463,14 +440,12 @@ class Documenter:
self.options, docstringlines)
yield from docstringlines
def get_sourcename(self):
# type: () -> str
def get_sourcename(self) -> str:
if self.analyzer:
return '%s:docstring of %s' % (self.analyzer.srcname, self.fullname)
return 'docstring of %s' % self.fullname
def add_content(self, more_content, no_docstring=False):
# type: (Any, bool) -> None
def add_content(self, more_content: Any, no_docstring: bool = False) -> None:
"""Add content from docstrings, attribute documentation and user."""
# set sourcename and add content from attribute documentation
sourcename = self.get_sourcename()
@@ -500,8 +475,7 @@ class Documenter:
for line, src in zip(more_content.data, more_content.items):
self.add_line(line, src[0], src[1])
def get_object_members(self, want_all):
# type: (bool) -> Tuple[bool, List[Tuple[str, Any]]]
def get_object_members(self, want_all: bool) -> Tuple[bool, List[Tuple[str, Any]]]:
"""Return `(members_check_module, members)` where `members` is a
list of `(membername, member)` pairs of the members of *self.object*.
@@ -527,8 +501,8 @@ class Documenter:
return False, sorted((m.name, m.value) for m in members.values()
if m.directly_defined)
def filter_members(self, members, want_all):
# type: (List[Tuple[str, Any]], bool) -> List[Tuple[str, Any, bool]]
def filter_members(self, members: List[Tuple[str, Any]], want_all: bool
) -> List[Tuple[str, Any, bool]]:
"""Filter the given member list.
Members are skipped if
@@ -616,8 +590,7 @@ class Documenter:
return ret
def document_members(self, all_members=False):
# type: (bool) -> None
def document_members(self, all_members: bool = False) -> None:
"""Generate reST for member documentation.
If *all_members* is True, do all members, else those given by
@@ -669,8 +642,7 @@ class Documenter:
# sort by source order, by virtue of the module analyzer
tagorder = self.analyzer.tagorder
def keyfunc(entry):
# type: (Tuple[Documenter, bool]) -> int
def keyfunc(entry: Tuple[Documenter, bool]) -> int:
fullname = entry[0].name.split('::')[1]
return tagorder.get(fullname, len(tagorder))
memberdocumenters.sort(key=keyfunc)
@@ -684,9 +656,8 @@ class Documenter:
self.env.temp_data['autodoc:module'] = None
self.env.temp_data['autodoc:class'] = None
def generate(self, more_content=None, real_modname=None,
check_module=False, all_members=False):
# type: (Any, str, bool, bool) -> None
def generate(self, more_content: Any = None, real_modname: str = None,
check_module: bool = False, all_members: bool = False) -> None:
"""Generate reST for the object given by *self.name*, and possibly for
its members.
@@ -778,26 +749,24 @@ class ModuleDocumenter(Documenter):
'imported-members': bool_option, 'ignore-module-all': bool_option
} # type: Dict[str, Callable]
def __init__(self, *args):
# type: (Any) -> None
def __init__(self, *args) -> None:
super().__init__(*args)
merge_special_members_option(self.options)
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, str, bool, Any) -> bool
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
# don't document submodules automatically
return False
def resolve_name(self, modname, parents, path, base):
# type: (str, Any, str, Any) -> Tuple[str, List[str]]
def resolve_name(self, modname: str, parents: Any, path: str, base: Any
) -> Tuple[str, List[str]]:
if modname is not None:
logger.warning(__('"::" in automodule name doesn\'t make sense'),
type='autodoc')
return (path or '') + base, []
def parse_name(self):
# type: () -> bool
def parse_name(self) -> bool:
ret = super().parse_name()
if self.args or self.retann:
logger.warning(__('signature arguments or return annotation '
@@ -805,8 +774,7 @@ class ModuleDocumenter(Documenter):
type='autodoc')
return ret
def add_directive_header(self, sig):
# type: (str) -> None
def add_directive_header(self, sig: str) -> None:
Documenter.add_directive_header(self, sig)
sourcename = self.get_sourcename()
@@ -819,8 +787,7 @@ class ModuleDocumenter(Documenter):
if self.options.deprecated:
self.add_line(' :deprecated:', sourcename)
def get_object_members(self, want_all):
# type: (bool) -> Tuple[bool, List[Tuple[str, object]]]
def get_object_members(self, want_all: bool) -> Tuple[bool, List[Tuple[str, object]]]:
if want_all:
if (self.options.ignore_module_all or not
hasattr(self.object, '__all__')):
@@ -861,8 +828,8 @@ class ModuleLevelDocumenter(Documenter):
Specialized Documenter subclass for objects on module level (functions,
classes, data/constants).
"""
def resolve_name(self, modname, parents, path, base):
# type: (str, Any, str, Any) -> Tuple[str, List[str]]
def resolve_name(self, modname: str, parents: Any, path: str, base: Any
) -> Tuple[str, List[str]]:
if modname is None:
if path:
modname = path.rstrip('.')
@@ -882,8 +849,8 @@ class ClassLevelDocumenter(Documenter):
Specialized Documenter subclass for objects on class level (methods,
attributes).
"""
def resolve_name(self, modname, parents, path, base):
# type: (str, Any, str, Any) -> Tuple[str, List[str]]
def resolve_name(self, modname: str, parents: Any, path: str, base: Any
) -> Tuple[str, List[str]]:
if modname is None:
if path:
mod_cls = path.rstrip('.')
@@ -916,8 +883,7 @@ class DocstringSignatureMixin:
feature of reading the signature from the docstring.
"""
def _find_signature(self, encoding=None):
# type: (str) -> Tuple[str, str]
def _find_signature(self, encoding: str = None) -> Tuple[str, str]:
if encoding is not None:
warnings.warn("The 'encoding' argument to autodoc.%s._find_signature() is "
"deprecated." % self.__class__.__name__,
@@ -951,8 +917,7 @@ class DocstringSignatureMixin:
break
return result
def get_doc(self, encoding=None, ignore=1):
# type: (str, int) -> List[List[str]]
def get_doc(self, encoding: str = None, ignore: int = 1) -> List[List[str]]:
if encoding is not None:
warnings.warn("The 'encoding' argument to autodoc.%s.get_doc() is deprecated."
% self.__class__.__name__,
@@ -962,8 +927,7 @@ class DocstringSignatureMixin:
return lines
return super().get_doc(None, ignore) # type: ignore
def format_signature(self, **kwargs):
# type: (Any) -> str
def format_signature(self, **kwargs) -> str:
if self.args is None and self.env.config.autodoc_docstring_signature: # type: ignore
# only act if a signature is not explicitly given already, and if
# the feature is enabled
@@ -978,8 +942,7 @@ class DocstringStripSignatureMixin(DocstringSignatureMixin):
Mixin for AttributeDocumenter to provide the
feature of stripping any function signature from the docstring.
"""
def format_signature(self, **kwargs):
# type: (Any) -> str
def format_signature(self, **kwargs) -> str:
if self.args is None and self.env.config.autodoc_docstring_signature: # type: ignore
# only act if a signature is not explicitly given already, and if
# the feature is enabled
@@ -1000,14 +963,13 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
member_order = 30
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, str, bool, Any) -> bool
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
# supports functions, builtins and bound methods exported at the module level
return (inspect.isfunction(member) or inspect.isbuiltin(member) or
(inspect.isroutine(member) and isinstance(parent, ModuleDocumenter)))
def format_args(self, **kwargs):
# type: (Any) -> str
def format_args(self, **kwargs) -> str:
if self.env.config.autodoc_typehints == 'none':
kwargs.setdefault('show_annotation', False)
@@ -1042,12 +1004,10 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
args = args.replace('\\', '\\\\')
return args
def document_members(self, all_members=False):
# type: (bool) -> None
def document_members(self, all_members: bool = False) -> None:
pass
def add_directive_header(self, sig):
# type: (str) -> None
def add_directive_header(self, sig: str) -> None:
sourcename = self.get_sourcename()
super().add_directive_header(sig)
@@ -1086,18 +1046,16 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
'private-members': bool_option, 'special-members': members_option,
} # type: Dict[str, Callable]
def __init__(self, *args):
# type: (Any) -> None
def __init__(self, *args) -> None:
super().__init__(*args)
merge_special_members_option(self.options)
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, str, bool, Any) -> bool
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
return isinstance(member, type)
def import_object(self):
# type: () -> Any
def import_object(self) -> Any:
ret = super().import_object()
# if the class is documented under another name, document it
# as data/attribute
@@ -1108,8 +1066,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
self.doc_as_attr = True
return ret
def format_args(self, **kwargs):
# type: (Any) -> str
def format_args(self, **kwargs) -> str:
if self.env.config.autodoc_typehints == 'none':
kwargs.setdefault('show_annotation', False)
@@ -1129,15 +1086,13 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
# with __init__ in C
return None
def format_signature(self, **kwargs):
# type: (Any) -> str
def format_signature(self, **kwargs) -> str:
if self.doc_as_attr:
return ''
return super().format_signature(**kwargs)
def add_directive_header(self, sig):
# type: (str) -> None
def add_directive_header(self, sig: str) -> None:
if self.doc_as_attr:
self.directivetype = 'attribute'
super().add_directive_header(sig)
@@ -1154,8 +1109,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
self.add_line(' ' + _('Bases: %s') % ', '.join(bases),
sourcename)
def get_doc(self, encoding=None, ignore=1):
# type: (str, int) -> List[List[str]]
def get_doc(self, encoding: str = None, ignore: int = 1) -> List[List[str]]:
if encoding is not None:
warnings.warn("The 'encoding' argument to autodoc.%s.get_doc() is deprecated."
% self.__class__.__name__,
@@ -1199,8 +1153,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
tab_width = self.directive.state.document.settings.tab_width
return [prepare_docstring(docstring, ignore, tab_width) for docstring in docstrings]
def add_content(self, more_content, no_docstring=False):
# type: (Any, bool) -> None
def add_content(self, more_content: Any, no_docstring: bool = False) -> None:
if self.doc_as_attr:
classname = safe_getattr(self.object, '__qualname__', None)
if not classname:
@@ -1215,15 +1168,13 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
else:
super().add_content(more_content)
def document_members(self, all_members=False):
# type: (bool) -> None
def document_members(self, all_members: bool = False) -> None:
if self.doc_as_attr:
return
super().document_members(all_members)
def generate(self, more_content=None, real_modname=None,
check_module=False, all_members=False):
# type: (Any, str, bool, bool) -> None
def generate(self, more_content: Any = None, real_modname: str = None,
check_module: bool = False, all_members: bool = False) -> None:
# Do not pass real_modname and use the name from the __module__
# attribute of the class.
# If a class gets imported into the module real_modname
@@ -1245,8 +1196,8 @@ class ExceptionDocumenter(ClassDocumenter):
priority = 10
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, str, bool, Any) -> bool
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
return isinstance(member, type) and issubclass(member, BaseException)
@@ -1261,12 +1212,11 @@ class DataDocumenter(ModuleLevelDocumenter):
option_spec["annotation"] = annotation_option
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, str, bool, Any) -> bool
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
return isinstance(parent, ModuleDocumenter) and isattr
def add_directive_header(self, sig):
# type: (str) -> None
def add_directive_header(self, sig: str) -> None:
super().add_directive_header(sig)
sourcename = self.get_sourcename()
if not self.options.annotation:
@@ -1282,12 +1232,10 @@ class DataDocumenter(ModuleLevelDocumenter):
self.add_line(' :annotation: %s' % self.options.annotation,
sourcename)
def document_members(self, all_members=False):
# type: (bool) -> None
def document_members(self, all_members: bool = False) -> None:
pass
def get_real_modname(self):
# type: () -> str
def get_real_modname(self) -> str:
return self.get_attr(self.parent or self.object, '__module__', None) \
or self.modname
@@ -1302,13 +1250,12 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
priority = 1 # must be more than FunctionDocumenter
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, str, bool, Any) -> bool
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
return inspect.isroutine(member) and \
not isinstance(parent, ModuleDocumenter)
def import_object(self):
# type: () -> Any
def import_object(self) -> Any:
ret = super().import_object()
if not ret:
return ret
@@ -1325,8 +1272,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
return ret
def format_args(self, **kwargs):
# type: (Any) -> str
def format_args(self, **kwargs) -> str:
if self.env.config.autodoc_typehints == 'none':
kwargs.setdefault('show_annotation', False)
@@ -1341,8 +1287,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
args = args.replace('\\', '\\\\')
return args
def add_directive_header(self, sig):
# type: (str) -> None
def add_directive_header(self, sig) -> None:
super().add_directive_header(sig)
sourcename = self.get_sourcename()
@@ -1356,8 +1301,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
if inspect.isstaticmethod(obj, cls=self.parent, name=self.object_name):
self.add_line(' :staticmethod:', sourcename)
def document_members(self, all_members=False):
# type: (bool) -> None
def document_members(self, all_members: bool = False) -> None:
pass
@@ -1375,13 +1319,12 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
priority = 10
@staticmethod
def is_function_or_method(obj):
# type: (Any) -> bool
def is_function_or_method(obj: Any) -> bool:
return inspect.isfunction(obj) or inspect.isbuiltin(obj) or inspect.ismethod(obj)
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, str, bool, Any) -> bool
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
if inspect.isattributedescriptor(member):
return True
elif (not isinstance(parent, ModuleDocumenter) and
@@ -1391,12 +1334,10 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
else:
return False
def document_members(self, all_members=False):
# type: (bool) -> None
def document_members(self, all_members: bool = False) -> None:
pass
def import_object(self):
# type: () -> Any
def import_object(self) -> Any:
ret = super().import_object()
if inspect.isenumattribute(self.object):
self.object = self.object.value
@@ -1407,13 +1348,11 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
self._datadescriptor = False
return ret
def get_real_modname(self):
# type: () -> str
def get_real_modname(self) -> str:
return self.get_attr(self.parent or self.object, '__module__', None) \
or self.modname
def add_directive_header(self, sig):
# type: (str) -> None
def add_directive_header(self, sig: str) -> None:
super().add_directive_header(sig)
sourcename = self.get_sourcename()
if not self.options.annotation:
@@ -1429,8 +1368,7 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
else:
self.add_line(' :annotation: %s' % self.options.annotation, sourcename)
def add_content(self, more_content, no_docstring=False):
# type: (Any, bool) -> None
def add_content(self, more_content: Any, no_docstring: bool = False) -> None:
if not self._datadescriptor:
# if it's not a data descriptor, its docstring is very probably the
# wrong thing to display
@@ -1450,21 +1388,18 @@ class PropertyDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): #
priority = AttributeDocumenter.priority + 1
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, str, bool, Any) -> bool
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
return inspect.isproperty(member) and isinstance(parent, ClassDocumenter)
def document_members(self, all_members=False):
# type: (bool) -> None
def document_members(self, all_members: bool = False) -> None:
pass
def get_real_modname(self):
# type: () -> str
def get_real_modname(self) -> str:
return self.get_attr(self.parent or self.object, '__module__', None) \
or self.modname
def add_directive_header(self, sig):
# type: (str) -> None
def add_directive_header(self, sig: str) -> None:
super().add_directive_header(sig)
sourcename = self.get_sourcename()
if inspect.isabstractmethod(self.object):
@@ -1485,21 +1420,19 @@ class InstanceAttributeDocumenter(AttributeDocumenter):
priority = 11
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, str, bool, Any) -> bool
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
"""This documents only INSTANCEATTR members."""
return isattr and (member is INSTANCEATTR)
def import_object(self):
# type: () -> bool
def import_object(self) -> bool:
"""Never import anything."""
# disguise as an attribute
self.objtype = 'attribute'
self._datadescriptor = False
return True
def add_content(self, more_content, no_docstring=False):
# type: (Any, bool) -> None
def add_content(self, more_content: Any, no_docstring: bool = False) -> None:
"""Never try to get a docstring from the object."""
super().add_content(more_content, no_docstring=True)
@@ -1517,13 +1450,12 @@ class SlotsAttributeDocumenter(AttributeDocumenter):
priority = 11
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, str, bool, Any) -> bool
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
"""This documents only SLOTSATTR members."""
return member is SLOTSATTR
def import_object(self):
# type: () -> bool
def import_object(self) -> Any:
"""Never import anything."""
# disguise as an attribute
self.objtype = 'attribute'
@@ -1541,8 +1473,7 @@ class SlotsAttributeDocumenter(AttributeDocumenter):
self.env.note_reread()
return False
def get_doc(self, encoding=None, ignore=1):
# type: (str, int) -> List[List[str]]
def get_doc(self, encoding: str = None, ignore: int = 1) -> List[List[str]]:
"""Decode and return lines of the docstring(s) for the object."""
name = self.objpath[-1]
__slots__ = safe_getattr(self.parent, '__slots__', [])
@@ -1553,14 +1484,12 @@ class SlotsAttributeDocumenter(AttributeDocumenter):
return []
def get_documenters(app):
# type: (Sphinx) -> Dict[str, Type[Documenter]]
def get_documenters(app: Sphinx) -> Dict[str, Type[Documenter]]:
"""Returns registered Documenter classes"""
return app.registry.documenters
def autodoc_attrgetter(app, obj, name, *defargs):
# type: (Sphinx, Any, str, Any) -> Any
def autodoc_attrgetter(app: Sphinx, obj: Any, name: str, *defargs) -> Any:
"""Alternative getattr() for types"""
for typ, func in app.registry.autodoc_attrgettrs.items():
if isinstance(obj, typ):
@@ -1569,8 +1498,7 @@ def autodoc_attrgetter(app, obj, name, *defargs):
return safe_getattr(obj, name, *defargs)
def merge_autodoc_default_flags(app, config):
# type: (Sphinx, Config) -> None
def merge_autodoc_default_flags(app: Sphinx, config: Config) -> None:
"""This merges the autodoc_default_flags to autodoc_default_options."""
if not config.autodoc_default_flags:
return
@@ -1602,8 +1530,7 @@ deprecated_alias('sphinx.ext.autodoc',
RemovedInSphinx40Warning)
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_autodocumenter(ModuleDocumenter)
app.add_autodocumenter(ClassDocumenter)
app.add_autodocumenter(ExceptionDocumenter)
+18 -27
View File
@@ -7,27 +7,22 @@
"""
import warnings
from typing import Any, Callable, Dict, List, Set, Type
from docutils import nodes
from docutils.parsers.rst.states import Struct
from docutils.nodes import Element, Node
from docutils.parsers.rst.states import RSTState, Struct
from docutils.statemachine import StringList
from docutils.utils import assemble_option_dict
from docutils.utils import Reporter, assemble_option_dict
from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.ext.autodoc import Options, get_documenters
from sphinx.environment import BuildEnvironment
from sphinx.ext.autodoc import Documenter, Options, get_documenters
from sphinx.util import logging
from sphinx.util.docutils import SphinxDirective, switch_source_input
from sphinx.util.nodes import nested_parse_with_titles
if False:
# For type annotation
from typing import Any, Callable, Dict, List, Set, Type # NOQA
from docutils.parsers.rst.state import RSTState # NOQA
from docutils.utils import Reporter # NOQA
from sphinx.config import Config # NOQA
from sphinx.environment import BuildEnvironment # NOQA
from sphinx.ext.autodoc import Documenter # NOQA
logger = logging.getLogger(__name__)
@@ -41,21 +36,19 @@ AUTODOC_DEFAULT_OPTIONS = ['members', 'undoc-members', 'inherited-members',
class DummyOptionSpec(dict):
"""An option_spec allows any options."""
def __bool__(self):
# type: () -> bool
def __bool__(self) -> bool:
"""Behaves like some options are defined."""
return True
def __getitem__(self, key):
# type: (str) -> Callable[[str], str]
def __getitem__(self, key: str) -> Callable[[str], str]:
return lambda x: x
class DocumenterBridge:
"""A parameters container for Documenters."""
def __init__(self, env, reporter, options, lineno, state=None):
# type: (BuildEnvironment, Reporter, Options, int, Any) -> None
def __init__(self, env: BuildEnvironment, reporter: Reporter, options: Options,
lineno: int, state: Any = None) -> None:
self.env = env
self.reporter = reporter
self.genopt = options
@@ -73,13 +66,12 @@ class DocumenterBridge:
document = Struct(settings=settings)
self.state = Struct(document=document)
def warn(self, msg):
# type: (str) -> None
def warn(self, msg: str) -> None:
logger.warning(msg, location=(self.env.docname, self.lineno))
def process_documenter_options(documenter, config, options):
# type: (Type[Documenter], Config, Dict) -> Options
def process_documenter_options(documenter: Type[Documenter], config: Config, options: Dict
) -> Options:
"""Recognize options of Documenter from user input."""
for name in AUTODOC_DEFAULT_OPTIONS:
if name not in documenter.option_spec:
@@ -92,12 +84,12 @@ def process_documenter_options(documenter, config, options):
return Options(assemble_option_dict(options.items(), documenter.option_spec))
def parse_generated_content(state, content, documenter):
# type: (RSTState, StringList, Documenter) -> List[nodes.Node]
def parse_generated_content(state: RSTState, content: StringList, documenter: Documenter
) -> List[Node]:
"""Parse a generated content by Documenter."""
with switch_source_input(state, content):
if documenter.titles_allowed:
node = nodes.section() # type: nodes.Element
node = nodes.section() # type: Element
# necessary so that the child nodes get the right source/line set
node.document = state.document
nested_parse_with_titles(state, content, node)
@@ -121,8 +113,7 @@ class AutodocDirective(SphinxDirective):
optional_arguments = 0
final_argument_whitespace = True
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
reporter = self.state.document.reporter
try:
+7 -10
View File
@@ -12,20 +12,16 @@ import sys
import traceback
import warnings
from collections import namedtuple
from typing import Any, Callable, Dict, List
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
from sphinx.util import logging
from sphinx.util.inspect import isclass, isenumclass, safe_getattr
if False:
# For type annotation
from typing import Any, Callable, Dict, List # NOQA
logger = logging.getLogger(__name__)
def import_module(modname, warningiserror=False):
# type: (str, bool) -> Any
def import_module(modname: str, warningiserror: bool = False) -> Any:
"""
Call __import__(modname), convert exceptions to ImportError
"""
@@ -41,8 +37,9 @@ def import_module(modname, warningiserror=False):
raise ImportError(exc, traceback.format_exc())
def import_object(modname, objpath, objtype='', attrgetter=safe_getattr, warningiserror=False):
# type: (str, List[str], str, Callable[[Any, str], Any], bool) -> Any
def import_object(modname: str, objpath: List[str], objtype: str = '',
attrgetter: Callable[[Any, str], Any] = safe_getattr,
warningiserror: bool = False) -> Any:
if objpath:
logger.debug('[autodoc] from %s import %s', modname, '.'.join(objpath))
else:
@@ -108,8 +105,8 @@ def import_object(modname, objpath, objtype='', attrgetter=safe_getattr, warning
Attribute = namedtuple('Attribute', ['name', 'directly_defined', 'value'])
def get_object_members(subject, objpath, attrgetter, analyzer=None):
# type: (Any, List[str], Callable, Any) -> Dict[str, Attribute] # NOQA
def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable,
analyzer: Any = None) -> Dict[str, Attribute]:
"""Get members and attributes of target object."""
# the members directly defined in the class
obj_dict = attrgetter(subject, '__dict__', {})
+28 -54
View File
@@ -15,14 +15,11 @@ import warnings
from importlib.abc import Loader, MetaPathFinder
from importlib.machinery import ModuleSpec
from types import FunctionType, MethodType, ModuleType
from typing import Any, Generator, Iterator, List, Sequence, Tuple, Union
from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.util import logging
if False:
# For type annotation
from typing import Any, Generator, Iterator, List, Sequence, Tuple, Union # NOQA
logger = logging.getLogger(__name__)
@@ -31,8 +28,7 @@ class _MockObject:
__display_name__ = '_MockObject'
def __new__(cls, *args, **kwargs):
# type: (Any, Any) -> Any
def __new__(cls, *args, **kwargs) -> Any:
if len(args) == 3 and isinstance(args[1], tuple):
superclass = args[1][-1].__class__
if superclass is cls:
@@ -42,48 +38,39 @@ class _MockObject:
return super().__new__(cls)
def __init__(self, *args, **kwargs):
# type: (Any, Any) -> None
def __init__(self, *args, **kwargs) -> None:
self.__qualname__ = ''
def __len__(self):
# type: () -> int
def __len__(self) -> int:
return 0
def __contains__(self, key):
# type: (str) -> bool
def __contains__(self, key: str) -> bool:
return False
def __iter__(self):
# type: () -> Iterator
def __iter__(self) -> Iterator:
return iter([])
def __mro_entries__(self, bases):
# type: (Tuple) -> Tuple
def __mro_entries__(self, bases: Tuple) -> Tuple:
return (self.__class__,)
def __getitem__(self, key):
# type: (str) -> _MockObject
def __getitem__(self, key: str) -> "_MockObject":
return _make_subclass(key, self.__display_name__, self.__class__)()
def __getattr__(self, key):
# type: (str) -> _MockObject
def __getattr__(self, key: str) -> "_MockObject":
return _make_subclass(key, self.__display_name__, self.__class__)()
def __call__(self, *args, **kw):
# type: (Any, Any) -> Any
def __call__(self, *args, **kw) -> Any:
if args and type(args[0]) in [FunctionType, MethodType]:
# Appears to be a decorator, pass through unchanged
return args[0]
return self
def __repr__(self):
# type: () -> str
def __repr__(self) -> str:
return self.__display_name__
def _make_subclass(name, module, superclass=_MockObject, attributes=None):
# type: (str, str, Any, dict) -> Any
def _make_subclass(name: str, module: str, superclass: Any = _MockObject,
attributes: Any = None) -> Any:
attrs = {'__module__': module, '__display_name__': module + '.' + name}
attrs.update(attributes or {})
@@ -94,8 +81,7 @@ class _MockModule(ModuleType):
"""Used by autodoc_mock_imports."""
__file__ = os.devnull
def __init__(self, name, loader=None):
# type: (str, _MockImporter) -> None
def __init__(self, name: str, loader: "_MockImporter" = None) -> None:
super().__init__(name)
self.__all__ = [] # type: List[str]
self.__path__ = [] # type: List[str]
@@ -104,18 +90,15 @@ class _MockModule(ModuleType):
warnings.warn('The loader argument for _MockModule is deprecated.',
RemovedInSphinx30Warning)
def __getattr__(self, name):
# type: (str) -> _MockObject
def __getattr__(self, name: str) -> _MockObject:
return _make_subclass(name, self.__name__)()
def __repr__(self):
# type: () -> str
def __repr__(self) -> str:
return self.__name__
class _MockImporter(MetaPathFinder):
def __init__(self, names):
# type: (List[str]) -> None
def __init__(self, names: List[str]) -> None:
self.names = names
self.mocked_modules = [] # type: List[str]
# enable hook by adding itself to meta_path
@@ -124,8 +107,7 @@ class _MockImporter(MetaPathFinder):
warnings.warn('_MockImporter is now deprecated.',
RemovedInSphinx30Warning)
def disable(self):
# type: () -> None
def disable(self) -> None:
# remove `self` from `sys.meta_path` to disable import hook
sys.meta_path = [i for i in sys.meta_path if i is not self]
# remove mocked modules from sys.modules to avoid side effects after
@@ -134,16 +116,14 @@ class _MockImporter(MetaPathFinder):
if m in sys.modules:
del sys.modules[m]
def find_module(self, name, path=None):
# type: (str, Sequence[Union[bytes, str]]) -> Any
def find_module(self, name: str, path: Sequence[Union[bytes, str]] = None) -> Any:
# check if name is (or is a descendant of) one of our base_packages
for n in self.names:
if n == name or name.startswith(n + '.'):
return self
return None
def load_module(self, name):
# type: (str) -> ModuleType
def load_module(self, name: str) -> ModuleType:
if name in sys.modules:
# module has already been imported, return it
return sys.modules[name]
@@ -157,34 +137,30 @@ class _MockImporter(MetaPathFinder):
class MockLoader(Loader):
"""A loader for mocking."""
def __init__(self, finder):
# type: (MockFinder) -> None
def __init__(self, finder: "MockFinder") -> None:
super().__init__()
self.finder = finder
def create_module(self, spec):
# type: (ModuleSpec) -> ModuleType
def create_module(self, spec: ModuleSpec) -> ModuleType:
logger.debug('[autodoc] adding a mock module as %s!', spec.name)
self.finder.mocked_modules.append(spec.name)
return _MockModule(spec.name)
def exec_module(self, module):
# type: (ModuleType) -> None
def exec_module(self, module: ModuleType) -> None:
pass # nothing to do
class MockFinder(MetaPathFinder):
"""A finder for mocking."""
def __init__(self, modnames):
# type: (List[str]) -> None
def __init__(self, modnames: List[str]) -> None:
super().__init__()
self.modnames = modnames
self.loader = MockLoader(self)
self.mocked_modules = [] # type: List[str]
def find_spec(self, fullname, path, target=None):
# type: (str, Sequence[Union[bytes, str]], ModuleType) -> ModuleSpec
def find_spec(self, fullname: str, path: Sequence[Union[bytes, str]],
target: ModuleType = None) -> ModuleSpec:
for modname in self.modnames:
# check if fullname is (or is a descendant of) one of our targets
if modname == fullname or fullname.startswith(modname + '.'):
@@ -192,16 +168,14 @@ class MockFinder(MetaPathFinder):
return None
def invalidate_caches(self):
# type: () -> None
def invalidate_caches(self) -> None:
"""Invalidate mocked modules on sys.modules."""
for modname in self.mocked_modules:
sys.modules.pop(modname, None)
@contextlib.contextmanager
def mock(modnames):
# type: (List[str]) -> Generator[None, None, None]
def mock(modnames: List[str]) -> Generator[None, None, None]:
"""Insert mock modules during context::
with mock(['target.module.name']):
+13 -27
View File
@@ -14,30 +14,25 @@ import inspect
import pickle
import re
from os import path
from typing import Any, Dict, IO, List, Pattern, Set, Tuple
import sphinx
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.inspect import safe_getattr
if False:
# For type annotation
from typing import Any, Dict, IO, List, Pattern, Set, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
logger = logging.getLogger(__name__)
# utility
def write_header(f, text, char='-'):
# type:(IO, str, str) -> None
def write_header(f: IO, text: str, char: str = '-') -> None:
f.write(text + '\n')
f.write(char * len(text) + '\n')
def compile_regex_list(name, exps):
# type: (str, str) -> List[Pattern]
def compile_regex_list(name: str, exps: str) -> List[Pattern]:
lst = []
for exp in exps:
try:
@@ -55,8 +50,7 @@ class CoverageBuilder(Builder):
epilog = __('Testing of coverage in the sources finished, look at the '
'results in %(outdir)s' + path.sep + 'python.txt.')
def init(self):
# type: () -> None
def init(self) -> None:
self.c_sourcefiles = [] # type: List[str]
for pattern in self.config.coverage_c_path:
pattern = path.join(self.srcdir, pattern)
@@ -82,12 +76,10 @@ class CoverageBuilder(Builder):
self.py_ignorexps = compile_regex_list('coverage_ignore_pyobjects',
self.config.coverage_ignore_pyobjects)
def get_outdated_docs(self):
# type: () -> str
def get_outdated_docs(self) -> str:
return 'coverage overview'
def write(self, *ignored):
# type: (Any) -> None
def write(self, *ignored) -> None:
self.py_undoc = {} # type: Dict[str, Dict[str, Any]]
self.build_py_coverage()
self.write_py_coverage()
@@ -96,8 +88,7 @@ class CoverageBuilder(Builder):
self.build_c_coverage()
self.write_c_coverage()
def build_c_coverage(self):
# type: () -> None
def build_c_coverage(self) -> None:
# Fetch all the info from the header files
c_objects = self.env.domaindata['c']['objects']
for filename in self.c_sourcefiles:
@@ -118,8 +109,7 @@ class CoverageBuilder(Builder):
if undoc:
self.c_undoc[filename] = undoc
def write_c_coverage(self):
# type: () -> None
def write_c_coverage(self) -> None:
output_file = path.join(self.outdir, 'c.txt')
with open(output_file, 'w') as op:
if self.config.coverage_write_headline:
@@ -138,8 +128,7 @@ class CoverageBuilder(Builder):
return True
return False
def build_py_coverage(self):
# type: () -> None
def build_py_coverage(self) -> None:
objects = self.env.domaindata['py']['objects']
modules = self.env.domaindata['py']['modules']
@@ -230,8 +219,7 @@ class CoverageBuilder(Builder):
self.py_undoc[mod_name] = {'funcs': funcs, 'classes': classes}
def write_py_coverage(self):
# type: () -> None
def write_py_coverage(self) -> None:
output_file = path.join(self.outdir, 'python.txt')
failed = []
with open(output_file, 'w') as op:
@@ -266,16 +254,14 @@ class CoverageBuilder(Builder):
write_header(op, 'Modules that failed to import')
op.writelines(' * %s -- %s\n' % x for x in failed)
def finish(self):
# type: () -> None
def finish(self) -> None:
# dump the coverage data to a pickle file too
picklepath = path.join(self.outdir, 'undoc.pickle')
with open(picklepath, 'wb') as dumpfile:
pickle.dump((self.py_undoc, self.c_undoc), dumpfile)
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(CoverageBuilder)
app.add_config_value('coverage_ignore_modules', [], False)
app.add_config_value('coverage_ignore_functions', [], False)
+12 -15
View File
@@ -23,23 +23,22 @@
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict, List, Tuple
from docutils import nodes, utils
from docutils.nodes import Node, system_message
from docutils.parsers.rst.states import Inliner
import sphinx
from sphinx.application import Sphinx
from sphinx.util.nodes import split_explicit_title
if False:
# For type annotation
from typing import Any, Dict, List, Tuple # NOQA
from docutils.parsers.rst.states import Inliner # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.util.typing import RoleFunction # NOQA
from sphinx.util.typing import RoleFunction
def make_link_role(base_url, prefix):
# type: (str, str) -> RoleFunction
def role(typ, 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 make_link_role(base_url: str, prefix: str) -> RoleFunction:
def role(typ: str, rawtext: str, text: str, lineno: int,
inliner: Inliner, options: Dict = {}, content: List[str] = []
) -> Tuple[List[Node], List[system_message]]:
text = utils.unescape(text)
has_explicit_title, title, part = split_explicit_title(text)
try:
@@ -60,14 +59,12 @@ def make_link_role(base_url, prefix):
return role
def setup_link_roles(app):
# type: (Sphinx) -> None
def setup_link_roles(app: Sphinx) -> None:
for name, (base_url, prefix) in app.config.extlinks.items():
app.add_role(name, make_link_role(base_url, prefix))
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value('extlinks', {}, 'env')
app.connect('builder-inited', setup_link_roles)
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
+5 -10
View File
@@ -10,18 +10,14 @@
import os
import urllib
from typing import Any, Dict
import sphinx
if False:
# For type annotation
from typing import Any, Dict # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.environment import BuildEnvironment # NOQA
from sphinx.application import Sphinx
from sphinx.environment import BuildEnvironment
def create_nojekyll_and_cname(app, env):
# type: (Sphinx, BuildEnvironment) -> None
def create_nojekyll_and_cname(app: Sphinx, env: BuildEnvironment) -> None:
if app.builder.format == 'html':
open(os.path.join(app.builder.outdir, '.nojekyll'), 'wt').close()
@@ -35,7 +31,6 @@ def create_nojekyll_and_cname(app, env):
f.write(domain)
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.connect('env-updated', create_nojekyll_and_cname)
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
+33 -51
View File
@@ -15,31 +15,27 @@ import subprocess
from hashlib import sha1
from os import path
from subprocess import CalledProcessError, PIPE
from typing import Any, Dict, List, Tuple
from docutils import nodes
from docutils.parsers.rst import directives
from docutils.nodes import Node
from docutils.parsers.rst import Directive, directives
import sphinx
from sphinx.application import Sphinx
from sphinx.errors import SphinxError
from sphinx.locale import _, __
from sphinx.util import logging
from sphinx.util.docutils import SphinxDirective
from sphinx.util.docutils import SphinxDirective, SphinxTranslator
from sphinx.util.fileutil import copy_asset
from sphinx.util.i18n import search_image_for_language
from sphinx.util.nodes import set_source_info
from sphinx.util.osutil import ensuredir
if False:
# For type annotation
from docutils.parsers.rst import Directive # NOQA
from typing import Any, Dict, List, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.util.docutils import SphinxTranslator # NOQA
from sphinx.writers.html import HTMLTranslator # NOQA
from sphinx.writers.latex import LaTeXTranslator # NOQA
from sphinx.writers.manpage import ManualPageTranslator # NOQA
from sphinx.writers.texinfo import TexinfoTranslator # NOQA
from sphinx.writers.text import TextTranslator # NOQA
from sphinx.writers.html import HTMLTranslator
from sphinx.writers.latex import LaTeXTranslator
from sphinx.writers.manpage import ManualPageTranslator
from sphinx.writers.texinfo import TexinfoTranslator
from sphinx.writers.text import TextTranslator
logger = logging.getLogger(__name__)
@@ -53,8 +49,7 @@ class ClickableMapDefinition:
maptag_re = re.compile('<map id="(.*?)"')
href_re = re.compile('href=".*?"')
def __init__(self, filename, content, dot=''):
# type: (str, str, str) -> None
def __init__(self, filename: str, content: str, dot: str = '') -> None:
self.id = None # type: str
self.filename = filename
self.content = content.splitlines()
@@ -62,8 +57,7 @@ class ClickableMapDefinition:
self.parse(dot=dot)
def parse(self, dot=None):
# type: (str) -> None
def parse(self, dot: str = None) -> None:
matched = self.maptag_re.match(self.content[0])
if not matched:
raise GraphvizError('Invalid clickable map file found: %s' % self.filename)
@@ -80,8 +74,7 @@ class ClickableMapDefinition:
if self.href_re.search(line):
self.clickable.append(line)
def generate_clickable_map(self):
# type: () -> str
def generate_clickable_map(self) -> str:
"""Generate clickable map tags if clickable item exists.
If not exists, this only returns empty string.
@@ -96,8 +89,7 @@ class graphviz(nodes.General, nodes.Inline, nodes.Element):
pass
def figure_wrapper(directive, node, caption):
# type: (Directive, graphviz, str) -> nodes.figure
def figure_wrapper(directive: Directive, node: graphviz, caption: str) -> nodes.figure:
figure_node = nodes.figure('', node)
if 'align' in node:
figure_node['align'] = node.attributes.pop('align')
@@ -110,8 +102,7 @@ def figure_wrapper(directive, node, caption):
return figure_node
def align_spec(argument):
# type: (Any) -> str
def align_spec(argument: Any) -> str:
return directives.choice(argument, ('left', 'center', 'right'))
@@ -132,8 +123,7 @@ class Graphviz(SphinxDirective):
'name': directives.unchanged,
}
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
if self.arguments:
document = self.state.document
if self.content:
@@ -194,8 +184,7 @@ class GraphvizSimple(SphinxDirective):
'name': directives.unchanged,
}
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
node = graphviz()
node['code'] = '%s %s {\n%s\n}\n' % \
(self.name, self.arguments[0], '\n'.join(self.content))
@@ -216,8 +205,8 @@ class GraphvizSimple(SphinxDirective):
return [figure]
def render_dot(self, code, options, format, prefix='graphviz'):
# type: (SphinxTranslator, str, Dict, str, str) -> Tuple[str, str]
def render_dot(self: SphinxTranslator, code: str, options: Dict,
format: str, prefix: str = 'graphviz') -> Tuple[str, str]:
"""Render graphviz code into a PNG or PDF output file."""
graphviz_dot = options.get('graphviz_dot', self.builder.config.graphviz_dot)
hashkey = (code + str(options) + str(graphviz_dot) +
@@ -265,9 +254,9 @@ def render_dot(self, code, options, format, prefix='graphviz'):
'[stdout]\n%r') % (exc.stderr, exc.stdout))
def render_dot_html(self, node, code, options, prefix='graphviz',
imgcls=None, alt=None):
# type: (HTMLTranslator, graphviz, str, Dict, str, str, str) -> Tuple[str, str]
def render_dot_html(self: HTMLTranslator, node: graphviz, code: str, options: Dict,
prefix: str = 'graphviz', imgcls: str = None, alt: str = None
) -> Tuple[str, str]:
format = self.builder.config.graphviz_output_format
try:
if format not in ('png', 'svg'):
@@ -319,13 +308,12 @@ def render_dot_html(self, node, code, options, prefix='graphviz',
raise nodes.SkipNode
def html_visit_graphviz(self, node):
# type: (HTMLTranslator, graphviz) -> None
def html_visit_graphviz(self: HTMLTranslator, node: graphviz) -> None:
render_dot_html(self, node, node['code'], node['options'])
def render_dot_latex(self, node, code, options, prefix='graphviz'):
# type: (LaTeXTranslator, graphviz, str, Dict, str) -> None
def render_dot_latex(self: LaTeXTranslator, node: graphviz, code: str,
options: Dict, prefix: str = 'graphviz') -> None:
try:
fname, outfn = render_dot(self, code, options, 'pdf', prefix)
except GraphvizError as exc:
@@ -357,13 +345,12 @@ def render_dot_latex(self, node, code, options, prefix='graphviz'):
raise nodes.SkipNode
def latex_visit_graphviz(self, node):
# type: (LaTeXTranslator, graphviz) -> None
def latex_visit_graphviz(self: LaTeXTranslator, node: graphviz) -> None:
render_dot_latex(self, node, node['code'], node['options'])
def render_dot_texinfo(self, node, code, options, prefix='graphviz'):
# type: (TexinfoTranslator, graphviz, str, Dict, str) -> None
def render_dot_texinfo(self: TexinfoTranslator, node: graphviz, code: str,
options: Dict, prefix: str = 'graphviz') -> None:
try:
fname, outfn = render_dot(self, code, options, 'png', prefix)
except GraphvizError as exc:
@@ -374,13 +361,11 @@ def render_dot_texinfo(self, node, code, options, prefix='graphviz'):
raise nodes.SkipNode
def texinfo_visit_graphviz(self, node):
# type: (TexinfoTranslator, graphviz) -> None
def texinfo_visit_graphviz(self: TexinfoTranslator, node: graphviz) -> None:
render_dot_texinfo(self, node, node['code'], node['options'])
def text_visit_graphviz(self, node):
# type: (TextTranslator, graphviz) -> None
def text_visit_graphviz(self: TextTranslator, node: graphviz) -> None:
if 'alt' in node.attributes:
self.add_text(_('[graph: %s]') % node['alt'])
else:
@@ -388,8 +373,7 @@ def text_visit_graphviz(self, node):
raise nodes.SkipNode
def man_visit_graphviz(self, node):
# type: (ManualPageTranslator, graphviz) -> None
def man_visit_graphviz(self: ManualPageTranslator, node: graphviz) -> None:
if 'alt' in node.attributes:
self.body.append(_('[graph: %s]') % node['alt'])
else:
@@ -397,16 +381,14 @@ def man_visit_graphviz(self, node):
raise nodes.SkipNode
def on_build_finished(app, exc):
# type: (Sphinx, Exception) -> None
def on_build_finished(app: Sphinx, exc: Exception) -> None:
if exc is None:
src = path.join(sphinx.package_dir, 'templates', 'graphviz', 'graphviz.css')
dst = path.join(app.outdir, '_static')
copy_asset(src, dst)
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_node(graphviz,
html=(html_visit_graphviz, None),
latex=(latex_visit_graphviz, None),
+6 -11
View File
@@ -7,19 +7,17 @@
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import subprocess
from subprocess import CalledProcessError, PIPE
from typing import Any, Dict
from sphinx.application import Sphinx
from sphinx.errors import ExtensionError
from sphinx.locale import __
from sphinx.transforms.post_transforms.images import ImageConverter
from sphinx.util import logging
if False:
# For type annotation
from typing import Any, Dict # NOQA
from sphinx.application import Sphinx # NOQA
logger = logging.getLogger(__name__)
@@ -31,8 +29,7 @@ class ImagemagickConverter(ImageConverter):
('application/pdf', 'image/png'),
]
def is_available(self):
# type: () -> bool
def is_available(self) -> bool:
"""Confirms the converter is available or not."""
try:
args = [self.config.image_converter, '-version']
@@ -50,8 +47,7 @@ class ImagemagickConverter(ImageConverter):
exc.stderr, exc.stdout)
return False
def convert(self, _from, _to):
# type: (str, str) -> bool
def convert(self, _from: str, _to: str) -> bool:
"""Converts the image to expected one."""
try:
# append an index 0 to source filename to pick up the first frame
@@ -75,8 +71,7 @@ class ImagemagickConverter(ImageConverter):
(exc.stderr, exc.stdout))
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_post_transform(ImagemagickConverter)
app.add_config_value('image_converter', 'convert', 'env')
app.add_config_value('image_converter_args', [], 'env')
+22 -37
View File
@@ -28,24 +28,23 @@ import posixpath
import sys
import time
from os import path
from typing import Any, Dict, IO, List, Tuple
from urllib.parse import urlsplit, urlunsplit
from docutils import nodes
from docutils.nodes import Element, TextElement
from docutils.utils import relative_path
import sphinx
from sphinx.application import Sphinx
from sphinx.builders.html import INVENTORY_FILENAME
from sphinx.config import Config
from sphinx.environment import BuildEnvironment
from sphinx.locale import _, __
from sphinx.util import requests, logging
from sphinx.util.inventory import InventoryFile
from sphinx.util.typing import Inventory
if False:
# For type annotation
from typing import Any, Dict, IO, List, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
from sphinx.environment import BuildEnvironment # NOQA
from sphinx.util.typing import Inventory # NOQA
logger = logging.getLogger(__name__)
@@ -53,8 +52,7 @@ logger = logging.getLogger(__name__)
class InventoryAdapter:
"""Inventory adapter for environment"""
def __init__(self, env):
# type: (BuildEnvironment) -> None
def __init__(self, env: BuildEnvironment) -> None:
self.env = env
if not hasattr(env, 'intersphinx_cache'):
@@ -63,28 +61,23 @@ class InventoryAdapter:
self.env.intersphinx_named_inventory = {} # type: ignore
@property
def cache(self):
# type: () -> Dict[str, Tuple[str, int, Inventory]]
def cache(self) -> Dict[str, Tuple[str, int, Inventory]]:
return self.env.intersphinx_cache # type: ignore
@property
def main_inventory(self):
# type: () -> Inventory
def main_inventory(self) -> Inventory:
return self.env.intersphinx_inventory # type: ignore
@property
def named_inventory(self):
# type: () -> Dict[str, Inventory]
def named_inventory(self) -> Dict[str, Inventory]:
return self.env.intersphinx_named_inventory # type: ignore
def clear(self):
# type: () -> None
def clear(self) -> None:
self.env.intersphinx_inventory.clear() # type: ignore
self.env.intersphinx_named_inventory.clear() # type: ignore
def _strip_basic_auth(url):
# type: (str) -> str
def _strip_basic_auth(url: str) -> str:
"""Returns *url* with basic auth credentials removed. Also returns the
basic auth username and password if they're present in *url*.
@@ -105,8 +98,7 @@ def _strip_basic_auth(url):
return urlunsplit(frags)
def _read_from_url(url, config=None):
# type: (str, Config) -> IO
def _read_from_url(url: str, config: Config = None) -> IO:
"""Reads data from *url* with an HTTP *GET*.
This function supports fetching from resources which use basic HTTP auth as
@@ -131,8 +123,7 @@ def _read_from_url(url, config=None):
return r.raw
def _get_safe_url(url):
# type: (str) -> str
def _get_safe_url(url: str) -> str:
"""Gets version of *url* with basic auth passwords obscured. This function
returns results suitable for printing and logging.
@@ -157,8 +148,7 @@ def _get_safe_url(url):
return urlunsplit(frags)
def fetch_inventory(app, uri, inv):
# type: (Sphinx, str, Any) -> Any
def fetch_inventory(app: Sphinx, uri: str, inv: Any) -> Any:
"""Fetch, parse and return an intersphinx inventory file."""
# both *uri* (base URI of the links to generate) and *inv* (actual
# location of the inventory file) can be local or remote URIs
@@ -197,8 +187,7 @@ def fetch_inventory(app, uri, inv):
return invdata
def load_mappings(app):
# type: (Sphinx) -> None
def load_mappings(app: Sphinx) -> None:
"""Load all intersphinx mappings into the environment."""
now = int(time.time())
cache_time = now - app.config.intersphinx_cache_limit * 86400
@@ -258,8 +247,8 @@ def load_mappings(app):
inventories.main_inventory.setdefault(type, {}).update(objects)
def missing_reference(app, env, node, contnode):
# type: (Sphinx, BuildEnvironment, nodes.Element, nodes.TextElement) -> nodes.reference
def missing_reference(app: Sphinx, env: BuildEnvironment, node: Element, contnode: TextElement
) -> nodes.reference:
"""Attempt to resolve a missing reference via intersphinx references."""
target = node['reftarget']
inventories = InventoryAdapter(env)
@@ -336,8 +325,7 @@ def missing_reference(app, env, node, contnode):
return None
def normalize_intersphinx_mapping(app, config):
# type: (Sphinx, Config) -> None
def normalize_intersphinx_mapping(app: Sphinx, config: Config) -> None:
for key, value in config.intersphinx_mapping.copy().items():
try:
if isinstance(value, (list, tuple)):
@@ -361,8 +349,7 @@ def normalize_intersphinx_mapping(app, config):
config.intersphinx_mapping.pop(key)
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value('intersphinx_mapping', {}, True)
app.add_config_value('intersphinx_cache_limit', 5, False)
app.add_config_value('intersphinx_timeout', None, False)
@@ -376,8 +363,7 @@ def setup(app):
}
def inspect_main(argv):
# type: (List[str]) -> None
def inspect_main(argv: List[str]) -> None:
"""Debug functionality to print out an inventory"""
if len(argv) < 1:
print("Print out an inventory file.\n"
@@ -393,8 +379,7 @@ def inspect_main(argv):
srcdir = ''
config = MockConfig()
def warn(self, msg):
# type: (str) -> None
def warn(self, msg: str) -> None:
print(msg, file=sys.stderr)
try:
+6 -9
View File
@@ -8,25 +8,23 @@
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict, Set
from docutils import nodes
from docutils.nodes import Node
import sphinx
from sphinx import addnodes
from sphinx.application import Sphinx
from sphinx.errors import SphinxError
from sphinx.locale import _
if False:
# For type annotation
from typing import Any, Dict, Set # NOQA
from sphinx.application import Sphinx # NOQA
class LinkcodeError(SphinxError):
category = "linkcode error"
def doctree_read(app, doctree):
# type: (Sphinx, nodes.Node) -> None
def doctree_read(app: Sphinx, doctree: Node) -> None:
env = app.builder.env
resolve_target = getattr(env.config, 'linkcode_resolve', None)
@@ -75,8 +73,7 @@ def doctree_read(app, doctree):
signode += onlynode
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.connect('doctree-read', doctree_read)
app.add_config_value('linkcode_resolve', None, '')
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
+11 -15
View File
@@ -9,26 +9,24 @@
"""
import warnings
from typing import Callable, List, Tuple
from docutils import nodes
from docutils.nodes import Element, Node
from docutils.parsers.rst.roles import math_role as math_role_base
from sphinx.addnodes import math, math_block as displaymath # NOQA # to keep compatibility
from sphinx.application import Sphinx
from sphinx.builders.latex.nodes import math_reference as eqref # NOQA # to keep compatibility
from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.directives.patches import MathDirective as MathDirectiveBase
from sphinx.domains.math import MathDomain # NOQA # to keep compatibility
from sphinx.domains.math import MathReferenceRole as EqXRefRole # NOQA # to keep compatibility
if False:
# For type annotation
from typing import Callable, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.writers.html import HTMLTranslator # NOQA
from sphinx.writers.html import HTMLTranslator
class MathDirective(MathDirectiveBase):
def run(self):
def run(self) -> List[Node]:
warnings.warn('sphinx.ext.mathbase.MathDirective is moved to '
'sphinx.directives.patches package.',
RemovedInSphinx30Warning, stacklevel=2)
@@ -42,8 +40,7 @@ def math_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
return math_role_base(role, rawtext, text, lineno, inliner, options, content)
def get_node_equation_number(writer, node):
# type: (HTMLTranslator, nodes.math_block) -> str
def get_node_equation_number(writer: HTMLTranslator, node: nodes.math_block) -> str:
warnings.warn('sphinx.ext.mathbase.get_node_equation_number() is moved to '
'sphinx.util.math package.',
RemovedInSphinx30Warning, stacklevel=2)
@@ -51,8 +48,7 @@ def get_node_equation_number(writer, node):
return get_node_equation_number(writer, node)
def wrap_displaymath(text, label, numbering):
# type: (str, str, bool) -> str
def wrap_displaymath(text: str, label: str, numbering: bool) -> str:
warnings.warn('sphinx.ext.mathbase.wrap_displaymath() is moved to '
'sphinx.util.math package.',
RemovedInSphinx30Warning, stacklevel=2)
@@ -60,8 +56,7 @@ def wrap_displaymath(text, label, numbering):
return wrap_displaymath(text, label, numbering)
def is_in_section_title(node):
# type: (nodes.Element) -> bool
def is_in_section_title(node: Element) -> bool:
"""Determine whether the node is in a section title"""
from sphinx.util.nodes import traverse_parent
@@ -75,8 +70,9 @@ def is_in_section_title(node):
return False
def setup_math(app, htmlinlinevisitors, htmldisplayvisitors):
# type: (Sphinx, Tuple[Callable, Callable], Tuple[Callable, Callable]) -> None
def setup_math(app: Sphinx,
htmlinlinevisitors: Tuple[Callable, Callable],
htmldisplayvisitors: Tuple[Callable, Callable]) -> None:
warnings.warn('setup_math() is deprecated. '
'Please use app.add_html_math_renderer() instead.',
RemovedInSphinx30Warning, stacklevel=2)
+8 -15
View File
@@ -11,27 +11,23 @@
"""
import json
from typing import Any, Dict
from typing import cast
from docutils import nodes
import sphinx
from sphinx.application import Sphinx
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.domains.math import MathDomain
from sphinx.environment import BuildEnvironment
from sphinx.errors import ExtensionError
from sphinx.locale import _
from sphinx.util.math import get_node_equation_number
if False:
# For type annotation
from typing import Any, Dict # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.environment import BuildEnvironment # NOQA
from sphinx.writers.html import HTMLTranslator # NOQA
from sphinx.writers.html import HTMLTranslator
def html_visit_math(self, node):
# type: (HTMLTranslator, nodes.math) -> None
def html_visit_math(self: HTMLTranslator, node: nodes.math) -> None:
self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate nohighlight'))
self.body.append(self.builder.config.mathjax_inline[0] +
self.encode(node.astext()) +
@@ -39,8 +35,7 @@ def html_visit_math(self, node):
raise nodes.SkipNode
def html_visit_displaymath(self, node):
# type: (HTMLTranslator, nodes.math_block) -> None
def html_visit_displaymath(self: HTMLTranslator, node: nodes.math_block) -> None:
self.body.append(self.starttag(node, 'div', CLASS='math notranslate nohighlight'))
if node['nowrap']:
self.body.append(self.encode(node.astext()))
@@ -72,8 +67,7 @@ def html_visit_displaymath(self, node):
raise nodes.SkipNode
def install_mathjax(app, env):
# type: (Sphinx, BuildEnvironment) -> None
def install_mathjax(app: Sphinx, env: BuildEnvironment) -> None:
if app.builder.format != 'html' or app.builder.math_renderer_name != 'mathjax': # type: ignore # NOQA
return
if not app.config.mathjax_path:
@@ -94,8 +88,7 @@ def install_mathjax(app, env):
builder.add_js_file(None, type="text/x-mathjax-config", body=body)
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_html_math_renderer('mathjax',
(html_visit_math, None),
(html_visit_displaymath, None))