Merge branch '2.0'

This commit is contained in:
Takeshi KOMIYA 2019-10-06 18:41:32 +09:00
commit e8925e78ca
18 changed files with 125 additions and 51 deletions

32
CHANGES
View File

@ -42,12 +42,44 @@ Incompatible changes
Deprecated
----------
* ``sphinx.io.SphinxStandaloneReader.app``
* ``sphinx.io.SphinxStandaloneReader.env``
Features added
--------------
Bugs fixed
----------
* #6668: LaTeX: Longtable before header has incorrect distance
(refs: `latex3/latex2e#173`_)
.. _latex3/latex2e#173: https://github.com/latex3/latex2e/issues/173
* #6618: LaTeX: Avoid section names at the end of a page
Testing
--------
Release 2.2.1 (in development)
==============================
Dependencies
------------
Incompatible changes
--------------------
Deprecated
----------
Features added
--------------
Bugs fixed
----------
* #6641: LaTeX: Undefined control sequence ``\sphinxmaketitle``
Testing
--------

View File

@ -26,6 +26,16 @@ The following is a list of deprecated interfaces.
- (will be) Removed
- Alternatives
* - ``sphinx.io.SphinxStandaloneReader.app``
- 2.3
- 4.0
- ``sphinx.io.SphinxStandaloneReader.setup()``
* - ``sphinx.io.SphinxStandaloneReader.env``
- 2.3
- 4.0
- ``sphinx.io.SphinxStandaloneReader.setup()``
* - ``sphinx.domains.math.MathDomain.add_equation()``
- 2.2
- 4.0

View File

@ -47,7 +47,7 @@ extras_require = {
'html5lib',
'flake8>=3.5.0',
'flake8-import-order',
'mypy>=0.720',
'mypy>=0.730',
'docutils-stubs',
],
}

View File

@ -90,7 +90,7 @@ class Stylesheet(str):
attributes = None # type: Dict[str, str]
filename = None # type: str
def __new__(cls, filename: str, *args: str, **attributes: str) -> None:
def __new__(cls, filename: str, *args: str, **attributes: str) -> "Stylesheet":
self = str.__new__(cls, filename) # type: ignore
self.filename = filename
self.attributes = attributes
@ -113,7 +113,7 @@ class JavaScript(str):
attributes = None # type: Dict[str, str]
filename = None # type: str
def __new__(cls, filename: str, **attributes: str) -> None:
def __new__(cls, filename: str, **attributes: str) -> "JavaScript":
self = str.__new__(cls, filename) # type: ignore
self.filename = filename
self.attributes = attributes

View File

@ -88,7 +88,7 @@ class Make:
nocolor()
print(bold("Sphinx v%s" % sphinx.__display_version__))
print("Please use `make %s' where %s is one of" % ((blue('target'),) * 2)) # type: ignore # NOQA
print("Please use `make %s' where %s is one of" % ((blue('target'),) * 2))
for osname, bname, description in BUILDERS:
if not osname or os.name == osname:
print(' %s %s' % (blue(bname.ljust(10)), description))

View File

