mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '2.0' into 6561_glossary_hyperrer_for_alphanumeric_term
This commit is contained in:
1
CHANGES
1
CHANGES
@@ -54,6 +54,7 @@ Bugs fixed
|
|||||||
* #5592: std domain: :rst:dir:`option` directive registers an index entry for
|
* #5592: std domain: :rst:dir:`option` directive registers an index entry for
|
||||||
each comma separated option
|
each comma separated option
|
||||||
* #6549: sphinx-build: Escaped characters in error messages
|
* #6549: sphinx-build: Escaped characters in error messages
|
||||||
|
* #6545: doctest comments not getting trimmed since Sphinx 1.8.0
|
||||||
* #6561: glossary: Wrong hyperlinks are generated for non alphanumeric terms
|
* #6561: glossary: Wrong hyperlinks are generated for non alphanumeric terms
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -47,7 +47,7 @@ extras_require = {
|
|||||||
'html5lib',
|
'html5lib',
|
||||||
'flake8>=3.5.0',
|
'flake8>=3.5.0',
|
||||||
'flake8-import-order',
|
'flake8-import-order',
|
||||||
'mypy>=0.711',
|
'mypy>=0.720',
|
||||||
'docutils-stubs',
|
'docutils-stubs',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ class DocTestBuilder(Builder):
|
|||||||
# for doctest examples but unusable for multi-statement code such
|
# for doctest examples but unusable for multi-statement code such
|
||||||
# as setup code -- to be able to use doctest error reporting with
|
# as setup code -- to be able to use doctest error reporting with
|
||||||
# that code nevertheless, we monkey-patch the "compile" it uses.
|
# that code nevertheless, we monkey-patch the "compile" it uses.
|
||||||
doctest.compile = self.compile # type: ignore
|
doctest.compile = self.compile
|
||||||
|
|
||||||
sys.path[0:0] = self.config.doctest_path
|
sys.path[0:0] = self.config.doctest_path
|
||||||
|
|
||||||
|
|||||||
@@ -399,6 +399,6 @@ def inspect_main(argv: List[str]) -> None:
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import logging # type: ignore
|
import logging # type: ignore
|
||||||
logging.basicConfig() # type: ignore
|
logging.basicConfig()
|
||||||
|
|
||||||
inspect_main(argv=sys.argv[1:])
|
inspect_main(argv=sys.argv[1:])
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ class TodoListProcessor:
|
|||||||
self.process(doctree, docname)
|
self.process(doctree, docname)
|
||||||
|
|
||||||
def process(self, doctree: nodes.document, docname: str) -> None:
|
def process(self, doctree: nodes.document, docname: str) -> None:
|
||||||
todos = sum(self.domain.todos.values(), [])
|
todos = sum(self.domain.todos.values(), []) # type: List[todo_node]
|
||||||
for node in doctree.traverse(todolist):
|
for node in doctree.traverse(todolist):
|
||||||
if not self.config.todo_include_todos:
|
if not self.config.todo_include_todos:
|
||||||
node.parent.remove(node)
|
node.parent.remove(node)
|
||||||
@@ -220,7 +220,7 @@ def process_todo_nodes(app: Sphinx, doctree: nodes.document, fromdocname: str) -
|
|||||||
warnings.warn('process_todo_nodes() is deprecated.', RemovedInSphinx40Warning)
|
warnings.warn('process_todo_nodes() is deprecated.', RemovedInSphinx40Warning)
|
||||||
|
|
||||||
domain = cast(TodoDomain, app.env.get_domain('todo'))
|
domain = cast(TodoDomain, app.env.get_domain('todo'))
|
||||||
todos = sum(domain.todos.values(), [])
|
todos = sum(domain.todos.values(), []) # type: List[todo_node]
|
||||||
|
|
||||||
for node in doctree.traverse(todolist):
|
for node in doctree.traverse(todolist):
|
||||||
if node.get('ids'):
|
if node.get('ids'):
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ class VariableCommentPicker(ast.NodeVisitor):
|
|||||||
"""Handles Assign node and pick up a variable comment."""
|
"""Handles Assign node and pick up a variable comment."""
|
||||||
try:
|
try:
|
||||||
targets = get_assign_targets(node)
|
targets = get_assign_targets(node)
|
||||||
varnames = sum([get_lvar_names(t, self=self.get_self()) for t in targets], [])
|
varnames = sum([get_lvar_names(t, self=self.get_self()) for t in targets], []) # type: List[str] # NOQA
|
||||||
current_line = self.get_line(node.lineno)
|
current_line = self.get_line(node.lineno)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return # this assignment is not new definition!
|
return # this assignment is not new definition!
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ class GUILabel(SphinxRole):
|
|||||||
class MenuSelection(GUILabel):
|
class MenuSelection(GUILabel):
|
||||||
def run(self):
|
def run(self):
|
||||||
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||||
self.text = self.text.replace('-->', '\N{TRIANGULAR BULLET}') # type: ignore
|
self.text = self.text.replace('-->', '\N{TRIANGULAR BULLET}')
|
||||||
return super().run()
|
return super().run()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -120,8 +120,8 @@ class SphinxTestApp(application.Sphinx):
|
|||||||
warningiserror = False
|
warningiserror = False
|
||||||
|
|
||||||
self._saved_path = sys.path[:]
|
self._saved_path = sys.path[:]
|
||||||
self._saved_directives = directives._directives.copy() # type: ignore
|
self._saved_directives = directives._directives.copy()
|
||||||
self._saved_roles = roles._roles.copy() # type: ignore
|
self._saved_roles = roles._roles.copy()
|
||||||
|
|
||||||
self._saved_nodeclasses = {v for v in dir(nodes.GenericNodeVisitor)
|
self._saved_nodeclasses = {v for v in dir(nodes.GenericNodeVisitor)
|
||||||
if v.startswith('visit_')}
|
if v.startswith('visit_')}
|
||||||
@@ -140,8 +140,8 @@ class SphinxTestApp(application.Sphinx):
|
|||||||
locale.translators.clear()
|
locale.translators.clear()
|
||||||
sys.path[:] = self._saved_path
|
sys.path[:] = self._saved_path
|
||||||
sys.modules.pop('autodoc_fodder', None)
|
sys.modules.pop('autodoc_fodder', None)
|
||||||
directives._directives = self._saved_directives # type: ignore
|
directives._directives = self._saved_directives
|
||||||
roles._roles = self._saved_roles # type: ignore
|
roles._roles = self._saved_roles
|
||||||
for method in dir(nodes.GenericNodeVisitor):
|
for method in dir(nodes.GenericNodeVisitor):
|
||||||
if method.startswith('visit_') and \
|
if method.startswith('visit_') and \
|
||||||
method not in self._saved_nodeclasses:
|
method not in self._saved_nodeclasses:
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from typing import NamedTuple
|
from typing import NamedTuple, Union
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from pygments.lexers import PythonConsoleLexer, guess_lexer
|
from pygments.lexers import PythonConsoleLexer, guess_lexer
|
||||||
@@ -110,8 +110,16 @@ class TrimDoctestFlagsTransform(SphinxTransform):
|
|||||||
if not self.config.trim_doctest_flags:
|
if not self.config.trim_doctest_flags:
|
||||||
return
|
return
|
||||||
|
|
||||||
for node in self.document.traverse(nodes.literal_block):
|
for lbnode in self.document.traverse(nodes.literal_block): # type: nodes.literal_block
|
||||||
if self.is_pyconsole(node):
|
if self.is_pyconsole(lbnode):
|
||||||
|
self.strip_doctest_flags(lbnode)
|
||||||
|
|
||||||
|
for dbnode in self.document.traverse(nodes.doctest_block): # type: nodes.doctest_block
|
||||||
|
self.strip_doctest_flags(dbnode)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def strip_doctest_flags(node):
|
||||||
|
# type: (Union[nodes.literal_block, nodes.doctest_block]) -> None
|
||||||
source = node.rawsource
|
source = node.rawsource
|
||||||
source = doctest.blankline_re.sub('', source)
|
source = doctest.blankline_re.sub('', source)
|
||||||
source = doctest.doctestopt_re.sub('', source)
|
source = doctest.doctestopt_re.sub('', source)
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ def save_traceback(app: "Sphinx") -> str:
|
|||||||
platform.python_version(),
|
platform.python_version(),
|
||||||
platform.python_implementation(),
|
platform.python_implementation(),
|
||||||
docutils.__version__, docutils.__version_details__,
|
docutils.__version__, docutils.__version_details__,
|
||||||
jinja2.__version__, # type: ignore
|
jinja2.__version__,
|
||||||
last_msgs)).encode())
|
last_msgs)).encode())
|
||||||
if app is not None:
|
if app is not None:
|
||||||
for ext in app.extensions.values():
|
for ext in app.extensions.values():
|
||||||
|
|||||||
@@ -53,13 +53,13 @@ additional_nodes = set() # type: Set[Type[nodes.Element]]
|
|||||||
def docutils_namespace() -> Generator[None, None, None]:
|
def docutils_namespace() -> Generator[None, None, None]:
|
||||||
"""Create namespace for reST parsers."""
|
"""Create namespace for reST parsers."""
|
||||||
try:
|
try:
|
||||||
_directives = copy(directives._directives) # type: ignore
|
_directives = copy(directives._directives)
|
||||||
_roles = copy(roles._roles) # type: ignore
|
_roles = copy(roles._roles)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
directives._directives = _directives # type: ignore
|
directives._directives = _directives
|
||||||
roles._roles = _roles # type: ignore
|
roles._roles = _roles
|
||||||
|
|
||||||
for node in list(additional_nodes):
|
for node in list(additional_nodes):
|
||||||
unregister_node(node)
|
unregister_node(node)
|
||||||
@@ -68,7 +68,7 @@ def docutils_namespace() -> Generator[None, None, None]:
|
|||||||
|
|
||||||
def is_directive_registered(name: str) -> bool:
|
def is_directive_registered(name: str) -> bool:
|
||||||
"""Check the *name* directive is already registered."""
|
"""Check the *name* directive is already registered."""
|
||||||
return name in directives._directives # type: ignore
|
return name in directives._directives
|
||||||
|
|
||||||
|
|
||||||
def register_directive(name: str, directive: Type[Directive]) -> None:
|
def register_directive(name: str, directive: Type[Directive]) -> None:
|
||||||
@@ -82,7 +82,7 @@ def register_directive(name: str, directive: Type[Directive]) -> None:
|
|||||||
|
|
||||||
def is_role_registered(name: str) -> bool:
|
def is_role_registered(name: str) -> bool:
|
||||||
"""Check the *name* role is already registered."""
|
"""Check the *name* role is already registered."""
|
||||||
return name in roles._roles # type: ignore
|
return name in roles._roles
|
||||||
|
|
||||||
|
|
||||||
def register_role(name: str, role: RoleFunction) -> None:
|
def register_role(name: str, role: RoleFunction) -> None:
|
||||||
@@ -96,7 +96,7 @@ def register_role(name: str, role: RoleFunction) -> None:
|
|||||||
|
|
||||||
def unregister_role(name: str) -> None:
|
def unregister_role(name: str) -> None:
|
||||||
"""Unregister a role from docutils."""
|
"""Unregister a role from docutils."""
|
||||||
roles._roles.pop(name, None) # type: ignore
|
roles._roles.pop(name, None)
|
||||||
|
|
||||||
|
|
||||||
def is_node_registered(node: Type[Element]) -> bool:
|
def is_node_registered(node: Type[Element]) -> bool:
|
||||||
@@ -111,7 +111,7 @@ def register_node(node: Type[Element]) -> None:
|
|||||||
inside ``docutils_namespace()`` to prevent side-effects.
|
inside ``docutils_namespace()`` to prevent side-effects.
|
||||||
"""
|
"""
|
||||||
if not hasattr(nodes.GenericNodeVisitor, 'visit_' + node.__name__):
|
if not hasattr(nodes.GenericNodeVisitor, 'visit_' + node.__name__):
|
||||||
nodes._add_node_class_names([node.__name__]) # type: ignore
|
nodes._add_node_class_names([node.__name__])
|
||||||
additional_nodes.add(node)
|
additional_nodes.add(node)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -536,7 +536,7 @@ class Signature:
|
|||||||
qualname = repr(annotation)
|
qualname = repr(annotation)
|
||||||
|
|
||||||
if (hasattr(typing, 'TupleMeta') and
|
if (hasattr(typing, 'TupleMeta') and
|
||||||
isinstance(annotation, typing.TupleMeta) and # type: ignore
|
isinstance(annotation, typing.TupleMeta) and
|
||||||
not hasattr(annotation, '__tuple_params__')):
|
not hasattr(annotation, '__tuple_params__')):
|
||||||
# This is for Python 3.6+, 3.5 case is handled below
|
# This is for Python 3.6+, 3.5 case is handled below
|
||||||
params = annotation.__args__
|
params = annotation.__args__
|
||||||
@@ -567,7 +567,7 @@ class Signature:
|
|||||||
param_str = ', '.join(self.format_annotation(p) for p in params)
|
param_str = ', '.join(self.format_annotation(p) for p in params)
|
||||||
return '%s[%s]' % (qualname, param_str)
|
return '%s[%s]' % (qualname, param_str)
|
||||||
elif (hasattr(typing, 'UnionMeta') and # for py35 or below
|
elif (hasattr(typing, 'UnionMeta') and # for py35 or below
|
||||||
isinstance(annotation, typing.UnionMeta) and # type: ignore
|
isinstance(annotation, typing.UnionMeta) and
|
||||||
hasattr(annotation, '__union_params__')):
|
hasattr(annotation, '__union_params__')):
|
||||||
params = annotation.__union_params__
|
params = annotation.__union_params__
|
||||||
if params is not None:
|
if params is not None:
|
||||||
@@ -587,7 +587,7 @@ class Signature:
|
|||||||
param_str = ', '.join(self.format_annotation(p) for p in params)
|
param_str = ', '.join(self.format_annotation(p) for p in params)
|
||||||
return 'Union[%s]' % param_str
|
return 'Union[%s]' % param_str
|
||||||
elif (hasattr(typing, 'CallableMeta') and # for py36 or below
|
elif (hasattr(typing, 'CallableMeta') and # for py36 or below
|
||||||
isinstance(annotation, typing.CallableMeta) and # type: ignore
|
isinstance(annotation, typing.CallableMeta) and
|
||||||
getattr(annotation, '__args__', None) is not None and
|
getattr(annotation, '__args__', None) is not None and
|
||||||
hasattr(annotation, '__result__')):
|
hasattr(annotation, '__result__')):
|
||||||
# Skipped in the case of plain typing.Callable
|
# Skipped in the case of plain typing.Callable
|
||||||
@@ -603,7 +603,7 @@ class Signature:
|
|||||||
args_str,
|
args_str,
|
||||||
self.format_annotation(annotation.__result__))
|
self.format_annotation(annotation.__result__))
|
||||||
elif (hasattr(typing, 'TupleMeta') and # for py36 or below
|
elif (hasattr(typing, 'TupleMeta') and # for py36 or below
|
||||||
isinstance(annotation, typing.TupleMeta) and # type: ignore
|
isinstance(annotation, typing.TupleMeta) and
|
||||||
hasattr(annotation, '__tuple_params__') and
|
hasattr(annotation, '__tuple_params__') and
|
||||||
hasattr(annotation, '__tuple_use_ellipsis__')):
|
hasattr(annotation, '__tuple_use_ellipsis__')):
|
||||||
params = annotation.__tuple_params__
|
params = annotation.__tuple_params__
|
||||||
|
|||||||
@@ -377,7 +377,7 @@ class TextWriter(writers.Writer):
|
|||||||
settings_spec = ('No options here.', '', ())
|
settings_spec = ('No options here.', '', ())
|
||||||
settings_defaults = {} # type: Dict
|
settings_defaults = {} # type: Dict
|
||||||
|
|
||||||
output = None
|
output = None # type: str
|
||||||
|
|
||||||
def __init__(self, builder):
|
def __init__(self, builder):
|
||||||
# type: (TextBuilder) -> None
|
# type: (TextBuilder) -> None
|
||||||
|
|||||||
@@ -21,3 +21,8 @@ test-trim_doctest_flags
|
|||||||
|
|
||||||
>>> datetime.date.now() # doctest: +QUX
|
>>> datetime.date.now() # doctest: +QUX
|
||||||
datetime.date(2008, 1, 1)
|
datetime.date(2008, 1, 1)
|
||||||
|
|
||||||
|
.. doctest_block::
|
||||||
|
|
||||||
|
>>> datetime.date.now() # doctest: +QUUX
|
||||||
|
datetime.date(2008, 1, 1)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ def test_trim_doctest_flags_html(app, status, warning):
|
|||||||
assert 'BAR' in result
|
assert 'BAR' in result
|
||||||
assert 'BAZ' not in result
|
assert 'BAZ' not in result
|
||||||
assert 'QUX' not in result
|
assert 'QUX' not in result
|
||||||
|
assert 'QUUX' not in result
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('latex', testroot='trim_doctest_flags')
|
@pytest.mark.sphinx('latex', testroot='trim_doctest_flags')
|
||||||
@@ -29,3 +30,4 @@ def test_trim_doctest_flags_latex(app, status, warning):
|
|||||||
assert 'BAR' in result
|
assert 'BAR' in result
|
||||||
assert 'BAZ' not in result
|
assert 'BAZ' not in result
|
||||||
assert 'QUX' not in result
|
assert 'QUX' not in result
|
||||||
|
assert 'QUUX' not in result
|
||||||
|
|||||||
Reference in New Issue
Block a user