Add mypy annotations

This commit is contained in:
Takeshi KOMIYA 2017-02-10 15:53:42 +09:00
parent 82e011cae6
commit da6f4c0019
22 changed files with 368 additions and 36 deletions

View File

@ -60,6 +60,7 @@ if __version__.endswith('+'):
def main(argv=sys.argv): def main(argv=sys.argv):
# type: (List[str]) -> None
if sys.argv[1:2] == ['-M']: if sys.argv[1:2] == ['-M']:
sys.exit(make_main(argv)) sys.exit(make_main(argv))
else: else:
@ -67,6 +68,7 @@ def main(argv=sys.argv):
def build_main(argv=sys.argv): def build_main(argv=sys.argv):
# type: (List[str]) -> int
"""Sphinx build "main" command-line entry.""" """Sphinx build "main" command-line entry."""
if (sys.version_info[:3] < (2, 7, 0) or if (sys.version_info[:3] < (2, 7, 0) or
(3, 0, 0) <= sys.version_info[:3] < (3, 4, 0)): (3, 0, 0) <= sys.version_info[:3] < (3, 4, 0)):
@ -104,14 +106,15 @@ def build_main(argv=sys.argv):
sys.stderr.write('Error: Sphinx requires at least Docutils 0.10 to ' sys.stderr.write('Error: Sphinx requires at least Docutils 0.10 to '
'run.\n') 'run.\n')
return 1 return 1
return cmdline.main(argv) return cmdline.main(argv) # type: ignore
def make_main(argv=sys.argv): def make_main(argv=sys.argv):
# type: (List[str]) -> int
"""Sphinx build "make mode" entry.""" """Sphinx build "make mode" entry."""
from sphinx import make_mode from sphinx import make_mode
return make_mode.run_make_mode(argv[2:]) return make_mode.run_make_mode(argv[2:]) # type: ignore
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main(sys.argv)) sys.exit(main(sys.argv)) # type: ignore

View File

@ -621,7 +621,7 @@ class StandaloneHTMLBuilder(Builder):
ensuredir(path.join(self.outdir, '_static')) ensuredir(path.join(self.outdir, '_static'))
# first, create pygments style file # first, create pygments style file
with open(path.join(self.outdir, '_static', 'pygments.css'), 'w') as f: with open(path.join(self.outdir, '_static', 'pygments.css'), 'w') as f:
f.write(self.highlighter.get_stylesheet()) f.write(self.highlighter.get_stylesheet()) # type: ignore
# then, copy translations JavaScript file # then, copy translations JavaScript file
if self.config.language is not None: if self.config.language is not None:
jsfile = self._get_translations_js() jsfile = self._get_translations_js()

View File

@ -104,7 +104,7 @@ class LaTeXBuilder(Builder):
f.write('\\NeedsTeXFormat{LaTeX2e}[1995/12/01]\n') f.write('\\NeedsTeXFormat{LaTeX2e}[1995/12/01]\n')
f.write('\\ProvidesPackage{sphinxhighlight}' f.write('\\ProvidesPackage{sphinxhighlight}'
'[2016/05/29 stylesheet for highlighting with pygments]\n\n') '[2016/05/29 stylesheet for highlighting with pygments]\n\n')
f.write(highlighter.get_stylesheet()) f.write(highlighter.get_stylesheet()) # type: ignore
def write(self, *ignored): def write(self, *ignored):
# type: (Any) -> None # type: (Any) -> None

View File

@ -21,6 +21,7 @@ if False:
# For type annotation # For type annotation
from typing import Any, Callable, Iterable, Tuple, Type, Union # NOQA from typing import Any, Callable, Iterable, Tuple, Type, Union # NOQA
from docutils import nodes # NOQA from docutils import nodes # NOQA
from docutils.parsers.rst.states import Inliner # NOQA
from sphinx.builders import Builder # NOQA from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA from sphinx.environment import BuildEnvironment # NOQA
@ -189,8 +190,8 @@ class Domain(object):
return None return None
fullname = '%s:%s' % (self.name, name) fullname = '%s:%s' % (self.name, name)
def role_adapter(typ, rawtext, text, lineno, inliner, def role_adapter(typ, rawtext, text, lineno, inliner, options={}, content=[]):
options={}, content=[]): # type: (unicode, unicode, unicode, int, Inliner, Dict, List[unicode]) -> nodes.Node # NOQA
return self.roles[name](fullname, rawtext, text, lineno, return self.roles[name](fullname, rawtext, text, lineno,
inliner, options, content) inliner, options, content)
self._role_cache[name] = role_adapter self._role_cache[name] = role_adapter
@ -210,6 +211,7 @@ class Domain(object):
class DirectiveAdapter(BaseDirective): # type: ignore class DirectiveAdapter(BaseDirective): # type: ignore
def run(self): def run(self):
# type: () -> List[nodes.Node]
self.name = fullname self.name = fullname
return BaseDirective.run(self) return BaseDirective.run(self)
self._directive_cache[name] = DirectiveAdapter self._directive_cache[name] = DirectiveAdapter

View File

@ -895,6 +895,7 @@ class StandardDomain(Domain):
# type: (nodes.Node) -> unicode # type: (nodes.Node) -> unicode
"""Get figure type of nodes.""" """Get figure type of nodes."""
def has_child(node, cls): def has_child(node, cls):
# type: (nodes.Node, Type) -> bool
return any(isinstance(child, cls) for child in node) return any(isinstance(child, cls) for child in node)
if isinstance(node, nodes.section): if isinstance(node, nodes.section):

View File