@ -286,7 +286,7 @@ class DocTestBuilder(Builder):
# for doctest examples but unusable for multi-statement code such
# as setup code -- to be able to use doctest error reporting with
# that code nevertheless, we monkey-patch the "compile" it uses.
doctest.compile = self.compile
doctest.compile = self.compile # type: ignore
sys.path[0:0] = self.config.doctest_path
@ -507,7 +507,7 @@ Doctest summary
if len(code) == 1:
# ordinary doctests (code/output interleaved)
try:
test = parser.get_doctest(code[0].code, {}, group.name, # type: ignore
test = parser.get_doctest(code[0].code, {}, group.name,
code[0].filename, code[0].lineno)
except Exception:
logger.warning(__('ignoring invalid doctest code: %r'), code[0].code,

View File

@ -368,7 +368,7 @@ class InheritanceDiagram(SphinxDirective):
# removed from the doctree after we're done with them.
for name in graph.get_all_class_names():
refnodes, x = class_role( # type: ignore
'class', ':class:`%s`' % name, name, 0, self.state)
'class', ':class:`%s`' % name, name, 0, self.state) # type: ignore
node.extend(refnodes)
# Store the graph object so we can use it to generate the
# dot file later

View File

@ -398,7 +398,7 @@ def inspect_main(argv: List[str]) -> None:
if __name__ == '__main__':
import logging # type: ignore
logging.basicConfig()
import logging as _logging
_logging.basicConfig()
inspect_main(argv=sys.argv[1:])

View File

@ -17,6 +17,7 @@ from docutils.readers import standalone
from docutils.transforms.references import DanglingReferences
from docutils.writers import UnfilteredWriter
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.transforms import (
AutoIndexUpgrader, DoctreeReadEvent, FigureAligner, SphinxTransformer
)
@ -54,12 +55,35 @@ class SphinxBaseReader(standalone.Reader):
transforms = [] # type: List[Type[Transform]]
def __init__(self, app, *args, **kwargs):
# type: (Sphinx, Any, Any) -> None
self.app = app
self.env = app.env
def __init__(self, *args, **kwargs):
# type: (Any, Any) -> None
from sphinx.application import Sphinx
if len(args) > 0 and isinstance(args[0], Sphinx):
self._app = args[0]
self._env = self._app.env
args = args[1:]
super().__init__(*args, **kwargs)
@property
def app(self):
# type: () -> Sphinx
warnings.warn('SphinxBaseReader.app is deprecated.',
RemovedInSphinx40Warning, stacklevel=2)
return self._app
@property
def env(self):
# type: () -> BuildEnvironment
warnings.warn('SphinxBaseReader.env is deprecated.',
RemovedInSphinx40Warning, stacklevel=2)
return self._env
def setup(self, app):
# type: (Sphinx) -> None
self._app = app # hold application object only for compatibility
self._env = app.env
def get_transforms(self):
# type: () -> List[Type[Transform]]
transforms = super().get_transforms() + self.transforms
@ -81,7 +105,7 @@ class SphinxBaseReader(standalone.Reader):
# substitute transformer
document.transformer = SphinxTransformer(document)
document.transformer.set_environment(self.env)
document.transformer.set_environment(self.settings.env)
# substitute reporter
reporter = document.reporter
@ -95,10 +119,10 @@ class SphinxStandaloneReader(SphinxBaseReader):
A basic document reader for Sphinx.
"""
def __init__(self, app, *args, **kwargs):
# type: (Sphinx, Any, Any) -> None
def setup(self, app):
# type: (Sphinx) -> None
self.transforms = self.transforms + app.registry.get_transforms()
super().__init__(app, *args, **kwargs)
super().setup(app)
def read(self, source, parser, settings):
# type: (Input, Parser, Values) -> nodes.document
@ -106,18 +130,18 @@ class SphinxStandaloneReader(SphinxBaseReader):
if not self.parser:
self.parser = parser
self.settings = settings
self.input = self.read_source()
self.input = self.read_source(settings.env)
self.parse()
return self.document
def read_source(self):
# type: () -> str
def read_source(self, env):
# type: (BuildEnvironment) -> str
"""Read content from source and do post-process."""
content = self.source.read()
# emit "source-read" event
arg = [content]
self.app.emit('source-read', self.env.docname, arg)
env.events.emit('source-read', env.docname, arg)
return arg[0]
@ -130,8 +154,10 @@ class SphinxI18nReader(SphinxBaseReader):
Because the translated texts are partial and they don't have correct line numbers.
"""
def __init__(self, app, *args, **kwargs):
# type: (Sphinx, Any, Any) -> None
def setup(self, app):
# type: (Sphinx) -> None
super().setup(app)
self.transforms = self.transforms + app.registry.get_transforms()
unused = [PreserveTranslatableMessages, Locale, RemoveTranslatableInline,
AutoIndexUpgrader, FigureAligner, SphinxDomains, DoctreeReadEvent,
@ -188,7 +214,8 @@ def read_doc(app, env, filename):
error_handler = UnicodeDecodeErrorHandler(env.docname)
codecs.register_error('sphinx', error_handler) # type: ignore
reader = SphinxStandaloneReader(app)
reader = SphinxStandaloneReader()
reader.setup(app)
filetype = get_filetype(app.config.source_suffix, filename)
parser = app.registry.create_source_parser(app, filetype)
if parser.__class__.__name__ == 'CommonMarkParser' and parser.settings_spec == ():
@ -204,10 +231,10 @@ def read_doc(app, env, filename):
# Sphinx-1.8 style
source = input_class(app, env, source=None, source_path=filename, # type: ignore
encoding=env.config.source_encoding)
pub = Publisher(reader=reader, # type: ignore
pub = Publisher(reader=reader,
parser=parser,
writer=SphinxDummyWriter(),
source_class=SphinxDummySourceClass,
source_class=SphinxDummySourceClass, # type: ignore
destination=NullOutput())
pub.process_programmatic_settings(None, env.settings, None)
pub.set_source(source, filename)

View File

@ -32,7 +32,7 @@ class _TranslationProxy(UserString):
"""
__slots__ = ('_func', '_args')
def __new__(cls, func, *args):
def __new__(cls, func, *args): # type: ignore
# type: (Callable, str) -> object
if not args:
# not called with "function" and "arguments", but a plain string

View File

@ -21,11 +21,13 @@ def parse(app: Sphinx, text: str, docname: str = 'index') -> nodes.document:
"""Parse a string as reStructuredText with Sphinx application."""
try:
app.env.temp_data['docname'] = docname
reader = SphinxStandaloneReader()
reader.setup(app)
parser = RSTParser()
parser.set_application(app)
with sphinx_domains(app.env):
return publish_doctree(text, path.join(app.srcdir, docname + '.rst'),
reader=SphinxStandaloneReader(app),
reader=reader,
parser=parser,
settings_overrides={'env': app.env,
'gettext_compact': True})

View File

@ -120,8 +120,8 @@ class SphinxTestApp(application.Sphinx):
warningiserror = False
self._saved_path = sys.path[:]
self._saved_directives = directives._directives.copy()
self._saved_roles = roles._roles.copy()
self._saved_directives = directives._directives.copy() # type: ignore
self._saved_roles = roles._roles.copy() # type: ignore
self._saved_nodeclasses = {v for v in dir(nodes.GenericNodeVisitor)
if v.startswith('visit_')}
@ -140,8 +140,8 @@ class SphinxTestApp(application.Sphinx):
locale.translators.clear()
sys.path[:] = self._saved_path
sys.modules.pop('autodoc_fodder', None)
directives._directives = self._saved_directives
roles._roles = self._saved_roles
directives._directives = self._saved_directives # type: ignore
roles._roles = self._saved_roles # type: ignore
for method in dir(nodes.GenericNodeVisitor):
if method.startswith('visit_') and \
method not in self._saved_nodeclasses:

View File

@ -6,7 +6,7 @@
%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesPackage{sphinx}[2019/06/04 v2.1.1 LaTeX package (Sphinx markup)]
\ProvidesPackage{sphinx}[2019/09/02 v2.3.0 LaTeX package (Sphinx markup)]
% provides \ltx@ifundefined
% (many packages load ltxcmds: graphicx does for pdftex and lualatex but
@ -40,7 +40,7 @@
% for \text macro and \iffirstchoice@ conditional even if amsmath not loaded
\RequirePackage{amstext}
\RequirePackage{textcomp}% "warn" option issued from template
\RequirePackage{titlesec}
\RequirePackage[nobottomtitles*]{titlesec}
\@ifpackagelater{titlesec}{2016/03/15}%
{\@ifpackagelater{titlesec}{2016/03/21}%
{}%
@ -119,7 +119,8 @@
{\dimexpr-\dp\strutbox
-\spx@ifcaptionpackage{\abovecaptionskip}{\sphinxbaselineskip}%
+\sphinxbelowcaptionspace\relax}%
\def\sphinxatlongtableend{\prevdepth\z@\vskip\sphinxtablepost\relax}%
\def\sphinxatlongtableend{\@nobreakfalse % latex3/latex2e#173
\prevdepth\z@\vskip\sphinxtablepost\relax}%
% B. Table with tabular or tabulary
\def\sphinxattablestart{\par\vskip\dimexpr\sphinxtablepre\relax}%
\let\sphinxattableend\sphinxatlongtableend
@ -527,6 +528,7 @@
\fi
% make commands known to non-Sphinx document classes
\providecommand*{\sphinxmaketitle}{\maketitle}
\providecommand*{\sphinxtableofcontents}{\tableofcontents}
\ltx@ifundefined{sphinxthebibliography}
{\newenvironment

View File

@ -53,7 +53,8 @@ def publish_msgstr(app, source, source_path, source_line, config, settings):
:rtype: docutils.nodes.document
"""
from sphinx.io import SphinxI18nReader
reader = SphinxI18nReader(app)
reader = SphinxI18nReader()
reader.setup(app)
parser = app.registry.create_source_parser(app, 'restructuredtext')
doc = reader.read(
source=StringInput(source=source,

View File

@ -220,7 +220,7 @@ def save_traceback(app: "Sphinx") -> str:
platform.python_version(),
platform.python_implementation(),
docutils.__version__, docutils.__version_details__,
jinja2.__version__,
jinja2.__version__, # type: ignore
last_msgs)).encode())
if app is not None:
for ext in app.extensions.values():

View File

@ -50,13 +50,13 @@ additional_nodes = set() # type: Set[Type[nodes.Element]]
def docutils_namespace() -> Generator[None, None, None]:
"""Create namespace for reST parsers."""
try:
_directives = copy(directives._directives)
_roles = copy(roles._roles)
_directives = copy(directives._directives) # type: ignore
_roles = copy(roles._roles) # type: ignore
yield
finally:
directives._directives = _directives
roles._roles = _roles
directives._directives = _directives # type: ignore
roles._roles = _roles # type: ignore
for node in list(additional_nodes):
unregister_node(node)
@ -65,7 +65,7 @@ def docutils_namespace() -> Generator[None, None, None]:
def is_directive_registered(name: str) -> bool:
"""Check the *name* directive is already registered."""
return name in directives._directives
return name in directives._directives # type: ignore
def register_directive(name: str, directive: "Type[Directive]") -> None:
@ -79,7 +79,7 @@ def register_directive(name: str, directive: "Type[Directive]") -> None:
def is_role_registered(name: str) -> bool:
"""Check the *name* role is already registered."""
return name in roles._roles
return name in roles._roles # type: ignore
def register_role(name: str, role: RoleFunction) -> None:
@ -93,7 +93,7 @@ def register_role(name: str, role: RoleFunction) -> None:
def unregister_role(name: str) -> None:
"""Unregister a role from docutils."""
roles._roles.pop(name, None)
roles._roles.pop(name, None) # type: ignore
def is_node_registered(node: "Type[Element]") -> bool:
@ -108,7 +108,7 @@ def register_node(node: "Type[Element]") -> None:
inside ``docutils_namespace()`` to prevent side-effects.
"""
if not hasattr(nodes.GenericNodeVisitor, 'visit_' + node.__name__):
nodes._add_node_class_names([node.__name__])
nodes._add_node_class_names([node.__name__]) # type: ignore
additional_nodes.add(node)

View File

@ -524,7 +524,7 @@ class Signature:
else:
qualname = repr(annotation)
if (isinstance(annotation, typing.TupleMeta) and
if (isinstance(annotation, typing.TupleMeta) and # type: ignore
not hasattr(annotation, '__tuple_params__')): # for Python 3.6
params = annotation.__args__
if params:
@ -550,7 +550,7 @@ class Signature:
param_str = ', '.join(self.format_annotation(p) for p in params)
return '%s[%s]' % (qualname, param_str)
elif (hasattr(typing, 'UnionMeta') and
isinstance(annotation, typing.UnionMeta) and
isinstance(annotation, typing.UnionMeta) and # type: ignore
hasattr(annotation, '__union_params__')): # for Python 3.5
params = annotation.__union_params__
if params is not None:
@ -568,7 +568,7 @@ class Signature:
else:
param_str = ', '.join(self.format_annotation(p) for p in params)
return 'Union[%s]' % param_str
elif (isinstance(annotation, typing.CallableMeta) and
elif (isinstance(annotation, typing.CallableMeta) and # type: ignore
getattr(annotation, '__args__', None) is not None and
hasattr(annotation, '__result__')): # for Python 3.5
# Skipped in the case of plain typing.Callable
@ -583,7 +583,7 @@ class Signature:
return '%s[%s, %s]' % (qualname,
args_str,
self.format_annotation(annotation.__result__))
elif (isinstance(annotation, typing.TupleMeta) and
elif (isinstance(annotation, typing.TupleMeta) and # type: ignore
hasattr(annotation, '__tuple_params__') and
hasattr(annotation, '__tuple_use_ellipsis__')): # for Python 3.5
params = annotation.__tuple_params__

View File

@ -210,7 +210,7 @@ class TexinfoTranslator(SphinxTranslator):
for index in self.indices:
name, content = index
pointers = tuple([name] + self.rellinks[name])
self.body.append('\n@node %s,%s,%s,%s\n' % pointers) # type: ignore
self.body.append('\n@node %s,%s,%s,%s\n' % pointers)
self.body.append('@unnumbered %s\n\n%s\n' % (name, content))
while self.referenced_ids:
@ -616,7 +616,7 @@ class TexinfoTranslator(SphinxTranslator):
node_name = node['node_name']
pointers = tuple([node_name] + self.rellinks[node_name])
self.body.append('\n@node %s,%s,%s,%s\n' % pointers) # type: ignore
self.body.append('\n@node %s,%s,%s,%s\n' % pointers)
for id in sorted(self.next_section_ids):
self.add_anchor(id, node)