mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #6956 from tk0miya/refactor_type_annotation3
Migrate to py3 style type annotation: highlighting, jinja2glue, roles and theming
This commit is contained in:
@@ -12,14 +12,17 @@ import html
|
||||
import warnings
|
||||
from functools import partial
|
||||
from importlib import import_module
|
||||
from typing import Any, Dict
|
||||
|
||||
from pygments import highlight
|
||||
from pygments.filters import ErrorToken
|
||||
from pygments.formatter import Formatter
|
||||
from pygments.formatters import HtmlFormatter, LatexFormatter
|
||||
from pygments.lexer import Lexer
|
||||
from pygments.lexers import get_lexer_by_name, guess_lexer
|
||||
from pygments.lexers import PythonLexer, Python3Lexer, PythonConsoleLexer, \
|
||||
CLexer, TextLexer, RstLexer
|
||||
from pygments.style import Style
|
||||
from pygments.styles import get_style_by_name
|
||||
from pygments.util import ClassNotFound
|
||||
|
||||
@@ -29,12 +32,6 @@ from sphinx.locale import __
|
||||
from sphinx.pygments_styles import SphinxStyle, NoneStyle
|
||||
from sphinx.util import logging, texescape
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict # NOQA
|
||||
from pygments.formatter import Formatter # NOQA
|
||||
from pygments.style import Style # NOQA
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -67,9 +64,8 @@ class PygmentsBridge:
|
||||
html_formatter = HtmlFormatter
|
||||
latex_formatter = LatexFormatter
|
||||
|
||||
def __init__(self, dest='html', stylename='sphinx', trim_doctest_flags=None,
|
||||
latex_engine=None):
|
||||
# type: (str, str, bool, str) -> None
|
||||
def __init__(self, dest: str = 'html', stylename: str = 'sphinx',
|
||||
trim_doctest_flags: bool = None, latex_engine: str = None) -> None:
|
||||
self.dest = dest
|
||||
self.latex_engine = latex_engine
|
||||
|
||||
@@ -86,8 +82,7 @@ class PygmentsBridge:
|
||||
warnings.warn('trim_doctest_flags option for PygmentsBridge is now deprecated.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
|
||||
def get_style(self, stylename):
|
||||
# type: (str) -> Style
|
||||
def get_style(self, stylename: str) -> Style:
|
||||
if stylename is None or stylename == 'sphinx':
|
||||
return SphinxStyle
|
||||
elif stylename == 'none':
|
||||
@@ -98,13 +93,11 @@ class PygmentsBridge:
|
||||
else:
|
||||
return get_style_by_name(stylename)
|
||||
|
||||
def get_formatter(self, **kwargs):
|
||||
# type: (Any) -> Formatter
|
||||
def get_formatter(self, **kwargs) -> Formatter:
|
||||
kwargs.update(self.formatter_args)
|
||||
return self.formatter(**kwargs)
|
||||
|
||||
def unhighlighted(self, source):
|
||||
# type: (str) -> str
|
||||
def unhighlighted(self, source: str) -> str:
|
||||
warnings.warn('PygmentsBridge.unhighlighted() is now deprecated.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
if self.dest == 'html':
|
||||
@@ -117,8 +110,8 @@ class PygmentsBridge:
|
||||
return '\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n' + \
|
||||
source + '\\end{Verbatim}\n'
|
||||
|
||||
def get_lexer(self, source, lang, opts=None, force=False, location=None):
|
||||
# type: (str, str, Dict, bool, Any) -> Lexer
|
||||
def get_lexer(self, source: str, lang: str, opts: Dict = None,
|
||||
force: bool = False, location: Any = None) -> Lexer:
|
||||
if not opts:
|
||||
opts = {}
|
||||
|
||||
@@ -161,8 +154,8 @@ class PygmentsBridge:
|
||||
|
||||
return lexer
|
||||
|
||||
def highlight_block(self, source, lang, opts=None, force=False, location=None, **kwargs):
|
||||
# type: (str, str, Dict, bool, Any, Any) -> str
|
||||
def highlight_block(self, source: str, lang: str, opts: Dict = None,
|
||||
force: bool = False, location: Any = None, **kwargs) -> str:
|
||||
if not isinstance(source, str):
|
||||
source = source.decode()
|
||||
|
||||
@@ -196,8 +189,7 @@ class PygmentsBridge:
|
||||
# MEMO: this is done to escape Unicode chars with non-Unicode engines
|
||||
return texescape.hlescape(hlsource, self.latex_engine)
|
||||
|
||||
def get_stylesheet(self):
|
||||
# type: () -> str
|
||||
def get_stylesheet(self) -> str:
|
||||
formatter = self.get_formatter()
|
||||
if self.dest == 'html':
|
||||
return formatter.get_style_defs('.highlight')
|
||||
|
||||
@@ -10,42 +10,37 @@
|
||||
|
||||
from os import path
|
||||
from pprint import pformat
|
||||
from typing import Any, Callable, Iterator, Tuple # NOQA
|
||||
from typing import Any, Callable, Dict, Iterator, List, Tuple, Union
|
||||
|
||||
from jinja2 import FileSystemLoader, BaseLoader, TemplateNotFound, \
|
||||
contextfunction
|
||||
from jinja2 import FileSystemLoader, BaseLoader, TemplateNotFound, contextfunction
|
||||
from jinja2.environment import Environment
|
||||
from jinja2.sandbox import SandboxedEnvironment
|
||||
from jinja2.utils import open_if_exists
|
||||
|
||||
from sphinx.application import TemplateBridge
|
||||
from sphinx.theming import Theme
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.osutil import mtimes_of_files
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Dict, List, Union # NOQA
|
||||
from jinja2.environment import Environment # NOQA
|
||||
from sphinx.builders import Builder # NOQA
|
||||
from sphinx.theming import Theme # NOQA
|
||||
from sphinx.builders import Builder
|
||||
|
||||
|
||||
def _tobool(val):
|
||||
# type: (str) -> bool
|
||||
def _tobool(val: str) -> bool:
|
||||
if isinstance(val, str):
|
||||
return val.lower() in ('true', '1', 'yes', 'on')
|
||||
return bool(val)
|
||||
|
||||
|
||||
def _toint(val):
|
||||
# type: (str) -> int
|
||||
def _toint(val: str) -> int:
|
||||
try:
|
||||
return int(val)
|
||||
except ValueError:
|
||||
return 0
|
||||
|
||||
|
||||
def _todim(val):
|
||||
# type: (Union[int, str]) -> str
|
||||
def _todim(val: Union[int, str]) -> str:
|
||||
"""
|
||||
Make val a css dimension. In particular the following transformations
|
||||
are performed:
|
||||
@@ -63,8 +58,7 @@ def _todim(val):
|
||||
return val # type: ignore
|
||||
|
||||
|
||||
def _slice_index(values, slices):
|
||||
# type: (List, int) -> Iterator[List]
|
||||
def _slice_index(values: List, slices: int) -> Iterator[List]:
|
||||
seq = list(values)
|
||||
length = 0
|
||||
for value in values:
|
||||
@@ -85,8 +79,7 @@ def _slice_index(values, slices):
|
||||
yield seq[start:offset]
|
||||
|
||||
|
||||
def accesskey(context, key):
|
||||
# type: (Any, str) -> str
|
||||
def accesskey(context: Any, key: str) -> str:
|
||||
"""Helper to output each access key only once."""
|
||||
if '_accesskeys' not in context:
|
||||
context.vars['_accesskeys'] = {}
|
||||
@@ -97,24 +90,20 @@ def accesskey(context, key):
|
||||
|
||||
|
||||
class idgen:
|
||||
def __init__(self):
|
||||
# type: () -> None
|
||||
def __init__(self) -> None:
|
||||
self.id = 0
|
||||
|
||||
def current(self):
|
||||
# type: () -> int
|
||||
def current(self) -> int:
|
||||
return self.id
|
||||
|
||||
def __next__(self):
|
||||
# type: () -> int
|
||||
def __next__(self) -> int:
|
||||
self.id += 1
|
||||
return self.id
|
||||
next = __next__ # Python 2/Jinja compatibility
|
||||
|
||||
|
||||
@contextfunction
|
||||
def warning(context, message, *args, **kwargs):
|
||||
# type: (Dict, str, Any, Any) -> str
|
||||
def warning(context: Dict, message: str, *args, **kwargs) -> str:
|
||||
if 'pagename' in context:
|
||||
filename = context.get('pagename') + context.get('file_suffix', '')
|
||||
message = 'in rendering %s: %s' % (filename, message)
|
||||
@@ -129,8 +118,7 @@ class SphinxFileSystemLoader(FileSystemLoader):
|
||||
template names.
|
||||
"""
|
||||
|
||||
def get_source(self, environment, template):
|
||||
# type: (Environment, str) -> Tuple[str, str, Callable]
|
||||
def get_source(self, environment: Environment, template: str) -> Tuple[str, str, Callable]:
|
||||
for searchpath in self.searchpath:
|
||||
filename = path.join(searchpath, template)
|
||||
f = open_if_exists(filename)
|
||||
@@ -141,8 +129,7 @@ class SphinxFileSystemLoader(FileSystemLoader):
|
||||
|
||||
mtime = path.getmtime(filename)
|
||||
|
||||
def uptodate():
|
||||
# type: () -> bool
|
||||
def uptodate() -> bool:
|
||||
try:
|
||||
return path.getmtime(filename) == mtime
|
||||
except OSError:
|
||||
@@ -158,8 +145,7 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
|
||||
|
||||
# TemplateBridge interface
|
||||
|
||||
def init(self, builder, theme=None, dirs=None):
|
||||
# type: (Builder, Theme, List[str]) -> None
|
||||
def init(self, builder: "Builder", theme: Theme = None, dirs: List[str] = None) -> None:
|
||||
# create a chain of paths to search
|
||||
if theme:
|
||||
# the theme's own dir and its bases' dirs
|
||||
@@ -202,22 +188,18 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
|
||||
if use_i18n:
|
||||
self.environment.install_gettext_translations(builder.app.translator) # type: ignore # NOQA
|
||||
|
||||
def render(self, template, context): # type: ignore
|
||||
# type: (str, Dict) -> str
|
||||
def render(self, template: str, context: Dict) -> str: # type: ignore
|
||||
return self.environment.get_template(template).render(context)
|
||||
|
||||
def render_string(self, source, context):
|
||||
# type: (str, Dict) -> str
|
||||
def render_string(self, source: str, context: Dict) -> str:
|
||||
return self.environment.from_string(source).render(context)
|
||||
|
||||
def newest_template_mtime(self):
|
||||
# type: () -> float
|
||||
def newest_template_mtime(self) -> float:
|
||||
return max(mtimes_of_files(self.pathchain, '.html'))
|
||||
|
||||
# Loader interface
|
||||
|
||||
def get_source(self, environment, template):
|
||||
# type: (Environment, str) -> Tuple[str, str, Callable]
|
||||
def get_source(self, environment: Environment, template: str) -> Tuple[str, str, Callable]:
|
||||
loaders = self.loaders
|
||||
# exclamation mark starts search from theme
|
||||
if template.startswith('!'):
|
||||
|
||||
117
sphinx/roles.py
117
sphinx/roles.py
@@ -10,25 +10,27 @@
|
||||
|
||||
import re
|
||||
import warnings
|
||||
from typing import Any, Dict, List, Tuple
|
||||
from typing import Type # for python3.5.1
|
||||
|
||||
from docutils import nodes, utils
|
||||
from docutils.nodes import Element, Node, TextElement, system_message
|
||||
from docutils.parsers.rst.states import Inliner
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||
from sphinx.locale import _
|
||||
from sphinx.util import ws_re
|
||||
from sphinx.util.docutils import ReferenceRole, SphinxRole
|
||||
from sphinx.util.nodes import split_explicit_title, process_index_entry, \
|
||||
set_role_source_info
|
||||
from sphinx.util.nodes import (
|
||||
split_explicit_title, process_index_entry, set_role_source_info
|
||||
)
|
||||
from sphinx.util.typing import RoleFunction
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, List, Tuple # NOQA
|
||||
from typing import Type # for python3.5.1
|
||||
from docutils.parsers.rst.states import Inliner # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
from sphinx.util.typing import RoleFunction # NOQA
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.environment import BuildEnvironment
|
||||
|
||||
|
||||
generic_docroles = {
|
||||
@@ -71,12 +73,12 @@ class XRefRole(ReferenceRole):
|
||||
* Subclassing and overwriting `process_link()` and/or `result_nodes()`.
|
||||
"""
|
||||
|
||||
nodeclass = addnodes.pending_xref # type: Type[nodes.Element]
|
||||
innernodeclass = nodes.literal # type: Type[nodes.TextElement]
|
||||
nodeclass = addnodes.pending_xref # type: Type[Element]
|
||||
innernodeclass = nodes.literal # type: Type[TextElement]
|
||||
|
||||
def __init__(self, fix_parens=False, lowercase=False,
|
||||
nodeclass=None, innernodeclass=None, warn_dangling=False):
|
||||
# type: (bool, bool, Type[nodes.Element], Type[nodes.TextElement], bool) -> None
|
||||
def __init__(self, fix_parens: bool = False, lowercase: bool = False,
|
||||
nodeclass: Type[Element] = None, innernodeclass: Type[TextElement] = None,
|
||||
warn_dangling: bool = False) -> None:
|
||||
self.fix_parens = fix_parens
|
||||
self.lowercase = lowercase
|
||||
self.warn_dangling = warn_dangling
|
||||
@@ -87,8 +89,8 @@ class XRefRole(ReferenceRole):
|
||||
|
||||
super().__init__()
|
||||
|
||||
def _fix_parens(self, env, has_explicit_title, title, target):
|
||||
# type: (BuildEnvironment, bool, str, str) -> Tuple[str, str]
|
||||
def _fix_parens(self, env: "BuildEnvironment", has_explicit_title: bool, title: str,
|
||||
target: str) -> Tuple[str, str]:
|
||||
warnings.warn('XRefRole._fix_parens() is deprecated.',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
if not has_explicit_title:
|
||||
@@ -103,8 +105,7 @@ class XRefRole(ReferenceRole):
|
||||
target = target[:-2]
|
||||
return title, target
|
||||
|
||||
def update_title_and_target(self, title, target):
|
||||
# type: (str, str) -> Tuple[str, str]
|
||||
def update_title_and_target(self, title: str, target: str) -> Tuple[str, str]:
|
||||
if not self.has_explicit_title:
|
||||
if title.endswith('()'):
|
||||
# remove parentheses
|
||||
@@ -117,8 +118,7 @@ class XRefRole(ReferenceRole):
|
||||
target = target[:-2]
|
||||
return title, target
|
||||
|
||||
def run(self):
|
||||
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||
def run(self) -> Tuple[List[Node], List[system_message]]:
|
||||
if ':' not in self.name:
|
||||
self.refdomain, self.reftype = '', self.name
|
||||
self.classes = ['xref', self.reftype]
|
||||
@@ -132,8 +132,7 @@ class XRefRole(ReferenceRole):
|
||||
else:
|
||||
return self.create_xref_node()
|
||||
|
||||
def create_non_xref_node(self):
|
||||
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||
def create_non_xref_node(self) -> Tuple[List[Node], List[system_message]]:
|
||||
text = utils.unescape(self.text[1:])
|
||||
if self.fix_parens:
|
||||
self.has_explicit_title = False # treat as implicit
|
||||
@@ -142,8 +141,7 @@ class XRefRole(ReferenceRole):
|
||||
node = self.innernodeclass(self.rawtext, text, classes=self.classes)
|
||||
return self.result_nodes(self.inliner.document, self.env, node, is_ref=False)
|
||||
|
||||
def create_xref_node(self):
|
||||
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||
def create_xref_node(self) -> Tuple[List[Node], List[system_message]]:
|
||||
target = self.target
|
||||
title = self.title
|
||||
if self.lowercase:
|
||||
@@ -170,8 +168,8 @@ class XRefRole(ReferenceRole):
|
||||
|
||||
# methods that can be overwritten
|
||||
|
||||
def process_link(self, env, refnode, has_explicit_title, title, target):
|
||||
# type: (BuildEnvironment, nodes.Element, bool, str, str) -> Tuple[str, str]
|
||||
def process_link(self, env: "BuildEnvironment", refnode: Element, has_explicit_title: bool,
|
||||
title: str, target: str) -> Tuple[str, str]:
|
||||
"""Called after parsing title and target text, and creating the
|
||||
reference node (given in *refnode*). This method can alter the
|
||||
reference node and must return a new (or the same) ``(title, target)``
|
||||
@@ -179,8 +177,8 @@ class XRefRole(ReferenceRole):
|
||||
"""
|
||||
return title, ws_re.sub(' ', target)
|
||||
|
||||
def result_nodes(self, document, env, node, is_ref):
|
||||
# type: (nodes.document, BuildEnvironment, nodes.Element, bool) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
||||
def result_nodes(self, document: nodes.document, env: "BuildEnvironment", node: Element,
|
||||
is_ref: bool) -> Tuple[List[Node], List[system_message]]:
|
||||
"""Called before returning the finished nodes. *node* is the reference
|
||||
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)``
|
||||
@@ -190,16 +188,17 @@ class XRefRole(ReferenceRole):
|
||||
|
||||
|
||||
class AnyXRefRole(XRefRole):
|
||||
def process_link(self, env, refnode, has_explicit_title, title, target):
|
||||
# type: (BuildEnvironment, nodes.Element, bool, str, str) -> Tuple[str, str]
|
||||
def process_link(self, env: "BuildEnvironment", refnode: Element, has_explicit_title: bool,
|
||||
title: str, target: str) -> Tuple[str, str]:
|
||||
result = super().process_link(env, refnode, has_explicit_title, title, target)
|
||||
# add all possible context info (i.e. std:program, py:module etc.)
|
||||
refnode.attributes.update(env.ref_context)
|
||||
return result
|
||||
|
||||
|
||||
def indexmarkup_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 indexmarkup_role(typ: str, rawtext: str, text: str, lineno: int, inliner: Inliner,
|
||||
options: Dict = {}, content: List[str] = []
|
||||
) -> Tuple[List[Node], List[system_message]]:
|
||||
"""Role for PEP/RFC references that generate an index entry."""
|
||||
warnings.warn('indexmarkup_role() is deprecated. Please use PEP or RFC class instead.',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
@@ -267,8 +266,7 @@ def indexmarkup_role(typ, rawtext, text, lineno, inliner, options={}, content=[]
|
||||
|
||||
|
||||
class PEP(ReferenceRole):
|
||||
def run(self):
|
||||
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||
def run(self) -> Tuple[List[Node], List[system_message]]:
|
||||
target_id = 'index-%s' % self.env.new_serialno('index')
|
||||
entries = [('single', _('Python Enhancement Proposals; PEP %s') % self.target,
|
||||
target_id, '', None)]
|
||||
@@ -293,8 +291,7 @@ class PEP(ReferenceRole):
|
||||
|
||||
return [index, target, reference], []
|
||||
|
||||
def build_uri(self):
|
||||
# type: () -> str
|
||||
def build_uri(self) -> str:
|
||||
base_url = self.inliner.document.settings.pep_base_url
|
||||
ret = self.target.split('#', 1)
|
||||
if len(ret) == 2:
|
||||
@@ -304,8 +301,7 @@ class PEP(ReferenceRole):
|
||||
|
||||
|
||||
class RFC(ReferenceRole):
|
||||
def run(self):
|
||||
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
||||
def run(self) -> Tuple[List[Node], List[system_message]]:
|
||||
target_id = 'index-%s' % self.env.new_serialno('index')
|
||||
entries = [('single', 'RFC; RFC %s' % self.target, target_id, '', None)]
|
||||
|
||||
@@ -329,8 +325,7 @@ class RFC(ReferenceRole):
|
||||
|
||||
return [index, target, reference], []
|
||||
|
||||
def build_uri(self):
|
||||
# type: () -> str
|
||||
def build_uri(self) -> str:
|
||||
base_url = self.inliner.document.settings.rfc_base_url
|
||||
ret = self.target.split('#', 1)
|
||||
if len(ret) == 2:
|
||||
@@ -342,8 +337,9 @@ class RFC(ReferenceRole):
|
||||
_amp_re = re.compile(r'(?<!&)&(?![&\s])')
|
||||
|
||||
|
||||
def menusel_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 menusel_role(typ: str, rawtext: str, text: str, lineno: int, inliner: Inliner,
|
||||
options: Dict = {}, content: List[str] = []
|
||||
) -> Tuple[List[Node], List[system_message]]:
|
||||
warnings.warn('menusel_role() is deprecated. '
|
||||
'Please use MenuSelection or GUILabel class instead.',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
@@ -382,8 +378,7 @@ def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||
class GUILabel(SphinxRole):
|
||||
amp_re = re.compile(r'(?<!&)&(?![&\s])')
|
||||
|
||||
def run(self):
|
||||
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||
def run(self) -> Tuple[List[Node], List[system_message]]:
|
||||
node = nodes.inline(rawtext=self.rawtext, classes=[self.name])
|
||||
spans = self.amp_re.split(self.text)
|
||||
node += nodes.Text(spans.pop(0))
|
||||
@@ -399,8 +394,7 @@ class GUILabel(SphinxRole):
|
||||
|
||||
|
||||
class MenuSelection(GUILabel):
|
||||
def run(self):
|
||||
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||
def run(self) -> Tuple[List[Node], List[system_message]]:
|
||||
self.text = self.text.replace('-->', '\N{TRIANGULAR BULLET}')
|
||||
return super().run()
|
||||
|
||||
@@ -409,9 +403,9 @@ _litvar_re = re.compile('{([^}]+)}')
|
||||
parens_re = re.compile(r'(\\*{|\\*})')
|
||||
|
||||
|
||||
def emph_literal_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 emph_literal_role(typ: str, rawtext: str, text: str, lineno: int, inliner: Inliner,
|
||||
options: Dict = {}, content: List[str] = []
|
||||
) -> Tuple[List[Node], List[system_message]]:
|
||||
warnings.warn('emph_literal_role() is deprecated. '
|
||||
'Please use EmphasizedLiteral class instead.',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
@@ -465,17 +459,15 @@ def emph_literal_role(typ, rawtext, text, lineno, inliner,
|
||||
class EmphasizedLiteral(SphinxRole):
|
||||
parens_re = re.compile(r'(\\\\|\\{|\\}|{|})')
|
||||
|
||||
def run(self):
|
||||
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||
def run(self) -> Tuple[List[Node], List[system_message]]:
|
||||
children = self.parse(self.text)
|
||||
node = nodes.literal(self.rawtext, '', *children,
|
||||
role=self.name.lower(), classes=[self.name])
|
||||
|
||||
return [node], []
|
||||
|
||||
def parse(self, text):
|
||||
# type: (str) -> List[nodes.Node]
|
||||
result = [] # type: List[nodes.Node]
|
||||
def parse(self, text: str) -> List[Node]:
|
||||
result = [] # type: List[Node]
|
||||
|
||||
stack = ['']
|
||||
for part in self.parens_re.split(text):
|
||||
@@ -517,8 +509,9 @@ class EmphasizedLiteral(SphinxRole):
|
||||
_abbr_re = re.compile(r'\((.*)\)$', re.S)
|
||||
|
||||
|
||||
def abbr_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 abbr_role(typ: str, rawtext: str, text: str, lineno: int, inliner: Inliner,
|
||||
options: Dict = {}, content: List[str] = []
|
||||
) -> Tuple[List[Node], List[system_message]]:
|
||||
warnings.warn('abbr_role() is deprecated. Please use Abbrevation class instead.',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
text = utils.unescape(text)
|
||||
@@ -535,8 +528,7 @@ def abbr_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||
class Abbreviation(SphinxRole):
|
||||
abbr_re = re.compile(r'\((.*)\)$', re.S)
|
||||
|
||||
def run(self):
|
||||
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||
def run(self) -> Tuple[List[Node], List[system_message]]:
|
||||
matched = self.abbr_re.search(self.text)
|
||||
if matched:
|
||||
text = self.text[:matched.start()].strip()
|
||||
@@ -547,8 +539,9 @@ class Abbreviation(SphinxRole):
|
||||
return [nodes.abbreviation(self.rawtext, text, **self.options)], []
|
||||
|
||||
|
||||
def index_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 index_role(typ: str, rawtext: str, text: str, lineno: int, inliner: Inliner,
|
||||
options: Dict = {}, content: List[str] = []
|
||||
) -> Tuple[List[Node], List[system_message]]:
|
||||
warnings.warn('index_role() is deprecated. Please use Index class instead.',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
# create new reference target
|
||||
@@ -579,8 +572,7 @@ def index_role(typ, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||
|
||||
|
||||
class Index(ReferenceRole):
|
||||
def run(self):
|
||||
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||
def run(self) -> Tuple[List[Node], List[system_message]]:
|
||||
target_id = 'index-%s' % self.env.new_serialno('index')
|
||||
if self.has_explicit_title:
|
||||
# if an explicit target is given, process it as a full entry
|
||||
@@ -619,8 +611,7 @@ specific_docroles = {
|
||||
} # type: Dict[str, RoleFunction]
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: "Sphinx") -> Dict[str, Any]:
|
||||
from docutils.parsers.rst import roles
|
||||
|
||||
for rolename, nodeclass in generic_docroles.items():
|
||||
|
||||
@@ -13,6 +13,7 @@ import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from os import path
|
||||
from typing import Any, Dict, List
|
||||
from zipfile import ZipFile
|
||||
|
||||
import pkg_resources
|
||||
@@ -23,19 +24,18 @@ from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.osutil import ensuredir
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, List # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.application import Sphinx
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
NODEFAULT = object()
|
||||
THEMECONF = 'theme.conf'
|
||||
|
||||
|
||||
def extract_zip(filename, targetdir):
|
||||
# type: (str, str) -> None
|
||||
def extract_zip(filename: str, targetdir: str) -> None:
|
||||
"""Extract zip file to target directory."""
|
||||
ensuredir(targetdir)
|
||||
|
||||
@@ -54,8 +54,7 @@ class Theme:
|
||||
|
||||
This class supports both theme directory and theme archive (zipped theme)."""
|
||||
|
||||
def __init__(self, name, theme_path, factory):
|
||||
# type: (str, str, HTMLThemeFactory) -> None
|
||||
def __init__(self, name: str, theme_path: str, factory: "HTMLThemeFactory") -> None:
|
||||
self.name = name
|
||||
self.base = None
|
||||
self.rootdir = None
|
||||
@@ -87,8 +86,7 @@ class Theme:
|
||||
raise ThemeError(__('no theme named %r found, inherited by %r') %
|
||||
(inherit, name))
|
||||
|
||||
def get_theme_dirs(self):
|
||||
# type: () -> List[str]
|
||||
def get_theme_dirs(self) -> List[str]:
|
||||
"""Return a list of theme directories, beginning with this theme's,
|
||||
then the base theme's, then that one's base theme's, etc.
|
||||
"""
|
||||
@@ -97,8 +95,7 @@ class Theme:
|
||||
else:
|
||||
return [self.themedir] + self.base.get_theme_dirs()
|
||||
|
||||
def get_config(self, section, name, default=NODEFAULT):
|
||||
# type: (str, str, Any) -> Any
|
||||
def get_config(self, section: str, name: str, default: Any = NODEFAULT) -> Any:
|
||||
"""Return the value for a theme configuration setting, searching the
|
||||
base theme chain.
|
||||
"""
|
||||
@@ -114,8 +111,7 @@ class Theme:
|
||||
else:
|
||||
return default
|
||||
|
||||
def get_options(self, overrides={}):
|
||||
# type: (Dict[str, Any]) -> Dict[str, Any]
|
||||
def get_options(self, overrides: Dict[str, Any] = {}) -> Dict[str, Any]:
|
||||
"""Return a dictionary of theme options and their values."""
|
||||
if self.base:
|
||||
options = self.base.get_options()
|
||||
@@ -135,8 +131,7 @@ class Theme:
|
||||
|
||||
return options
|
||||
|
||||
def cleanup(self):
|
||||
# type: () -> None
|
||||
def cleanup(self) -> None:
|
||||
"""Remove temporary directories."""
|
||||
if self.rootdir:
|
||||
try:
|
||||
@@ -147,8 +142,7 @@ class Theme:
|
||||
self.base.cleanup()
|
||||
|
||||
|
||||
def is_archived_theme(filename):
|
||||
# type: (str) -> bool
|
||||
def is_archived_theme(filename: str) -> bool:
|
||||
"""Check the specified file is an archived theme file or not."""
|
||||
try:
|
||||
with ZipFile(filename) as f:
|
||||
@@ -160,23 +154,20 @@ def is_archived_theme(filename):
|
||||
class HTMLThemeFactory:
|
||||
"""A factory class for HTML Themes."""
|
||||
|
||||
def __init__(self, app):
|
||||
# type: (Sphinx) -> None
|
||||
def __init__(self, app: "Sphinx") -> None:
|
||||
self.app = app
|
||||
self.themes = app.html_themes
|
||||
self.load_builtin_themes()
|
||||
if getattr(app.config, 'html_theme_path', None):
|
||||
self.load_additional_themes(app.config.html_theme_path)
|
||||
|
||||
def load_builtin_themes(self):
|
||||
# type: () -> None
|
||||
def load_builtin_themes(self) -> None:
|
||||
"""Load built-in themes."""
|
||||
themes = self.find_themes(path.join(package_dir, 'themes'))
|
||||
for name, theme in themes.items():
|
||||
self.themes[name] = theme
|
||||
|
||||
def load_additional_themes(self, theme_paths):
|
||||
# type: (str) -> None
|
||||
def load_additional_themes(self, theme_paths: str) -> None:
|
||||
"""Load additional themes placed at specified directories."""
|
||||
for theme_path in theme_paths:
|
||||
abs_theme_path = path.abspath(path.join(self.app.confdir, theme_path))
|
||||
@@ -184,8 +175,7 @@ class HTMLThemeFactory:
|
||||
for name, theme in themes.items():
|
||||
self.themes[name] = theme
|
||||
|
||||
def load_extra_theme(self, name):
|
||||
# type: (str) -> None
|
||||
def load_extra_theme(self, name: str) -> None:
|
||||
"""Try to load a theme having specifed name."""
|
||||
if name == 'alabaster':
|
||||
self.load_alabaster_theme()
|
||||
@@ -194,14 +184,12 @@ class HTMLThemeFactory:
|
||||
else:
|
||||
self.load_external_theme(name)
|
||||
|
||||
def load_alabaster_theme(self):
|
||||
# type: () -> None
|
||||
def load_alabaster_theme(self) -> None:
|
||||
"""Load alabaster theme."""
|
||||
import alabaster
|
||||
self.themes['alabaster'] = path.join(alabaster.get_path(), 'alabaster')
|
||||
|
||||
def load_sphinx_rtd_theme(self):
|
||||
# type: () -> None
|
||||
def load_sphinx_rtd_theme(self) -> None:
|
||||
"""Load sphinx_rtd_theme theme (if exists)."""
|
||||
try:
|
||||
import sphinx_rtd_theme
|
||||
@@ -210,8 +198,7 @@ class HTMLThemeFactory:
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
def load_external_theme(self, name):
|
||||
# type: (str) -> None
|
||||
def load_external_theme(self, name: str) -> None:
|
||||
"""Try to load a theme using entry_points.
|
||||
|
||||
Sphinx refers to ``sphinx_themes`` entry_points.
|
||||
@@ -225,8 +212,7 @@ class HTMLThemeFactory:
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
def find_themes(self, theme_path):
|
||||
# type: (str) -> Dict[str, str]
|
||||
def find_themes(self, theme_path: str) -> Dict[str, str]:
|
||||
"""Search themes from specified directory."""
|
||||
themes = {} # type: Dict[str, str]
|
||||
if not path.isdir(theme_path):
|
||||
@@ -247,8 +233,7 @@ class HTMLThemeFactory:
|
||||
|
||||
return themes
|
||||
|
||||
def create(self, name):
|
||||
# type: (str) -> Theme
|
||||
def create(self, name: str) -> Theme:
|
||||
"""Create an instance of theme."""
|
||||
if name not in self.themes:
|
||||
self.load_extra_theme(name)
|
||||
|
||||
Reference in New Issue
Block a user