@ -746,7 +746,7 @@ class BuildEnvironment(object):
@property @property
def currmodule(self): def currmodule(self):
# type () -> None # type: () -> None
"""Backwards compatible alias. Will be removed.""" """Backwards compatible alias. Will be removed."""
logger.warning('env.currmodule is being referenced by an ' logger.warning('env.currmodule is being referenced by an '
'extension; this API will be removed in the future', 'extension; this API will be removed in the future',
@ -1024,6 +1024,7 @@ class BuildEnvironment(object):
traversed = set() traversed = set()
def traverse_toctree(parent, docname): def traverse_toctree(parent, docname):
# type: (unicode, unicode) -> Iterator[Tuple[unicode, unicode]]
if parent == docname: if parent == docname:
logger.warning('self referenced toctree found. Ignored.', location=docname) logger.warning('self referenced toctree found. Ignored.', location=docname)
return return

View File

@ -42,6 +42,7 @@ class IndexEntries(object):
new = {} # type: Dict[unicode, List] new = {} # type: Dict[unicode, List]
def add_entry(word, subword, main, link=True, dic=new, key=None): def add_entry(word, subword, main, link=True, dic=new, key=None):
# type: (unicode, unicode, unicode, bool, Dict, unicode) -> None
# Force the word to be unicode if it's a ASCII bytestring. # Force the word to be unicode if it's a ASCII bytestring.
# This will solve problems with unicode normalization later. # This will solve problems with unicode normalization later.
# For instance the RFC role will add bytestrings at the moment # For instance the RFC role will add bytestrings at the moment
@ -96,6 +97,7 @@ class IndexEntries(object):
# sort the index entries; put all symbols at the front, even those # sort the index entries; put all symbols at the front, even those
# following the letters in ASCII, this is where the chr(127) comes from # following the letters in ASCII, this is where the chr(127) comes from
def keyfunc(entry, lcletters=string.ascii_lowercase + '_'): def keyfunc(entry, lcletters=string.ascii_lowercase + '_'):
# type: (Tuple[unicode, List], unicode) -> Tuple[unicode, unicode]
key, (void, void, category_key) = entry key, (void, void, category_key) = entry
if category_key: if category_key:
# using specified category key to sort # using specified category key to sort
@ -140,6 +142,7 @@ class IndexEntries(object):
# group the entries by letter # group the entries by letter
def keyfunc2(item, letters=string.ascii_uppercase + '_'): def keyfunc2(item, letters=string.ascii_uppercase + '_'):
# type: (Tuple[unicode, List], unicode) -> unicode
# hack: mutating the subitems dicts to a list in the keyfunc # hack: mutating the subitems dicts to a list in the keyfunc
k, v = item k, v = item
v[1] = sorted((si, se) for (si, (se, void, void)) in iteritems(v[1])) v[1] = sorted((si, se) for (si, (se, void, void)) in iteritems(v[1]))

View File

@ -85,6 +85,7 @@ class TocTree(object):
toctree_ancestors = self.get_toctree_ancestors(docname) toctree_ancestors = self.get_toctree_ancestors(docname)
def _toctree_add_classes(node, depth): def _toctree_add_classes(node, depth):
# type: (nodes.Node, int) -> None
"""Add 'toctree-l%d' and 'current' classes to the toctree.""" """Add 'toctree-l%d' and 'current' classes to the toctree."""
for subnode in node.children: for subnode in node.children:
if isinstance(subnode, (addnodes.compact_paragraph, if isinstance(subnode, (addnodes.compact_paragraph,
@ -114,8 +115,8 @@ class TocTree(object):
subnode['iscurrent'] = True subnode['iscurrent'] = True
subnode = subnode.parent subnode = subnode.parent
def _entries_from_toctree(toctreenode, parents, def _entries_from_toctree(toctreenode, parents, separate=False, subtree=False):
separate=False, subtree=False): # type: (addnodes.toctree, List[nodes.Node], bool, bool) -> List[nodes.Node]
"""Return TOC entries for a toctree node.""" """Return TOC entries for a toctree node."""
refs = [(e[0], e[1]) for e in toctreenode['entries']] refs = [(e[0], e[1]) for e in toctreenode['entries']]
entries = [] entries = []

View File

@ -975,6 +975,7 @@ class Documenter(object):
tagorder = self.analyzer.tagorder tagorder = self.analyzer.tagorder
def keyfunc(entry): def keyfunc(entry):
# type: (Tuple[Documenter, bool]) -> int
fullname = entry[0].name.split('::')[1] fullname = entry[0].name.split('::')[1]
return tagorder.get(fullname, len(tagorder)) return tagorder.get(fullname, len(tagorder))
memberdocumenters.sort(key=keyfunc) memberdocumenters.sort(key=keyfunc)
@ -1828,7 +1829,9 @@ class testcls:
"""test doc string""" """test doc string"""
def __getattr__(self, x): def __getattr__(self, x):
# type: (Any) -> Any
return x return x
def __setattr__(self, x, y): def __setattr__(self, x, y):
# type: (Any, Any) -> None
"""Attr setter.""" """Attr setter."""

View File

@ -58,6 +58,7 @@ else:
def compare_version(ver1, ver2, operand): def compare_version(ver1, ver2, operand):
# type: (unicode, unicode, unicode) -> bool
"""Compare `ver1` to `ver2`, relying on `operand`. """Compare `ver1` to `ver2`, relying on `operand`.
Some examples: Some examples:

View File

@ -27,6 +27,12 @@ from pygments.styles import get_style_by_name
from pygments.util import ClassNotFound from pygments.util import ClassNotFound
from sphinx.pygments_styles import SphinxStyle, NoneStyle from sphinx.pygments_styles import SphinxStyle, NoneStyle
if False:
# For type annotation
from typing import Any # NOQA
from pygments.formatter import Formatter # NOQA
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
lexers = dict( lexers = dict(
@ -59,8 +65,8 @@ class PygmentsBridge(object):
html_formatter = HtmlFormatter html_formatter = HtmlFormatter
latex_formatter = LatexFormatter latex_formatter = LatexFormatter
def __init__(self, dest='html', stylename='sphinx', def __init__(self, dest='html', stylename='sphinx', trim_doctest_flags=False):
trim_doctest_flags=False): # type: (unicode, unicode, bool) -> None
self.dest = dest self.dest = dest
if stylename is None or stylename == 'sphinx': if stylename is None or stylename == 'sphinx':
style = SphinxStyle style = SphinxStyle
@ -73,7 +79,7 @@ class PygmentsBridge(object):
else: else:
style = get_style_by_name(stylename) style = get_style_by_name(stylename)
self.trim_doctest_flags = trim_doctest_flags self.trim_doctest_flags = trim_doctest_flags
self.formatter_args = {'style': style} self.formatter_args = {'style': style} # type: Dict[unicode, Any]
if dest == 'html': if dest == 'html':
self.formatter = self.html_formatter self.formatter = self.html_formatter
else: else:
@ -81,10 +87,12 @@ class PygmentsBridge(object):
self.formatter_args['commandprefix'] = 'PYG' self.formatter_args['commandprefix'] = 'PYG'
def get_formatter(self, **kwargs): def get_formatter(self, **kwargs):
kwargs.update(self.formatter_args) # type: (Any) -> Formatter
kwargs.update(self.formatter_args) # type: ignore
return self.formatter(**kwargs) return self.formatter(**kwargs)
def unhighlighted(self, source): def unhighlighted(self, source):
# type: (unicode) -> unicode
if self.dest == 'html': if self.dest == 'html':
return '<pre>' + htmlescape(source) + '</pre>\n' return '<pre>' + htmlescape(source) + '</pre>\n'
else: else:
@ -96,6 +104,7 @@ class PygmentsBridge(object):
source + '\\end{Verbatim}\n' source + '\\end{Verbatim}\n'
def highlight_block(self, source, lang, opts=None, location=None, force=False, **kwargs): def highlight_block(self, source, lang, opts=None, location=None, force=False, **kwargs):
# type: (unicode, unicode, Any, Any, bool, Any) -> unicode
if not isinstance(source, text_type): if not isinstance(source, text_type):
source = source.decode() source = source.decode()
@ -131,8 +140,8 @@ class PygmentsBridge(object):
# trim doctest options if wanted # trim doctest options if wanted
if isinstance(lexer, PythonConsoleLexer) and self.trim_doctest_flags: if isinstance(lexer, PythonConsoleLexer) and self.trim_doctest_flags:
source = doctest.blankline_re.sub('', source) source = doctest.blankline_re.sub('', source) # type: ignore
source = doctest.doctestopt_re.sub('', source) source = doctest.doctestopt_re.sub('', source) # type: ignore
# highlight via Pygments # highlight via Pygments
formatter = self.get_formatter(**kwargs) formatter = self.get_formatter(**kwargs)
@ -157,6 +166,7 @@ class PygmentsBridge(object):
return hlsource.translate(tex_hl_escape_map_new) return hlsource.translate(tex_hl_escape_map_new)
def get_stylesheet(self): def get_stylesheet(self):
# type: () -> unicode
formatter = self.get_formatter() formatter = self.get_formatter()
if self.dest == 'html': if self.dest == 'html':
return formatter.get_style_defs('.highlight') return formatter.get_style_defs('.highlight')

View File

@ -113,6 +113,7 @@ class SphinxFileSystemLoader(FileSystemLoader):
mtime = path.getmtime(filename) mtime = path.getmtime(filename)
def uptodate(): def uptodate():
# type: () -> bool
try: try:
return path.getmtime(filename) == mtime return path.getmtime(filename) == mtime
except OSError: except OSError:

View File

@ -16,7 +16,7 @@ from six.moves import UserString
if False: if False:
# For type annotation # For type annotation
from typing import Any, Tuple # NOQA from typing import Any, Callable, Iterator, Tuple # NOQA
class _TranslationProxy(UserString, object): class _TranslationProxy(UserString, object):
@ -35,24 +35,31 @@ class _TranslationProxy(UserString, object):
__slots__ = ('_func', '_args') __slots__ = ('_func', '_args')
def __new__(cls, func, *args): def __new__(cls, func, *args):
# type: (Callable, unicode) -> object
if not args: if not args:
# not called with "function" and "arguments", but a plain string # not called with "function" and "arguments", but a plain string
return text_type(func) return text_type(func)
return object.__new__(cls) return object.__new__(cls) # type: ignore
def __getnewargs__(self): def __getnewargs__(self):
return (self._func,) + self._args # type: () -> Tuple
return (self._func,) + self._args # type: ignore
def __init__(self, func, *args): def __init__(self, func, *args):
# type: (Callable, unicode) -> None
self._func = func self._func = func
self._args = args self._args = args
data = property(lambda x: x._func(*x._args)) @property
def data(self):
# type: () -> unicode
return self._func(*self._args)
# replace function from UserString; it instantiates a self.__class__ # replace function from UserString; it instantiates a self.__class__
# for the encoding result # for the encoding result
def encode(self, encoding=None, errors=None): def encode(self, encoding=None, errors=None):
# type: (unicode, unicode) -> str
if encoding: if encoding:
if errors: if errors:
return self.data.encode(encoding, errors) return self.data.encode(encoding, errors)
@ -62,81 +69,106 @@ class _TranslationProxy(UserString, object):
return self.data.encode() return self.data.encode()
def __contains__(self, key): def __contains__(self, key):
# type: (Any) -> bool
return key in self.data return key in self.data
def __bool__(self): def __bool__(self):
# type: () -> bool
return bool(self.data) return bool(self.data)
__nonzero__ = __bool__ # for python2 compatibility __nonzero__ = __bool__ # for python2 compatibility
def __dir__(self): def __dir__(self):
# type: () -> List[str]
return dir(text_type) return dir(text_type)
def __iter__(self): def __iter__(self):
# type: () -> Iterator[unicode]
return iter(self.data) return iter(self.data)
def __len__(self): def __len__(self):
# type: () -> int
return len(self.data) return len(self.data)
def __str__(self): def __str__(self):
# type: () -> str
return str(self.data) return str(self.data)
def __unicode__(self): def __unicode__(self):
# type: () -> unicode
return text_type(self.data) return text_type(self.data)
def __add__(self, other): def __add__(self, other):
# type: (unicode) -> unicode
return self.data + other return self.data + other
def __radd__(self, other): def __radd__(self, other):
# type: (unicode) -> unicode
return other + self.data return other + self.data
def __mod__(self, other): def __mod__(self, other):
# type: (unicode) -> unicode
return self.data % other return self.data % other
def __rmod__(self, other): def __rmod__(self, other):
# type: (unicode) -> unicode
return other % self.data return other % self.data
def __mul__(self, other): def __mul__(self, other):
# type: (Any) -> unicode
return self.data * other return self.data * other
def __rmul__(self, other): def __rmul__(self, other):
# type: (Any) -> unicode
return other * self.data return other * self.data
def __lt__(self, other): def __lt__(self, other):
# type: (unicode) -> bool
return self.data < other return self.data < other
def __le__(self, other): def __le__(self, other):
# type: (unicode) -> bool
return self.data <= other return self.data <= other
def __eq__(self, other): def __eq__(self, other):
# type: (Any) -> bool
return self.data == other return self.data == other
def __ne__(self, other): def __ne__(self, other):
# type: (Any) -> bool
return self.data != other return self.data != other
def __gt__(self, other): def __gt__(self, other):
# type: (unicode) -> bool
return self.data > other return self.data > other
def __ge__(self, other): def __ge__(self, other):
# type: (unicode) -> bool
return self.data >= other return self.data >= other
def __getattr__(self, name): def __getattr__(self, name):
# type: (unicode) -> Any
if name == '__members__': if name == '__members__':
return self.__dir__() return self.__dir__()
return getattr(self.data, name) return getattr(self.data, name)
def __getstate__(self): def __getstate__(self):
# type: () -> Tuple[Callable, Tuple[unicode, ...]]
return self._func, self._args return self._func, self._args
def __setstate__(self, tup): def __setstate__(self, tup):
# type: (Tuple[Callable, Tuple[unicode]]) -> None
self._func, self._args = tup self._func, self._args = tup
def __getitem__(self, key): def __getitem__(self, key):
# type: (Any) -> unicode
return self.data[key] return self.data[key]
def __copy__(self): def __copy__(self):
# type: () -> _TranslationProxy
return self return self
def __repr__(self): def __repr__(self):
# type: () -> str
try: try:
return 'i' + repr(text_type(self.data)) return 'i' + repr(text_type(self.data))
except: except:
@ -173,13 +205,13 @@ admonitionlabels = {
'seealso': l_('See also'), 'seealso': l_('See also'),
'tip': l_('Tip'), 'tip': l_('Tip'),
'warning': l_('Warning'), 'warning': l_('Warning'),
} } # type: Dict[unicode, unicode]
versionlabels = { versionlabels = {
'versionadded': l_('New in version %s'), 'versionadded': l_('New in version %s'),
'versionchanged': l_('Changed in version %s'), 'versionchanged': l_('Changed in version %s'),
'deprecated': l_('Deprecated since version %s'), 'deprecated': l_('Deprecated since version %s'),
} } # type: Dict[unicode, unicode]
# XXX Python specific # XXX Python specific
pairindextypes = { pairindextypes = {
@ -242,6 +274,7 @@ def init(locale_dirs, language, catalog='sphinx'):
def get_translator(catalog='sphinx'): def get_translator(catalog='sphinx'):
# type: (unicode) -> gettext.NullTranslations
global translators global translators
translator = translators.get(catalog) translator = translators.get(catalog)
if translator is None: if translator is None:

View File

@ -42,6 +42,10 @@ from sphinx.util.console import ( # type: ignore
from sphinx.util.template import SphinxRenderer from sphinx.util.template import SphinxRenderer
from sphinx.util import texescape from sphinx.util import texescape
if False:
# For type annotation
from typing import Any, Callable, Pattern # NOQA
TERM_ENCODING = getattr(sys.stdin, 'encoding', None) TERM_ENCODING = getattr(sys.stdin, 'encoding', None)
DEFAULT_VALUE = { DEFAULT_VALUE = {
@ -66,6 +70,7 @@ PROMPT_PREFIX = '> '
def mkdir_p(dir): def mkdir_p(dir):
# type: (unicode) -> None
if path.isdir(dir): if path.isdir(dir):
return return
os.makedirs(dir) os.makedirs(dir)
@ -73,6 +78,7 @@ def mkdir_p(dir):
# function to get input from terminal -- overridden by the test suite # function to get input from terminal -- overridden by the test suite
def term_input(prompt): def term_input(prompt):
# type: (unicode) -> unicode
print(prompt, end='') print(prompt, end='')
return input('') return input('')
@ -82,6 +88,7 @@ class ValidationError(Exception):
def is_path(x): def is_path(x):
# type: (unicode) -> unicode
x = path.expanduser(x) x = path.expanduser(x)
if path.exists(x) and not path.isdir(x): if path.exists(x) and not path.isdir(x):
raise ValidationError("Please enter a valid path name.") raise ValidationError("Please enter a valid path name.")
@ -89,30 +96,36 @@ def is_path(x):
def allow_empty(x): def allow_empty(x):
# type: (unicode) -> unicode
return x return x
def nonempty(x): def nonempty(x):
# type: (unicode) -> unicode
if not x: if not x:
raise ValidationError("Please enter some text.") raise ValidationError("Please enter some text.")
return x return x
def choice(*l): def choice(*l):
# type: (List[unicode]) -> Callable[[unicode], unicode]
def val(x): def val(x):
# type: (unicode) -> unicode
if x not in l: if x not in l:
raise ValidationError('Please enter one of %s.' % ', '.join(l)) raise ValidationError('Please enter one of %s.' % ', '.join(l)) # type: ignore
return x return x
return val return val
def boolean(x): def boolean(x):
# type: (unicode) -> bool
if x.upper() not in ('Y', 'YES', 'N', 'NO'): if x.upper() not in ('Y', 'YES', 'N', 'NO'):
raise ValidationError("Please enter either 'y' or 'n'.") raise ValidationError("Please enter either 'y' or 'n'.")
return x.upper() in ('Y', 'YES') return x.upper() in ('Y', 'YES')
def suffix(x): def suffix(x):
# type: (unicode) -> unicode
if not (x[0:1] == '.' and len(x) > 1): if not (x[0:1] == '.' and len(x) > 1):
raise ValidationError("Please enter a file suffix, " raise ValidationError("Please enter a file suffix, "
"e.g. '.rst' or '.txt'.") "e.g. '.rst' or '.txt'.")
@ -120,10 +133,12 @@ def suffix(x):
def ok(x): def ok(x):
# type: (unicode) -> unicode
return x return x
def term_decode(text): def term_decode(text):
# type: (unicode) -> unicode
if isinstance(text, text_type): if isinstance(text, text_type):
return text return text
@ -145,9 +160,10 @@ def term_decode(text):
def do_prompt(d, key, text, default=None, validator=nonempty): def do_prompt(d, key, text, default=None, validator=nonempty):
# type: (Dict, unicode, unicode, unicode, Callable[[unicode], Any]) -> None
while True: while True:
if default is not None: if default is not None:
prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default) prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default) # type: unicode
else: else:
prompt = PROMPT_PREFIX + text + ': ' prompt = PROMPT_PREFIX + text + ': '
if PY2: if PY2:
@ -179,6 +195,7 @@ def do_prompt(d, key, text, default=None, validator=nonempty):
def convert_python_source(source, rex=re.compile(r"[uU]('.*?')")): def convert_python_source(source, rex=re.compile(r"[uU]('.*?')")):
# type: (unicode, Pattern) -> unicode
# remove Unicode literal prefixes # remove Unicode literal prefixes
if PY3: if PY3:
return rex.sub('\\1', source) return rex.sub('\\1', source)
@ -188,10 +205,12 @@ def convert_python_source(source, rex=re.compile(r"[uU]('.*?')")):
class QuickstartRenderer(SphinxRenderer): class QuickstartRenderer(SphinxRenderer):
def __init__(self, templatedir): def __init__(self, templatedir):
# type: (unicode) -> None
self.templatedir = templatedir or '' self.templatedir = templatedir or ''
super(QuickstartRenderer, self).__init__() super(QuickstartRenderer, self).__init__()
def render(self, template_name, context): def render(self, template_name, context):
# type: (unicode, Dict) -> unicode
user_template = path.join(self.templatedir, path.basename(template_name)) user_template = path.join(self.templatedir, path.basename(template_name))
if self.templatedir and path.exists(user_template): if self.templatedir and path.exists(user_template):
return self.render_from_file(user_template, context) return self.render_from_file(user_template, context)
@ -200,6 +219,7 @@ class QuickstartRenderer(SphinxRenderer):
def ask_user(d): def ask_user(d):
# type: (Dict) -> None
"""Ask the user for quickstart values missing from *d*. """Ask the user for quickstart values missing from *d*.
Values are: Values are:
@ -375,6 +395,7 @@ directly.''')
def generate(d, overwrite=True, silent=False, templatedir=None): def generate(d, overwrite=True, silent=False, templatedir=None):
# type: (Dict, bool, bool, unicode) -> None
"""Generate project based on values in *d*.""" """Generate project based on values in *d*."""
template = QuickstartRenderer(templatedir=templatedir) template = QuickstartRenderer(templatedir=templatedir)
@ -432,6 +453,7 @@ def generate(d, overwrite=True, silent=False, templatedir=None):
mkdir_p(path.join(srcdir, d['dot'] + 'static')) mkdir_p(path.join(srcdir, d['dot'] + 'static'))
def write_file(fpath, content, newline=None): def write_file(fpath, content, newline=None):
# type: (unicode, unicode, unicode) -> None
if overwrite or not path.isfile(fpath): if overwrite or not path.isfile(fpath):
print('Creating file %s.' % fpath) print('Creating file %s.' % fpath)
with open(fpath, 'wt', encoding='utf-8', newline=newline) as f: with open(fpath, 'wt', encoding='utf-8', newline=newline) as f:
@ -488,6 +510,7 @@ where "builder" is one of the supported builders, e.g. html, latex or linkcheck.
def usage(argv, msg=None): def usage(argv, msg=None):
# type: (List[unicode], unicode) -> None
if msg: if msg:
print(msg, file=sys.stderr) print(msg, file=sys.stderr)
print(file=sys.stderr) print(file=sys.stderr)
@ -504,6 +527,7 @@ For more information, visit <http://sphinx-doc.org/>.
def valid_dir(d): def valid_dir(d):
# type: (Dict) -> bool
dir = d['path'] dir = d['path']
if not path.exists(dir): if not path.exists(dir):
return True return True
@ -534,6 +558,7 @@ def valid_dir(d):
class MyFormatter(optparse.IndentedHelpFormatter): class MyFormatter(optparse.IndentedHelpFormatter):
def format_usage(self, usage): def format_usage(self, usage):
# type: (str) -> str
return usage return usage
def format_help(self, formatter): def format_help(self, formatter):
@ -546,6 +571,7 @@ class MyFormatter(optparse.IndentedHelpFormatter):
def main(argv=sys.argv): def main(argv=sys.argv):
# type: (List[str]) -> int
if not color_terminal(): if not color_terminal():
nocolor() nocolor()

View File

@ -21,6 +21,13 @@ from sphinx.util import ws_re
from sphinx.util.nodes import split_explicit_title, process_index_entry, \ from sphinx.util.nodes import split_explicit_title, process_index_entry, \
set_role_source_info set_role_source_info
if False:
# For type annotation
from typing import Any, Tuple, Type # NOQA
from docutils.parsers.rst.states import Inliner # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.environment import BuildEnvironment # NOQA
generic_docroles = { generic_docroles = {
'command': addnodes.literal_strong, 'command': addnodes.literal_strong,
@ -67,6 +74,7 @@ class XRefRole(object):
def __init__(self, fix_parens=False, lowercase=False, def __init__(self, fix_parens=False, lowercase=False,
nodeclass=None, innernodeclass=None, warn_dangling=False): nodeclass=None, innernodeclass=None, warn_dangling=False):
# type: (bool, bool, Type[nodes.Node], Type[nodes.Node], bool) -> None
self.fix_parens = fix_parens self.fix_parens = fix_parens
self.lowercase = lowercase self.lowercase = lowercase
self.warn_dangling = warn_dangling self.warn_dangling = warn_dangling
@ -76,6 +84,7 @@ class XRefRole(object):
self.innernodeclass = innernodeclass self.innernodeclass = innernodeclass
def _fix_parens(self, env, has_explicit_title, title, target): def _fix_parens(self, env, has_explicit_title, title, target):
# type: (BuildEnvironment, bool, unicode, unicode) -> Tuple[unicode, unicode]
if not has_explicit_title: if not has_explicit_title:
if title.endswith('()'): if title.endswith('()'):
# remove parentheses # remove parentheses
@ -90,6 +99,7 @@ class XRefRole(object):
def __call__(self, typ, rawtext, text, lineno, inliner, def __call__(self, typ, rawtext, text, lineno, inliner,
options={}, content=[]): options={}, content=[]):
# type: (unicode, unicode, unicode, int, Inliner, Dict, List[unicode]) -> Tuple[List[nodes.Node], List[nodes.Node]] # NOQA
env = inliner.document.settings.env env = inliner.document.settings.env
if not typ: if not typ:
typ = env.temp_data.get('default_role') typ = env.temp_data.get('default_role')
@ -100,7 +110,7 @@ class XRefRole(object):
else: else:
typ = typ.lower() typ = typ.lower()
if ':' not in typ: if ':' not in typ:
domain, role = '', typ domain, role = '', typ # type: unicode, unicode
classes = ['xref', role] classes = ['xref', role]
else: else:
domain, role = typ.split(':', 1) domain, role = typ.split(':', 1)
@ -127,7 +137,7 @@ class XRefRole(object):
refnode = self.nodeclass(rawtext, reftype=role, refdomain=domain, refnode = self.nodeclass(rawtext, reftype=role, refdomain=domain,
refexplicit=has_explicit_title) refexplicit=has_explicit_title)
# we may need the line number for warnings # we may need the line number for warnings
set_role_source_info(inliner, lineno, refnode) set_role_source_info(inliner, lineno, refnode) # type: ignore
title, target = self.process_link( title, target = self.process_link(
env, refnode, has_explicit_title, title, target) env, refnode, has_explicit_title, title, target)
# now that the target and title are finally determined, set them # now that the target and title are finally determined, set them
@ -142,6 +152,7 @@ class XRefRole(object):
# methods that can be overwritten # methods that can be overwritten
def process_link(self, env, refnode, has_explicit_title, title, target): def process_link(self, env, refnode, has_explicit_title, title, target):
# type: (BuildEnvironment, nodes.reference, bool, unicode, unicode) -> Tuple[unicode, unicode] # NOQA
"""Called after parsing title and target text, and creating the """Called after parsing title and target text, and creating the
reference node (given in *refnode*). This method can alter the reference node (given in *refnode*). This method can alter the
reference node and must return a new (or the same) ``(title, target)`` reference node and must return a new (or the same) ``(title, target)``
@ -150,6 +161,7 @@ class XRefRole(object):
return title, ws_re.sub(' ', target) return title, ws_re.sub(' ', target)
def result_nodes(self, document, env, node, is_ref): def result_nodes(self, document, env, node, is_ref):
# type: (nodes.document, BuildEnvironment, nodes.Node, bool) -> Tuple[List[nodes.Node], List[nodes.Node]] # NOQA
"""Called before returning the finished nodes. *node* is the reference """Called before returning the finished nodes. *node* is the reference
node if one was created (*is_ref* is then true), else the content node. node if one was created (*is_ref* is then true), else the content node.
This method can add other nodes and must return a ``(nodes, messages)`` This method can add other nodes and must return a ``(nodes, messages)``
@ -160,6 +172,7 @@ class XRefRole(object):
class AnyXRefRole(XRefRole): class AnyXRefRole(XRefRole):
def process_link(self, env, refnode, has_explicit_title, title, target): def process_link(self, env, refnode, has_explicit_title, title, target):
# type: (BuildEnvironment, nodes.reference, bool, unicode, unicode) -> Tuple[unicode, unicode] # NOQA
result = XRefRole.process_link(self, env, refnode, has_explicit_title, result = XRefRole.process_link(self, env, refnode, has_explicit_title,
title, target) title, target)
# add all possible context info (i.e. std:program, py:module etc.) # add all possible context info (i.e. std:program, py:module etc.)
@ -169,13 +182,14 @@ class AnyXRefRole(XRefRole):
def indexmarkup_role(typ, rawtext, text, lineno, inliner, def indexmarkup_role(typ, rawtext, text, lineno, inliner,
options={}, content=[]): options={}, content=[]):
# type: (unicode, unicode, unicode, int, Inliner, Dict, List[unicode]) -> Tuple[List[nodes.Node], List[nodes.Node]] # NOQA
"""Role for PEP/RFC references that generate an index entry.""" """Role for PEP/RFC references that generate an index entry."""
env = inliner.document.settings.env env = inliner.document.settings.env
if not typ: if not typ:
typ = env.config.default_role typ = env.config.default_role
else: else:
typ = typ.lower() typ = typ.lower()
has_explicit_title, title, target = split_explicit_title(text) # type: bool, unicode, unicode # NOQA has_explicit_title, title, target = split_explicit_title(text)
title = utils.unescape(title) title = utils.unescape(title)
target = utils.unescape(target) target = utils.unescape(target)
targetid = 'index-%s' % env.new_serialno('index') targetid = 'index-%s' % env.new_serialno('index')
@ -233,10 +247,11 @@ _amp_re = re.compile(r'(?<!&)&(?![&\s])')
def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
# type: (unicode, unicode, unicode, int, Inliner, Dict, List[unicode]) -> Tuple[List[nodes.Node], List[nodes.Node]] # NOQA
text = utils.unescape(text) text = utils.unescape(text)
if typ == 'menuselection': if typ == 'menuselection':
text = text.replace('-->', u'\N{TRIANGULAR BULLET}') text = text.replace('-->', u'\N{TRIANGULAR BULLET}')
spans = _amp_re.split(text) spans = _amp_re.split(text) # type: ignore
node = nodes.inline(rawtext=rawtext) node = nodes.inline(rawtext=rawtext)
for i, span in enumerate(spans): for i, span in enumerate(spans):
@ -263,10 +278,11 @@ _litvar_re = re.compile('{([^}]+)}')
def emph_literal_role(typ, rawtext, text, lineno, inliner, def emph_literal_role(typ, rawtext, text, lineno, inliner,
options={}, content=[]): options={}, content=[]):
# type: (unicode, unicode, unicode, int, Inliner, Dict, List[unicode]) -> Tuple[List[nodes.Node], List[nodes.Node]] # NOQA
text = utils.unescape(text) text = utils.unescape(text)
pos = 0 pos = 0
retnode = nodes.literal(role=typ.lower(), classes=[typ]) retnode = nodes.literal(role=typ.lower(), classes=[typ])
for m in _litvar_re.finditer(text): for m in _litvar_re.finditer(text): # type: ignore
if m.start() > pos: if m.start() > pos:
txt = text[pos:m.start()] txt = text[pos:m.start()]
retnode += nodes.Text(txt, txt) retnode += nodes.Text(txt, txt)
@ -281,8 +297,9 @@ _abbr_re = re.compile('\((.*)\)$', re.S)
def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
# type: (unicode, unicode, unicode, int, Inliner, Dict, List[unicode]) -> Tuple[List[nodes.Node], List[nodes.Node]] # NOQA
text = utils.unescape(text) text = utils.unescape(text)
m = _abbr_re.search(text) m = _abbr_re.search(text) # type: ignore
if m is None: if m is None:
return [addnodes.abbreviation(text, text, **options)], [] return [addnodes.abbreviation(text, text, **options)], []
abbr = text[:m.start()].strip() abbr = text[:m.start()].strip()
@ -293,6 +310,7 @@ def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
def index_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): def index_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
# type: (unicode, unicode, unicode, int, Inliner, Dict, List[unicode]) -> Tuple[List[nodes.Node], List[nodes.Node]] # NOQA
# create new reference target # create new reference target
env = inliner.document.settings.env env = inliner.document.settings.env
targetid = 'index-%s' % env.new_serialno('index') targetid = 'index-%s' % env.new_serialno('index')
@ -315,7 +333,7 @@ def index_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
entries = [('single', target, targetid, main, None)] entries = [('single', target, targetid, main, None)]
indexnode = addnodes.index() indexnode = addnodes.index()
indexnode['entries'] = entries indexnode['entries'] = entries
set_role_source_info(inliner, lineno, indexnode) set_role_source_info(inliner, lineno, indexnode) # type: ignore
textnode = nodes.Text(title, title) textnode = nodes.Text(title, title)
return [indexnode, targetnode, textnode], [] return [indexnode, targetnode, textnode], []
@ -338,6 +356,7 @@ specific_docroles = {
def setup(app): def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
from docutils.parsers.rst import roles from docutils.parsers.rst import roles
for rolename, nodeclass in iteritems(generic_docroles): for rolename, nodeclass in iteritems(generic_docroles):

View File

@ -304,6 +304,7 @@ class Locale(Transform):
# * use translated refname for section refname. # * use translated refname for section refname.
# * inline reference "`Python <...>`_" has no 'refname'. # * inline reference "`Python <...>`_" has no 'refname'.
def is_refnamed_ref(node): def is_refnamed_ref(node):
# type: (nodes.Node) -> bool
return isinstance(node, nodes.reference) and \ return isinstance(node, nodes.reference) and \
'refname' in node 'refname' in node
old_refs = node.traverse(is_refnamed_ref) old_refs = node.traverse(is_refnamed_ref)

View File

@ -239,9 +239,9 @@ def clean_astext(node):
def split_explicit_title(text): def split_explicit_title(text):
# type: (str) -> Tuple[bool, unicode, unicode] # type: (unicode) -> Tuple[bool, unicode, unicode]
"""Split role content into title and target, if given.""" """Split role content into title and target, if given."""
match = explicit_title_re.match(text) match = explicit_title_re.match(text) # type: ignore
if match: if match:
return True, match.group(1), match.group(2) return True, match.group(1), match.group(2)
return False, text, text return False, text, text

View File

@ -24,6 +24,12 @@ from sphinx.util import logging
from sphinx.util.images import get_image_size from sphinx.util.images import get_image_size
from sphinx.util.smartypants import sphinx_smarty_pants from sphinx.util.smartypants import sphinx_smarty_pants
if False:
# For type annotation
from typing import Any # NOQA
from sphinx.builders.html import StandaloneHTMLBuilder # NOQA
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# A good overview of the purpose behind these classes can be found here: # A good overview of the purpose behind these classes can be found here:
@ -39,10 +45,12 @@ class HTMLWriter(Writer):
_setting[2]['default'] = 0 _setting[2]['default'] = 0
def __init__(self, builder): def __init__(self, builder):
# type: (StandaloneHTMLBuilder) -> None
Writer.__init__(self) Writer.__init__(self)
self.builder = builder self.builder = builder
def translate(self): def translate(self):
# type: () -> None
# sadly, this is mostly copied from parent class # sadly, this is mostly copied from parent class
self.visitor = visitor = self.builder.translator_class(self.builder, self.visitor = visitor = self.builder.translator_class(self.builder,
self.document) self.document)
@ -63,6 +71,7 @@ class HTMLTranslator(BaseTranslator):
""" """
def __init__(self, builder, *args, **kwds): def __init__(self, builder, *args, **kwds):
# type: (StandaloneHTMLBuilder, Any, Any) -> None
BaseTranslator.__init__(self, *args, **kwds) BaseTranslator.__init__(self, *args, **kwds)
self.highlighter = builder.highlighter self.highlighter = builder.highlighter
self.no_smarty = 0 self.no_smarty = 0
@ -82,22 +91,28 @@ class HTMLTranslator(BaseTranslator):
self.param_separator = '' self.param_separator = ''
self.optional_param_level = 0 self.optional_param_level = 0
self._table_row_index = 0 self._table_row_index = 0
self.required_params_left = 0
def visit_start_of_file(self, node): def visit_start_of_file(self, node):
# type: (nodes.Node) -> None
# only occurs in the single-file builder # only occurs in the single-file builder
self.docnames.append(node['docname']) self.docnames.append(node['docname'])
self.body.append('<span id="document-%s"></span>' % node['docname']) self.body.append('<span id="document-%s"></span>' % node['docname'])
def depart_start_of_file(self, node): def depart_start_of_file(self, node):
# type: (nodes.Node) -> None
self.docnames.pop() self.docnames.pop()
def visit_desc(self, node): def visit_desc(self, node):
# type: (nodes.Node) -> None
self.body.append(self.starttag(node, 'dl', CLASS=node['objtype'])) self.body.append(self.starttag(node, 'dl', CLASS=node['objtype']))
def depart_desc(self, node): def depart_desc(self, node):
# type: (nodes.Node) -> None
self.body.append('</dl>\n\n') self.body.append('</dl>\n\n')
def visit_desc_signature(self, node): def visit_desc_signature(self, node):
# type: (nodes.Node) -> None
# the id is set automatically # the id is set automatically
self.body.append(self.starttag(node, 'dt')) self.body.append(self.starttag(node, 'dt'))
# anchor for per-desc interactive data # anchor for per-desc interactive data
@ -106,44 +121,56 @@ class HTMLTranslator(BaseTranslator):
self.body.append('<!--[%s]-->' % node['ids'][0]) self.body.append('<!--[%s]-->' % node['ids'][0])
def depart_desc_signature(self, node): def depart_desc_signature(self, node):
# type: (nodes.Node) -> None
if not node.get('is_multiline'): if not node.get('is_multiline'):
self.add_permalink_ref(node, _('Permalink to this definition')) self.add_permalink_ref(node, _('Permalink to this definition'))
self.body.append('</dt>\n') self.body.append('</dt>\n')
def visit_desc_signature_line(self, node): def visit_desc_signature_line(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_desc_signature_line(self, node): def depart_desc_signature_line(self, node):
# type: (nodes.Node) -> None
if node.get('add_permalink'): if node.get('add_permalink'):
# the permalink info is on the parent desc_signature node # the permalink info is on the parent desc_signature node
self.add_permalink_ref(node.parent, _('Permalink to this definition')) self.add_permalink_ref(node.parent, _('Permalink to this definition'))
self.body.append('<br />') self.body.append('<br />')
def visit_desc_addname(self, node): def visit_desc_addname(self, node):
# type: (nodes.Node) -> None
self.body.append(self.starttag(node, 'code', '', CLASS='descclassname')) self.body.append(self.starttag(node, 'code', '', CLASS='descclassname'))
def depart_desc_addname(self, node): def depart_desc_addname(self, node):
# type: (nodes.Node) -> None
self.body.append('</code>') self.body.append('</code>')
def visit_desc_type(self, node): def visit_desc_type(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_desc_type(self, node): def depart_desc_type(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_desc_returns(self, node): def visit_desc_returns(self, node):
# type: (nodes.Node) -> None
self.body.append(' &rarr; ') self.body.append(' &rarr; ')
def depart_desc_returns(self, node): def depart_desc_returns(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_desc_name(self, node): def visit_desc_name(self, node):
# type: (nodes.Node) -> None
self.body.append(self.starttag(node, 'code', '', CLASS='descname')) self.body.append(self.starttag(node, 'code', '', CLASS='descname'))
def depart_desc_name(self, node): def depart_desc_name(self, node):
# type: (nodes.Node) -> None
self.body.append('</code>') self.body.append('</code>')
def visit_desc_parameterlist(self, node): def visit_desc_parameterlist(self, node):
# type: (nodes.Node) -> None
self.body.append('<span class="sig-paren">(</span>') self.body.append('<span class="sig-paren">(</span>')
self.first_param = 1 self.first_param = 1
self.optional_param_level = 0 self.optional_param_level = 0
@ -153,6 +180,7 @@ class HTMLTranslator(BaseTranslator):
self.param_separator = node.child_text_separator self.param_separator = node.child_text_separator
def depart_desc_parameterlist(self, node): def depart_desc_parameterlist(self, node):
# type: (nodes.Node) -> None
self.body.append('<span class="sig-paren">)</span>') self.body.append('<span class="sig-paren">)</span>')
# If required parameters are still to come, then put the comma after # If required parameters are still to come, then put the comma after
@ -162,6 +190,7 @@ class HTMLTranslator(BaseTranslator):
# foo([a, ]b, c[, d]) # foo([a, ]b, c[, d])
# #
def visit_desc_parameter(self, node): def visit_desc_parameter(self, node):
# type: (nodes.Node) -> None
if self.first_param: if self.first_param:
self.first_param = 0 self.first_param = 0
elif not self.required_params_left: elif not self.required_params_left:
@ -172,39 +201,49 @@ class HTMLTranslator(BaseTranslator):
self.body.append('<em>') self.body.append('<em>')
def depart_desc_parameter(self, node): def depart_desc_parameter(self, node):
# type: (nodes.Node) -> None
if not node.hasattr('noemph'): if not node.hasattr('noemph'):
self.body.append('</em>') self.body.append('</em>')
if self.required_params_left: if self.required_params_left:
self.body.append(self.param_separator) self.body.append(self.param_separator)
def visit_desc_optional(self, node): def visit_desc_optional(self, node):
# type: (nodes.Node) -> None
self.optional_param_level += 1 self.optional_param_level += 1
self.body.append('<span class="optional">[</span>') self.body.append('<span class="optional">[</span>')
def depart_desc_optional(self, node): def depart_desc_optional(self, node):
# type: (nodes.Node) -> None
self.optional_param_level -= 1 self.optional_param_level -= 1
self.body.append('<span class="optional">]</span>') self.body.append('<span class="optional">]</span>')
def visit_desc_annotation(self, node): def visit_desc_annotation(self, node):
# type: (nodes.Node) -> None
self.body.append(self.starttag(node, 'em', '', CLASS='property')) self.body.append(self.starttag(node, 'em', '', CLASS='property'))
def depart_desc_annotation(self, node): def depart_desc_annotation(self, node):
# type: (nodes.Node) -> None
self.body.append('</em>') self.body.append('</em>')
def visit_desc_content(self, node): def visit_desc_content(self, node):
# type: (nodes.Node) -> None
self.body.append(self.starttag(node, 'dd', '')) self.body.append(self.starttag(node, 'dd', ''))
def depart_desc_content(self, node): def depart_desc_content(self, node):
# type: (nodes.Node) -> None
self.body.append('</dd>') self.body.append('</dd>')
def visit_versionmodified(self, node): def visit_versionmodified(self, node):
# type: (nodes.Node) -> None
self.body.append(self.starttag(node, 'div', CLASS=node['type'])) self.body.append(self.starttag(node, 'div', CLASS=node['type']))
def depart_versionmodified(self, node): def depart_versionmodified(self, node):
# type: (nodes.Node) -> None
self.body.append('</div>\n') self.body.append('</div>\n')
# overwritten # overwritten
def visit_reference(self, node): def visit_reference(self, node):
# type: (nodes.Node) -> None
atts = {'class': 'reference'} atts = {'class': 'reference'}
if node.get('internal') or 'refuri' not in node: if node.get('internal') or 'refuri' not in node:
atts['class'] += ' internal' atts['class'] += ' internal'
@ -234,17 +273,21 @@ class HTMLTranslator(BaseTranslator):
'.'.join(map(str, node['secnumber']))) '.'.join(map(str, node['secnumber'])))
def visit_number_reference(self, node): def visit_number_reference(self, node):
# type: (nodes.Node) -> None
self.visit_reference(node) self.visit_reference(node)
def depart_number_reference(self, node): def depart_number_reference(self, node):
# type: (nodes.Node) -> None
self.depart_reference(node) self.depart_reference(node)
# overwritten -- we don't want source comments to show up in the HTML # overwritten -- we don't want source comments to show up in the HTML
def visit_comment(self, node): def visit_comment(self, node):
# type: (nodes.Node) -> None
raise nodes.SkipNode raise nodes.SkipNode
# overwritten # overwritten
def visit_admonition(self, node, name=''): def visit_admonition(self, node, name=''):
# type: (nodes.Node, unicode) -> None
self.body.append(self.starttag( self.body.append(self.starttag(
node, 'div', CLASS=('admonition ' + name))) node, 'div', CLASS=('admonition ' + name)))
if name: if name:
@ -252,12 +295,15 @@ class HTMLTranslator(BaseTranslator):
self.set_first_last(node) self.set_first_last(node)
def visit_seealso(self, node): def visit_seealso(self, node):
# type: (nodes.Node) -> None
self.visit_admonition(node, 'seealso') self.visit_admonition(node, 'seealso')
def depart_seealso(self, node): def depart_seealso(self, node):
# type: (nodes.Node) -> None
self.depart_admonition(node) self.depart_admonition(node)
def add_secnumber(self, node): def add_secnumber(self, node):
# type: (nodes.Node) -> None
if node.get('secnumber'): if node.get('secnumber'):
self.body.append('.'.join(map(str, node['secnumber'])) + self.body.append('.'.join(map(str, node['secnumber'])) +
self.secnumber_suffix) self.secnumber_suffix)
@ -279,7 +325,9 @@ class HTMLTranslator(BaseTranslator):
self.secnumber_suffix) self.secnumber_suffix)
def add_fignumber(self, node): def add_fignumber(self, node):
# type: (nodes.Node) -> None
def append_fignumber(figtype, figure_id): def append_fignumber(figtype, figure_id):
# type: (unicode, unicode) -> None
if self.builder.name == 'singlehtml': if self.builder.name == 'singlehtml':
key = (self.docnames[-1], figtype) key = (self.docnames[-1], figtype)
else: else:
@ -296,7 +344,7 @@ class HTMLTranslator(BaseTranslator):
self.body.append(prefix % '.'.join(map(str, numbers)) + ' ') self.body.append(prefix % '.'.join(map(str, numbers)) + ' ')
self.body.append('</span>') self.body.append('</span>')
figtype = self.builder.env.domains['std'].get_figtype(node) figtype = self.builder.env.domains['std'].get_figtype(node) # type: ignore
if figtype: if figtype:
if len(node['ids']) == 0: if len(node['ids']) == 0:
msg = 'Any IDs not assigned for %s node' % node.tagname msg = 'Any IDs not assigned for %s node' % node.tagname
@ -305,11 +353,13 @@ class HTMLTranslator(BaseTranslator):
append_fignumber(figtype, node['ids'][0]) append_fignumber(figtype, node['ids'][0])
def add_permalink_ref(self, node, title): def add_permalink_ref(self, node, title):
# type: (nodes.Node, unicode) -> None
if node['ids'] and self.permalink_text and self.builder.add_permalinks: if node['ids'] and self.permalink_text and self.builder.add_permalinks:
format = u'<a class="headerlink" href="#%s" title="%s">%s</a>' format = u'<a class="headerlink" href="#%s" title="%s">%s</a>'
self.body.append(format % (node['ids'][0], title, self.permalink_text)) self.body.append(format % (node['ids'][0], title, self.permalink_text))
def generate_targets_for_listing(self, node): def generate_targets_for_listing(self, node):
# type: (nodes.Node) -> None
"""Generate hyperlink targets for listings. """Generate hyperlink targets for listings.
Original visit_bullet_list(), visit_definition_list() and visit_enumerated_list() Original visit_bullet_list(), visit_definition_list() and visit_enumerated_list()
@ -325,6 +375,7 @@ class HTMLTranslator(BaseTranslator):
# overwritten # overwritten
def visit_bullet_list(self, node): def visit_bullet_list(self, node):
# type: (nodes.Node) -> None
if len(node) == 1 and node[0].tagname == 'toctree': if len(node) == 1 and node[0].tagname == 'toctree':
# avoid emitting empty <ul></ul> # avoid emitting empty <ul></ul>
raise nodes.SkipNode raise nodes.SkipNode
@ -333,11 +384,13 @@ class HTMLTranslator(BaseTranslator):
# overwritten # overwritten
def visit_enumerated_list(self, node): def visit_enumerated_list(self, node):
# type: (nodes.Node) -> None
self.generate_targets_for_listing(node) self.generate_targets_for_listing(node)
BaseTranslator.visit_enumerated_list(self, node) BaseTranslator.visit_enumerated_list(self, node)
# overwritten # overwritten
def visit_title(self, node): def visit_title(self, node):
# type: (nodes.Node) -> None
BaseTranslator.visit_title(self, node) BaseTranslator.visit_title(self, node)
self.add_secnumber(node) self.add_secnumber(node)
self.add_fignumber(node.parent) self.add_fignumber(node.parent)
@ -345,6 +398,7 @@ class HTMLTranslator(BaseTranslator):
self.body.append('<span class="caption-text">') self.body.append('<span class="caption-text">')
def depart_title(self, node): def depart_title(self, node):
# type: (nodes.Node) -> None
close_tag = self.context[-1] close_tag = self.context[-1]
if (self.permalink_text and self.builder.add_permalinks and if (self.permalink_text and self.builder.add_permalinks and
node.parent.hasattr('ids') and node.parent['ids']): node.parent.hasattr('ids') and node.parent['ids']):
@ -367,6 +421,7 @@ class HTMLTranslator(BaseTranslator):
# overwritten # overwritten
def visit_literal_block(self, node): def visit_literal_block(self, node):
# type: (nodes.Node) -> None
if node.rawsource != node.astext(): if node.rawsource != node.astext():
# most probably a parsed-literal block -- don't highlight # most probably a parsed-literal block -- don't highlight
return BaseTranslator.visit_literal_block(self, node) return BaseTranslator.visit_literal_block(self, node)
@ -396,6 +451,7 @@ class HTMLTranslator(BaseTranslator):
raise nodes.SkipNode raise nodes.SkipNode
def visit_caption(self, node): def visit_caption(self, node):
# type: (nodes.Node) -> None
if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'): if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'):
self.body.append('<div class="code-block-caption">') self.body.append('<div class="code-block-caption">')
else: else:
@ -404,6 +460,7 @@ class HTMLTranslator(BaseTranslator):
self.body.append(self.starttag(node, 'span', '', CLASS='caption-text')) self.body.append(self.starttag(node, 'span', '', CLASS='caption-text'))
def depart_caption(self, node): def depart_caption(self, node):
# type: (nodes.Node) -> None
self.body.append('</span>') self.body.append('</span>')
# append permalink if available # append permalink if available
@ -422,26 +479,32 @@ class HTMLTranslator(BaseTranslator):
BaseTranslator.depart_caption(self, node) BaseTranslator.depart_caption(self, node)
def visit_doctest_block(self, node): def visit_doctest_block(self, node):
# type: (nodes.Node) -> None
self.visit_literal_block(node) self.visit_literal_block(node)
# overwritten to add the <div> (for XHTML compliance) # overwritten to add the <div> (for XHTML compliance)
def visit_block_quote(self, node): def visit_block_quote(self, node):
# type: (nodes.Node) -> None
self.body.append(self.starttag(node, 'blockquote') + '<div>') self.body.append(self.starttag(node, 'blockquote') + '<div>')
def depart_block_quote(self, node): def depart_block_quote(self, node):
# type: (nodes.Node) -> None
self.body.append('</div></blockquote>\n') self.body.append('</div></blockquote>\n')
# overwritten # overwritten
def visit_literal(self, node): def visit_literal(self, node):
# type: (nodes.Node) -> None
self.body.append(self.starttag(node, 'code', '', self.body.append(self.starttag(node, 'code', '',
CLASS='docutils literal')) CLASS='docutils literal'))
self.protect_literal_text += 1 self.protect_literal_text += 1
def depart_literal(self, node): def depart_literal(self, node):
# type: (nodes.Node) -> None
self.protect_literal_text -= 1 self.protect_literal_text -= 1
self.body.append('</code>') self.body.append('</code>')
def visit_productionlist(self, node): def visit_productionlist(self, node):
# type: (nodes.Node) -> None
self.body.append(self.starttag(node, 'pre')) self.body.append(self.starttag(node, 'pre'))
names = [] names = []
for production in node: for production in node:
@ -461,23 +524,29 @@ class HTMLTranslator(BaseTranslator):
raise nodes.SkipNode raise nodes.SkipNode
def depart_productionlist(self, node): def depart_productionlist(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_production(self, node): def visit_production(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_production(self, node): def depart_production(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_centered(self, node): def visit_centered(self, node):
# type: (nodes.Node) -> None
self.body.append(self.starttag(node, 'p', CLASS="centered") + self.body.append(self.starttag(node, 'p', CLASS="centered") +
'<strong>') '<strong>')
def depart_centered(self, node): def depart_centered(self, node):
# type: (nodes.Node) -> None
self.body.append('</strong></p>') self.body.append('</strong></p>')
# overwritten # overwritten
def should_be_compact_paragraph(self, node): def should_be_compact_paragraph(self, node):
# type: (nodes.Node) -> bool
"""Determine if the <p> tags around paragraph can be omitted.""" """Determine if the <p> tags around paragraph can be omitted."""
if isinstance(node.parent, addnodes.desc_content): if isinstance(node.parent, addnodes.desc_content):
# Never compact desc_content items. # Never compact desc_content items.
@ -488,19 +557,24 @@ class HTMLTranslator(BaseTranslator):
return BaseTranslator.should_be_compact_paragraph(self, node) return BaseTranslator.should_be_compact_paragraph(self, node)
def visit_compact_paragraph(self, node): def visit_compact_paragraph(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_compact_paragraph(self, node): def depart_compact_paragraph(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_highlightlang(self, node): def visit_highlightlang(self, node):
# type: (nodes.Node) -> None
self.highlightlang = node['lang'] self.highlightlang = node['lang']
self.highlightlinenothreshold = node['linenothreshold'] self.highlightlinenothreshold = node['linenothreshold']
def depart_highlightlang(self, node): def depart_highlightlang(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_download_reference(self, node): def visit_download_reference(self, node):
# type: (nodes.Node) -> None
if self.builder.download_support and node.hasattr('filename'): if self.builder.download_support and node.hasattr('filename'):
self.body.append( self.body.append(
'<a class="reference download internal" href="%s" download="">' % '<a class="reference download internal" href="%s" download="">' %
@ -510,10 +584,12 @@ class HTMLTranslator(BaseTranslator):
self.context.append('') self.context.append('')
def depart_download_reference(self, node): def depart_download_reference(self, node):
# type: (nodes.Node) -> None
self.body.append(self.context.pop()) self.body.append(self.context.pop())
# overwritten # overwritten
def visit_image(self, node): def visit_image(self, node):
# type: (nodes.Node) -> None
olduri = node['uri'] olduri = node['uri']
# rewrite the URI if the environment knows about it # rewrite the URI if the environment knows about it
if olduri in self.builder.images: if olduri in self.builder.images:
@ -555,51 +631,65 @@ class HTMLTranslator(BaseTranslator):
# overwritten # overwritten
def depart_image(self, node): def depart_image(self, node):
# type: (nodes.Node) -> None
if node['uri'].lower().endswith(('svg', 'svgz')): if node['uri'].lower().endswith(('svg', 'svgz')):
self.body.append(self.context.pop()) self.body.append(self.context.pop())
else: else:
BaseTranslator.depart_image(self, node) BaseTranslator.depart_image(self, node)
def visit_toctree(self, node): def visit_toctree(self, node):
# type: (nodes.Node) -> None
# this only happens when formatting a toc from env.tocs -- in this # this only happens when formatting a toc from env.tocs -- in this
# case we don't want to include the subtree # case we don't want to include the subtree
raise nodes.SkipNode raise nodes.SkipNode
def visit_index(self, node): def visit_index(self, node):
# type: (nodes.Node) -> None
raise nodes.SkipNode raise nodes.SkipNode
def visit_tabular_col_spec(self, node): def visit_tabular_col_spec(self, node):
# type: (nodes.Node) -> None
raise nodes.SkipNode raise nodes.SkipNode
def visit_glossary(self, node): def visit_glossary(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_glossary(self, node): def depart_glossary(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_acks(self, node): def visit_acks(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_acks(self, node): def depart_acks(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_hlist(self, node): def visit_hlist(self, node):
# type: (nodes.Node) -> None
self.body.append('<table class="hlist"><tr>') self.body.append('<table class="hlist"><tr>')
def depart_hlist(self, node): def depart_hlist(self, node):
# type: (nodes.Node) -> None
self.body.append('</tr></table>\n') self.body.append('</tr></table>\n')
def visit_hlistcol(self, node): def visit_hlistcol(self, node):
# type: (nodes.Node) -> None
self.body.append('<td>') self.body.append('<td>')
def depart_hlistcol(self, node): def depart_hlistcol(self, node):
# type: (nodes.Node) -> None
self.body.append('</td>') self.body.append('</td>')
def bulk_text_processor(self, text): def bulk_text_processor(self, text):
# type: (unicode) -> unicode
return text return text
# overwritten # overwritten
def visit_Text(self, node): def visit_Text(self, node):
# type: (nodes.Node) -> None
text = node.astext() text = node.astext()
encoded = self.encode(text) encoded = self.encode(text)
if self.protect_literal_text: if self.protect_literal_text:
@ -623,94 +713,122 @@ class HTMLTranslator(BaseTranslator):
self.body.append(encoded) self.body.append(encoded)
def visit_note(self, node): def visit_note(self, node):
# type: (nodes.Node) -> None
self.visit_admonition(node, 'note') self.visit_admonition(node, 'note')
def depart_note(self, node): def depart_note(self, node):
# type: (nodes.Node) -> None
self.depart_admonition(node) self.depart_admonition(node)
def visit_warning(self, node): def visit_warning(self, node):
# type: (nodes.Node) -> None
self.visit_admonition(node, 'warning') self.visit_admonition(node, 'warning')
def depart_warning(self, node): def depart_warning(self, node):
# type: (nodes.Node) -> None
self.depart_admonition(node) self.depart_admonition(node)
def visit_attention(self, node): def visit_attention(self, node):
# type: (nodes.Node) -> None
self.visit_admonition(node, 'attention') self.visit_admonition(node, 'attention')
def depart_attention(self, node): def depart_attention(self, node):
# type: (nodes.Node) -> None
self.depart_admonition() self.depart_admonition()
def visit_caution(self, node): def visit_caution(self, node):
# type: (nodes.Node) -> None
self.visit_admonition(node, 'caution') self.visit_admonition(node, 'caution')
def depart_caution(self, node): def depart_caution(self, node):
# type: (nodes.Node) -> None
self.depart_admonition() self.depart_admonition()
def visit_danger(self, node): def visit_danger(self, node):
# type: (nodes.Node) -> None
self.visit_admonition(node, 'danger') self.visit_admonition(node, 'danger')
def depart_danger(self, node): def depart_danger(self, node):
# type: (nodes.Node) -> None
self.depart_admonition() self.depart_admonition()
def visit_error(self, node): def visit_error(self, node):
# type: (nodes.Node) -> None
self.visit_admonition(node, 'error') self.visit_admonition(node, 'error')
def depart_error(self, node): def depart_error(self, node):
# type: (nodes.Node) -> None
self.depart_admonition() self.depart_admonition()
def visit_hint(self, node): def visit_hint(self, node):
# type: (nodes.Node) -> None
self.visit_admonition(node, 'hint') self.visit_admonition(node, 'hint')
def depart_hint(self, node): def depart_hint(self, node):
# type: (nodes.Node) -> None
self.depart_admonition() self.depart_admonition()
def visit_important(self, node): def visit_important(self, node):
# type: (nodes.Node) -> None
self.visit_admonition(node, 'important') self.visit_admonition(node, 'important')
def depart_important(self, node): def depart_important(self, node):
# type: (nodes.Node) -> None
self.depart_admonition() self.depart_admonition()
def visit_tip(self, node): def visit_tip(self, node):
# type: (nodes.Node) -> None
self.visit_admonition(node, 'tip') self.visit_admonition(node, 'tip')
def depart_tip(self, node): def depart_tip(self, node):
# type: (nodes.Node) -> None
self.depart_admonition() self.depart_admonition()
# these are only handled specially in the SmartyPantsHTMLTranslator # these are only handled specially in the SmartyPantsHTMLTranslator
def visit_literal_emphasis(self, node): def visit_literal_emphasis(self, node):
# type: (nodes.Node) -> None
return self.visit_emphasis(node) return self.visit_emphasis(node)
def depart_literal_emphasis(self, node): def depart_literal_emphasis(self, node):
# type: (nodes.Node) -> None
return self.depart_emphasis(node) return self.depart_emphasis(node)
def visit_literal_strong(self, node): def visit_literal_strong(self, node):
# type: (nodes.Node) -> None
return self.visit_strong(node) return self.visit_strong(node)
def depart_literal_strong(self, node): def depart_literal_strong(self, node):
# type: (nodes.Node) -> None
return self.depart_strong(node) return self.depart_strong(node)
def visit_abbreviation(self, node): def visit_abbreviation(self, node):
# type: (nodes.Node) -> None
attrs = {} attrs = {}
if node.hasattr('explanation'): if node.hasattr('explanation'):
attrs['title'] = node['explanation'] attrs['title'] = node['explanation']
self.body.append(self.starttag(node, 'abbr', '', **attrs)) self.body.append(self.starttag(node, 'abbr', '', **attrs))
def depart_abbreviation(self, node): def depart_abbreviation(self, node):
# type: (nodes.Node) -> None
self.body.append('</abbr>') self.body.append('</abbr>')
def visit_manpage(self, node): def visit_manpage(self, node):
return self.visit_literal_emphasis(node) # type: (nodes.Node) -> None
self.visit_literal_emphasis(node)
def depart_manpage(self, node): def depart_manpage(self, node):
return self.depart_literal_emphasis(node) # type: (nodes.Node) -> None
self.depart_literal_emphasis(node)
# overwritten to add even/odd classes # overwritten to add even/odd classes
def visit_table(self, node): def visit_table(self, node):
# type: (nodes.Node) -> None
self._table_row_index = 0 self._table_row_index = 0
return BaseTranslator.visit_table(self, node) return BaseTranslator.visit_table(self, node)
def visit_row(self, node): def visit_row(self, node):
# type: (nodes.Node) -> None
self._table_row_index += 1 self._table_row_index += 1
if self._table_row_index % 2 == 0: if self._table_row_index % 2 == 0:
node['classes'].append('row-even') node['classes'].append('row-even')
@ -720,10 +838,12 @@ class HTMLTranslator(BaseTranslator):
node.column = 0 node.column = 0
def visit_field_list(self, node): def visit_field_list(self, node):
# type: (nodes.Node) -> None
self._fieldlist_row_index = 0 self._fieldlist_row_index = 0
return BaseTranslator.visit_field_list(self, node) return BaseTranslator.visit_field_list(self, node)
def visit_field(self, node): def visit_field(self, node):
# type: (nodes.Node) -> None
self._fieldlist_row_index += 1 self._fieldlist_row_index += 1
if self._fieldlist_row_index % 2 == 0: if self._fieldlist_row_index % 2 == 0:
node['classes'].append('field-even') node['classes'].append('field-even')
@ -732,6 +852,7 @@ class HTMLTranslator(BaseTranslator):
self.body.append(self.starttag(node, 'tr', '', CLASS='field')) self.body.append(self.starttag(node, 'tr', '', CLASS='field'))
def visit_math(self, node, math_env=''): def visit_math(self, node, math_env=''):
# type: (nodes.Node, unicode) -> None
logger.warning('using "math" markup without a Sphinx math extension ' logger.warning('using "math" markup without a Sphinx math extension '
'active, please use one of the math extensions ' 'active, please use one of the math extensions '
'described at http://sphinx-doc.org/ext/math.html', 'described at http://sphinx-doc.org/ext/math.html',
@ -739,6 +860,7 @@ class HTMLTranslator(BaseTranslator):
raise nodes.SkipNode raise nodes.SkipNode
def unknown_visit(self, node): def unknown_visit(self, node):
# type: (nodes.Node) -> None
raise NotImplementedError('Unknown node: ' + node.__class__.__name__) raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
@ -749,10 +871,12 @@ class SmartyPantsHTMLTranslator(HTMLTranslator):
""" """
def __init__(self, *args, **kwds): def __init__(self, *args, **kwds):
# type: (Any, Any) -> None
self.no_smarty = 0 self.no_smarty = 0
HTMLTranslator.__init__(self, *args, **kwds) HTMLTranslator.__init__(self, *args, **kwds)
def visit_literal(self, node): def visit_literal(self, node):
# type: (nodes.Node) -> None
self.no_smarty += 1 self.no_smarty += 1
try: try:
# this raises SkipNode # this raises SkipNode
@ -761,6 +885,7 @@ class SmartyPantsHTMLTranslator(HTMLTranslator):
self.no_smarty -= 1 self.no_smarty -= 1
def visit_literal_block(self, node): def visit_literal_block(self, node):
# type: (nodes.Node) -> None
self.no_smarty += 1 self.no_smarty += 1
try: try:
HTMLTranslator.visit_literal_block(self, node) HTMLTranslator.visit_literal_block(self, node)
@ -771,34 +896,42 @@ class SmartyPantsHTMLTranslator(HTMLTranslator):
raise raise
def depart_literal_block(self, node): def depart_literal_block(self, node):
# type: (nodes.Node) -> None
HTMLTranslator.depart_literal_block(self, node) HTMLTranslator.depart_literal_block(self, node)
self.no_smarty -= 1 self.no_smarty -= 1
def visit_literal_emphasis(self, node): def visit_literal_emphasis(self, node):
# type: (nodes.Node) -> None
self.no_smarty += 1 self.no_smarty += 1
self.visit_emphasis(node) self.visit_emphasis(node)
def depart_literal_emphasis(self, node): def depart_literal_emphasis(self, node):
# type: (nodes.Node) -> None
self.depart_emphasis(node) self.depart_emphasis(node)
self.no_smarty -= 1 self.no_smarty -= 1
def visit_literal_strong(self, node): def visit_literal_strong(self, node):
# type: (nodes.Node) -> None
self.no_smarty += 1 self.no_smarty += 1
self.visit_strong(node) self.visit_strong(node)
def depart_literal_strong(self, node): def depart_literal_strong(self, node):
# type: (nodes.Node) -> None
self.depart_strong(node) self.depart_strong(node)
self.no_smarty -= 1 self.no_smarty -= 1
def visit_desc_signature(self, node): def visit_desc_signature(self, node):
# type: (nodes.Node) -> None
self.no_smarty += 1 self.no_smarty += 1
HTMLTranslator.visit_desc_signature(self, node) HTMLTranslator.visit_desc_signature(self, node)
def depart_desc_signature(self, node): def depart_desc_signature(self, node):
# type: (nodes.Node) -> None
self.no_smarty -= 1 self.no_smarty -= 1
HTMLTranslator.depart_desc_signature(self, node) HTMLTranslator.depart_desc_signature(self, node)
def visit_productionlist(self, node): def visit_productionlist(self, node):
# type: (nodes.Node) -> None
self.no_smarty += 1 self.no_smarty += 1
try: try:
HTMLTranslator.visit_productionlist(self, node) HTMLTranslator.visit_productionlist(self, node)
@ -806,14 +939,17 @@ class SmartyPantsHTMLTranslator(HTMLTranslator):
self.no_smarty -= 1 self.no_smarty -= 1
def visit_option(self, node): def visit_option(self, node):
# type: (nodes.Node) -> None
self.no_smarty += 1 self.no_smarty += 1
HTMLTranslator.visit_option(self, node) HTMLTranslator.visit_option(self, node)
def depart_option(self, node): def depart_option(self, node):
# type: (nodes.Node) -> None
self.no_smarty -= 1 self.no_smarty -= 1
HTMLTranslator.depart_option(self, node) HTMLTranslator.depart_option(self, node)
def bulk_text_processor(self, text): def bulk_text_processor(self, text):
# type: (unicode) -> unicode
if self.no_smarty <= 0: if self.no_smarty <= 0:
return sphinx_smarty_pants(text) return sphinx_smarty_pants(text)
return text return text

View File

@ -1794,6 +1794,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('\\end{sphinxadmonition}\n') self.body.append('\\end{sphinxadmonition}\n')
def _make_visit_admonition(name): def _make_visit_admonition(name):
# type: (unicode) -> Callable[[LaTeXTranslator, nodes.Node], None]
def visit_admonition(self, node): def visit_admonition(self, node):
# type: (nodes.Node) -> None # type: (nodes.Node) -> None
self.body.append(u'\n\\begin{sphinxadmonition}{%s}{%s:}' % self.body.append(u'\n\\begin{sphinxadmonition}{%s}{%s:}' %

View File

@ -22,17 +22,24 @@ from sphinx.util import logging
import sphinx.util.docutils import sphinx.util.docutils
from sphinx.util.i18n import format_date from sphinx.util.i18n import format_date
if False:
# For type annotation
from typing import Any # NOQA
from sphinx.builders import Builder # NOQA
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class ManualPageWriter(Writer): class ManualPageWriter(Writer):
def __init__(self, builder): def __init__(self, builder):
# type: (Builder) -> None
Writer.__init__(self) Writer.__init__(self)
self.builder = builder self.builder = builder
self.translator_class = ( self.translator_class = (
self.builder.translator_class or ManualPageTranslator) self.builder.translator_class or ManualPageTranslator)
def translate(self): def translate(self):
# type: () -> None
transform = NestedInlineTransform(self.document) transform = NestedInlineTransform(self.document)
transform.apply() transform.apply()
visitor = self.translator_class(self.builder, self.document) visitor = self.translator_class(self.builder, self.document)
@ -53,10 +60,13 @@ class NestedInlineTransform(object):
<strong>&bar=</strong><emphasis>2</emphasis> <strong>&bar=</strong><emphasis>2</emphasis>
""" """
def __init__(self, document): def __init__(self, document):
# type: (nodes.document) -> None
self.document = document self.document = document
def apply(self): def apply(self):
# type: () -> None
def is_inline(node): def is_inline(node):
# type: (nodes.Node) -> bool
return isinstance(node, (nodes.literal, nodes.emphasis, nodes.strong)) return isinstance(node, (nodes.literal, nodes.emphasis, nodes.strong))
for node in self.document.traverse(is_inline): for node in self.document.traverse(is_inline):
@ -77,6 +87,7 @@ class ManualPageTranslator(BaseTranslator):
""" """
def __init__(self, builder, *args, **kwds): def __init__(self, builder, *args, **kwds):
# type: (Builder, Any, Any) -> None
BaseTranslator.__init__(self, *args, **kwds) BaseTranslator.__init__(self, *args, **kwds)
self.builder = builder self.builder = builder
@ -114,6 +125,7 @@ class ManualPageTranslator(BaseTranslator):
# overwritten -- added quotes around all .TH arguments # overwritten -- added quotes around all .TH arguments
def header(self): def header(self):
# type: () -> unicode
tmpl = (".TH \"%(title_upper)s\" \"%(manual_section)s\"" tmpl = (".TH \"%(title_upper)s\" \"%(manual_section)s\""
" \"%(date)s\" \"%(version)s\" \"%(manual_group)s\"\n" " \"%(date)s\" \"%(version)s\" \"%(manual_group)s\"\n"
".SH NAME\n" ".SH NAME\n"
@ -121,96 +133,125 @@ class ManualPageTranslator(BaseTranslator):
return tmpl % self._docinfo return tmpl % self._docinfo
def visit_start_of_file(self, node): def visit_start_of_file(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_start_of_file(self, node): def depart_start_of_file(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_desc(self, node): def visit_desc(self, node):
# type: (nodes.Node) -> None
self.visit_definition_list(node) self.visit_definition_list(node)
def depart_desc(self, node): def depart_desc(self, node):
# type: (nodes.Node) -> None
self.depart_definition_list(node) self.depart_definition_list(node)
def visit_desc_signature(self, node): def visit_desc_signature(self, node):
# type: (nodes.Node) -> None
self.visit_definition_list_item(node) self.visit_definition_list_item(node)
self.visit_term(node) self.visit_term(node)
def depart_desc_signature(self, node): def depart_desc_signature(self, node):
# type: (nodes.Node) -> None
self.depart_term(node) self.depart_term(node)
def visit_desc_signature_line(self, node): def visit_desc_signature_line(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_desc_signature_line(self, node): def depart_desc_signature_line(self, node):
# type: (nodes.Node) -> None
self.body.append(' ') self.body.append(' ')
def visit_desc_addname(self, node): def visit_desc_addname(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_desc_addname(self, node): def depart_desc_addname(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_desc_type(self, node): def visit_desc_type(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_desc_type(self, node): def depart_desc_type(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_desc_returns(self, node): def visit_desc_returns(self, node):
# type: (nodes.Node) -> None
self.body.append(' -> ') self.body.append(' -> ')
def depart_desc_returns(self, node): def depart_desc_returns(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_desc_name(self, node): def visit_desc_name(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_desc_name(self, node): def depart_desc_name(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_desc_parameterlist(self, node): def visit_desc_parameterlist(self, node):
# type: (nodes.Node) -> None
self.body.append('(') self.body.append('(')
self.first_param = 1 self.first_param = 1
def depart_desc_parameterlist(self, node): def depart_desc_parameterlist(self, node):
# type: (nodes.Node) -> None
self.body.append(')') self.body.append(')')
def visit_desc_parameter(self, node): def visit_desc_parameter(self, node):
# type: (nodes.Node) -> None
if not self.first_param: if not self.first_param:
self.body.append(', ') self.body.append(', ')
else: else:
self.first_param = 0 self.first_param = 0
def depart_desc_parameter(self, node): def depart_desc_parameter(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_desc_optional(self, node): def visit_desc_optional(self, node):
# type: (nodes.Node) -> None
self.body.append('[') self.body.append('[')
def depart_desc_optional(self, node): def depart_desc_optional(self, node):
# type: (nodes.Node) -> None
self.body.append(']') self.body.append(']')
def visit_desc_annotation(self, node): def visit_desc_annotation(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_desc_annotation(self, node): def depart_desc_annotation(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_desc_content(self, node): def visit_desc_content(self, node):
# type: (nodes.Node) -> None
self.visit_definition(node) self.visit_definition(node)
def depart_desc_content(self, node): def depart_desc_content(self, node):
# type: (nodes.Node) -> None
self.depart_definition(node) self.depart_definition(node)
def visit_versionmodified(self, node): def visit_versionmodified(self, node):
# type: (nodes.Node) -> None
self.visit_paragraph(node) self.visit_paragraph(node)
def depart_versionmodified(self, node): def depart_versionmodified(self, node):
# type: (nodes.Node) -> None
self.depart_paragraph(node) self.depart_paragraph(node)
# overwritten -- don't make whole of term bold if it includes strong node # overwritten -- don't make whole of term bold if it includes strong node
def visit_term(self, node): def visit_term(self, node):
# type: (nodes.Node) -> None
if node.traverse(nodes.strong): if node.traverse(nodes.strong):
self.body.append('\n') self.body.append('\n')
else: else:
@ -218,15 +259,18 @@ class ManualPageTranslator(BaseTranslator):
# overwritten -- we don't want source comments to show up # overwritten -- we don't want source comments to show up
def visit_comment(self, node): def visit_comment(self, node):
# type: (nodes.Node) -> None
raise nodes.SkipNode raise nodes.SkipNode
# overwritten -- added ensure_eol() # overwritten -- added ensure_eol()
def visit_footnote(self, node): def visit_footnote(self, node):
# type: (nodes.Node) -> None
self.ensure_eol() self.ensure_eol()
BaseTranslator.visit_footnote(self, node) BaseTranslator.visit_footnote(self, node)
# overwritten -- handle footnotes rubric # overwritten -- handle footnotes rubric
def visit_rubric(self, node): def visit_rubric(self, node):
# type: (nodes.Node) -> None
self.ensure_eol() self.ensure_eol()
if len(node.children) == 1: if len(node.children) == 1:
rubtitle = node.children[0].astext() rubtitle = node.children[0].astext()
@ -238,15 +282,19 @@ class ManualPageTranslator(BaseTranslator):
self.body.append('.sp\n') self.body.append('.sp\n')
def depart_rubric(self, node): def depart_rubric(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_seealso(self, node): def visit_seealso(self, node):
# type: (nodes.Node) -> None
self.visit_admonition(node, 'seealso') self.visit_admonition(node, 'seealso')
def depart_seealso(self, node): def depart_seealso(self, node):
# type: (nodes.Node) -> None
self.depart_admonition(node) self.depart_admonition(node)
def visit_productionlist(self, node): def visit_productionlist(self, node):
# type: (nodes.Node) -> None
self.ensure_eol() self.ensure_eol()
names = [] names = []
self.in_productionlist += 1 self.in_productionlist += 1
@ -271,13 +319,16 @@ class ManualPageTranslator(BaseTranslator):
raise nodes.SkipNode raise nodes.SkipNode
def visit_production(self, node): def visit_production(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_production(self, node): def depart_production(self, node):
# type: (nodes.Node) -> None
pass pass
# overwritten -- don't emit a warning for images # overwritten -- don't emit a warning for images
def visit_image(self, node): def visit_image(self, node):
# type: (nodes.Node) -> None
if 'alt' in node.attributes: if 'alt' in node.attributes:
self.body.append(_('[image: %s]') % node['alt'] + '\n') self.body.append(_('[image: %s]') % node['alt'] + '\n')
self.body.append(_('[image]') + '\n') self.body.append(_('[image]') + '\n')
@ -285,6 +336,7 @@ class ManualPageTranslator(BaseTranslator):
# overwritten -- don't visit inner marked up nodes # overwritten -- don't visit inner marked up nodes
def visit_reference(self, node): def visit_reference(self, node):
# type: (nodes.Node) -> None
self.body.append(self.defs['reference'][0]) self.body.append(self.defs['reference'][0])
# avoid repeating escaping code... fine since # avoid repeating escaping code... fine since
# visit_Text calls astext() and only works on that afterwards # visit_Text calls astext() and only works on that afterwards
@ -306,51 +358,66 @@ class ManualPageTranslator(BaseTranslator):
raise nodes.SkipNode raise nodes.SkipNode
def visit_number_reference(self, node): def visit_number_reference(self, node):
# type: (nodes.Node) -> None
text = nodes.Text(node.get('title', '#')) text = nodes.Text(node.get('title', '#'))
self.visit_Text(text) self.visit_Text(text)
raise nodes.SkipNode raise nodes.SkipNode
def visit_centered(self, node): def visit_centered(self, node):
# type: (nodes.Node) -> None
self.ensure_eol() self.ensure_eol()
self.body.append('.sp\n.ce\n') self.body.append('.sp\n.ce\n')
def depart_centered(self, node): def depart_centered(self, node):
# type: (nodes.Node) -> None
self.body.append('\n.ce 0\n') self.body.append('\n.ce 0\n')
def visit_compact_paragraph(self, node): def visit_compact_paragraph(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_compact_paragraph(self, node): def depart_compact_paragraph(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_highlightlang(self, node): def visit_highlightlang(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_highlightlang(self, node): def depart_highlightlang(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_download_reference(self, node): def visit_download_reference(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_download_reference(self, node): def depart_download_reference(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_toctree(self, node): def visit_toctree(self, node):
# type: (nodes.Node) -> None
raise nodes.SkipNode raise nodes.SkipNode
def visit_index(self, node): def visit_index(self, node):
# type: (nodes.Node) -> None
raise nodes.SkipNode raise nodes.SkipNode
def visit_tabular_col_spec(self, node): def visit_tabular_col_spec(self, node):
# type: (nodes.Node) -> None
raise nodes.SkipNode raise nodes.SkipNode
def visit_glossary(self, node): def visit_glossary(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_glossary(self, node): def depart_glossary(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_acks(self, node): def visit_acks(self, node):
# type: (nodes.Node) -> None
self.ensure_eol() self.ensure_eol()
self.body.append(', '.join(n.astext() self.body.append(', '.join(n.astext()
for n in node.children[0].children) + '.') for n in node.children[0].children) + '.')
@ -358,43 +425,56 @@ class ManualPageTranslator(BaseTranslator):
raise nodes.SkipNode raise nodes.SkipNode
def visit_hlist(self, node): def visit_hlist(self, node):
# type: (nodes.Node) -> None
self.visit_bullet_list(node) self.visit_bullet_list(node)
def depart_hlist(self, node): def depart_hlist(self, node):
# type: (nodes.Node) -> None
self.depart_bullet_list(node) self.depart_bullet_list(node)
def visit_hlistcol(self, node): def visit_hlistcol(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_hlistcol(self, node): def depart_hlistcol(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_literal_emphasis(self, node): def visit_literal_emphasis(self, node):
# type: (nodes.Node) -> None
return self.visit_emphasis(node) return self.visit_emphasis(node)
def depart_literal_emphasis(self, node): def depart_literal_emphasis(self, node):
# type: (nodes.Node) -> None
return self.depart_emphasis(node) return self.depart_emphasis(node)
def visit_literal_strong(self, node): def visit_literal_strong(self, node):
# type: (nodes.Node) -> None
return self.visit_strong(node) return self.visit_strong(node)
def depart_literal_strong(self, node): def depart_literal_strong(self, node):
# type: (nodes.Node) -> None
return self.depart_strong(node) return self.depart_strong(node)
def visit_abbreviation(self, node): def visit_abbreviation(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_abbreviation(self, node): def depart_abbreviation(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_manpage(self, node): def visit_manpage(self, node):
# type: (nodes.Node) -> None
return self.visit_strong(node) return self.visit_strong(node)
def depart_manpage(self, node): def depart_manpage(self, node):
# type: (nodes.Node) -> None
return self.depart_strong(node) return self.depart_strong(node)
# overwritten: handle section titles better than in 0.6 release # overwritten: handle section titles better than in 0.6 release
def visit_title(self, node): def visit_title(self, node):
# type: (nodes.Node) -> None
if isinstance(node.parent, addnodes.seealso): if isinstance(node.parent, addnodes.seealso):
self.body.append('.IP "') self.body.append('.IP "')
return return
@ -409,26 +489,32 @@ class ManualPageTranslator(BaseTranslator):
return BaseTranslator.visit_title(self, node) return BaseTranslator.visit_title(self, node)
def depart_title(self, node): def depart_title(self, node):
# type: (nodes.Node) -> None
if isinstance(node.parent, addnodes.seealso): if isinstance(node.parent, addnodes.seealso):
self.body.append('"\n') self.body.append('"\n')
return return
return BaseTranslator.depart_title(self, node) return BaseTranslator.depart_title(self, node)
def visit_raw(self, node): def visit_raw(self, node):
# type: (nodes.Node) -> None
if 'manpage' in node.get('format', '').split(): if 'manpage' in node.get('format', '').split():
self.body.append(node.astext()) self.body.append(node.astext())
raise nodes.SkipNode raise nodes.SkipNode
def visit_meta(self, node): def visit_meta(self, node):
# type: (nodes.Node) -> None
raise nodes.SkipNode raise nodes.SkipNode
def visit_inline(self, node): def visit_inline(self, node):
# type: (nodes.Node) -> None
pass pass
def depart_inline(self, node): def depart_inline(self, node):
# type: (nodes.Node) -> None
pass pass
def visit_math(self, node): def visit_math(self, node):
# type: (nodes.Node) -> None
logger.warning('using "math" markup without a Sphinx math extension ' logger.warning('using "math" markup without a Sphinx math extension '
'active, please use one of the math extensions ' 'active, please use one of the math extensions '
'described at http://sphinx-doc.org/ext/math.html') 'described at http://sphinx-doc.org/ext/math.html')
@ -437,4 +523,5 @@ class ManualPageTranslator(BaseTranslator):
visit_math_block = visit_math visit_math_block = visit_math
def unknown_visit(self, node): def unknown_visit(self, node):
# type: (nodes.Node) -> None
raise NotImplementedError('Unknown node: ' + node.__class__.__name__) raise NotImplementedError('Unknown node: ' + node.__class__.__name__)

View File

@ -1055,6 +1055,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
pass pass
def visit_term(self, node): def visit_term(self, node):
# type: (nodes.Node) -> None
for id in node.get('ids'): for id in node.get('ids'):
self.add_anchor(id, node) self.add_anchor(id, node)
# anchors and indexes need to go in front # anchors and indexes need to go in front
@ -1209,6 +1210,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
'@end cartouche\n') '@end cartouche\n')
def _make_visit_admonition(name): def _make_visit_admonition(name):
# type: (unicode) -> Callable[[TexinfoTranslator, nodes.Node], None]
def visit(self, node): def visit(self, node):
# type: (nodes.Node) -> None # type: (nodes.Node) -> None
self.visit_admonition(node, admonitionlabels[name]) self.visit_admonition(node, admonitionlabels[name])

View File

@ -863,6 +863,7 @@ class TextTranslator(nodes.NodeVisitor):
self.add_text(self.nl) self.add_text(self.nl)
def _make_depart_admonition(name): def _make_depart_admonition(name):
# type: (unicode) -> Callable[[TextTranslator, nodes.Node], None]
def depart_admonition(self, node): def depart_admonition(self, node):
# type: (nodes.NodeVisitor, nodes.Node) -> None # type: (nodes.NodeVisitor, nodes.Node) -> None
self.end_state(first=admonitionlabels[name] + ': ') self.end_state(first=admonitionlabels[name] + ': ')