Merge branch '1.7'

This commit is contained in:
Takeshi KOMIYA 2018-05-21 23:07:54 +09:00
commit 506d4c87ef
11 changed files with 105 additions and 13 deletions

View File

@ -161,6 +161,12 @@ Bugs fixed
* #4969: autodoc: constructor method should not have return annotation
* latex: deeply nested enumerated list which is beginning with non-1 causes
LaTeX engine crashed
* #4978: latex: shorthandoff is not set up for Brazil locale
* #4928: i18n: Ignore dot-directories like .git/ in LC_MESSAGES/
* #4946: py domain: type field could not handle "None" as a type
* #4979: latex: Incorrect escaping of curly braces in index entries
* #4956: autodoc: Failed to extract document from a subclass of the class on
mocked module
Testing
--------

View File

@ -27,6 +27,7 @@ from sphinx.util.build_phase import BuildPhase
from sphinx.util.console import bold # type: ignore
from sphinx.util.docutils import sphinx_domains
from sphinx.util.i18n import find_catalog
from sphinx.util.matching import Matcher
from sphinx.util.osutil import SEP, ensuredir, relative_uri, relpath
from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \
parallel_available
@ -261,7 +262,8 @@ class Builder(object):
self.config.language,
charset=self.config.source_encoding,
gettext_compact=self.config.gettext_compact,
force_all=True)
force_all=True,
excluded=Matcher(['**/.?**']))
message = __('all of %d po files') % len(catalogs)
self.compile_catalogs(catalogs, message)
@ -282,7 +284,8 @@ class Builder(object):
self.config.language,
domains=list(specified_domains),
charset=self.config.source_encoding,
gettext_compact=self.config.gettext_compact)
gettext_compact=self.config.gettext_compact,
excluded=Matcher(['**/.?**']))
message = __('targets for %d po files that are specified') % len(catalogs)
self.compile_catalogs(catalogs, message)
@ -292,7 +295,8 @@ class Builder(object):
[path.join(self.srcdir, x) for x in self.config.locale_dirs],
self.config.language,
charset=self.config.source_encoding,
gettext_compact=self.config.gettext_compact)
gettext_compact=self.config.gettext_compact,
excluded=Matcher(['**/.?**']))
message = __('targets for %d po files that are out of date') % len(catalogs)
self.compile_catalogs(catalogs, message)

View File

@ -176,7 +176,15 @@ class PyGroupedField(PyXrefMixin, GroupedField):
class PyTypedField(PyXrefMixin, TypedField):
pass
def make_xref(self, rolename, domain, target,
innernode=nodes.emphasis, contnode=None, env=None):
# type: (unicode, unicode, unicode, nodes.Node, nodes.Node, BuildEnvironment) -> nodes.Node # NOQA
if rolename == 'class' and target == 'None':
# None is not a type, so use obj role instead.
rolename = 'obj'
return super(PyTypedField, self).make_xref(rolename, domain, target,
innernode, contnode, env)
class PyObject(ObjectDescription):

View File

@ -23,7 +23,7 @@ from sphinx.util.inspect import isenumclass, safe_getattr
if False:
# For type annotation
from typing import Any, Callable, Dict, Generator, List, Optional # NOQA
from typing import Any, Callable, Dict, Generator, List, Optional, Tuple # NOQA
logger = logging.getLogger(__name__)
@ -31,6 +31,14 @@ logger = logging.getLogger(__name__)
class _MockObject(object):
"""Used by autodoc_mock_imports."""
def __new__(cls, *args, **kwargs):
# type: (Any, Any) -> Any
if len(args) == 3 and isinstance(args[1], tuple) and args[1][-1].__class__ is cls:
# subclassing MockObject
return type(args[0], (_MockObject,), args[2], **kwargs) # type: ignore
else:
return super(_MockObject, cls).__new__(cls)
def __init__(self, *args, **kwargs):
# type: (Any, Any) -> None
pass
@ -47,6 +55,10 @@ class _MockObject(object):
# type: () -> None
pass
def __mro_entries__(self, bases):
# type: (Tuple) -> Tuple
return bases
def __getitem__(self, key):
# type: (str) -> _MockObject
return self

View File

@ -1612,6 +1612,10 @@
% figure legend comes after caption and may contain arbitrary body elements
\newenvironment{sphinxlegend}{\par\small}{\par}
% For curly braces inside \index macro
\def\sphinxleftcurlybrace{\{}
\def\sphinxrightcurlybrace{\}}
% Declare Unicode characters used by linux tree command to pdflatex utf8/utf8x
\def\spx@bd#1#2{%
\leavevmode

View File

@ -23,8 +23,10 @@ from babel.messages.pofile import read_po
from sphinx.errors import SphinxError
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.matching import Matcher
from sphinx.util.osutil import SEP, relpath, walk
logger = logging.getLogger(__name__)
if False:
@ -102,8 +104,9 @@ def find_catalog_files(docname, srcdir, locale_dirs, lang, compaction):
def find_catalog_source_files(locale_dirs, locale, domains=None, gettext_compact=False,
charset='utf-8', force_all=False):
# type: (List[unicode], unicode, List[unicode], bool, unicode, bool) -> Set[CatalogInfo]
charset='utf-8', force_all=False,
excluded=Matcher([])):
# type: (List[unicode], unicode, List[unicode], bool, unicode, bool, Matcher) -> Set[CatalogInfo] # NOQA
"""
:param list locale_dirs:
list of path as `['locale_dir1', 'locale_dir2', ...]` to find
@ -137,6 +140,8 @@ def find_catalog_source_files(locale_dirs, locale, domains=None, gettext_compact
for dirpath, dirnames, filenames in walk(base_dir, followlinks=True):
filenames = [f for f in filenames if f.endswith('.po')]
for filename in filenames:
if excluded(path.join(relpath(dirpath, base_dir), filename)):
continue
base = path.splitext(filename)[0]
domain = relpath(path.join(dirpath, base), base_dir)
if gettext_compact and path.sep in domain:

View File

@ -196,6 +196,7 @@ class ExtBabel(Babel):
'ngerman': '"',
'slovene': '"',
'portuges': '"',
'brazil': '"',
'spanish': '"',
'dutch': '"',
'polish': '"',
@ -1932,6 +1933,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_index(self, node, scre=re.compile(r';\s*')):
# type: (nodes.Node, Pattern) -> None
def escape(value):
value = self.encode(value)
value = value.replace(r'\{', r'\sphinxleftcurlybrace')
value = value.replace(r'\}', r'\sphinxrightcurlybrace')
return value
if not node.get('inline', True):
self.body.append('\n')
entries = node['entries']
@ -1941,24 +1948,23 @@ class LaTeXTranslator(nodes.NodeVisitor):
m = '|textbf'
try:
if type == 'single':
p = scre.sub('!', self.encode(string))
p = scre.sub('!', escape(string))
self.body.append(r'\index{%s%s}' % (p, m))
elif type == 'pair':
p1, p2 = [self.encode(x) for x in split_into(2, 'pair', string)]
p1, p2 = [escape(x) for x in split_into(2, 'pair', string)]
self.body.append(r'\index{%s!%s%s}\index{%s!%s%s}' %
(p1, p2, m, p2, p1, m))
elif type == 'triple':
p1, p2, p3 = [self.encode(x)
for x in split_into(3, 'triple', string)]
p1, p2, p3 = [escape(x) for x in split_into(3, 'triple', string)]
self.body.append(
r'\index{%s!%s %s%s}\index{%s!%s, %s%s}'
r'\index{%s!%s %s%s}' %
(p1, p2, p3, m, p2, p3, p1, m, p3, p1, p2, m))
elif type == 'see':
p1, p2 = [self.encode(x) for x in split_into(2, 'see', string)]
p1, p2 = [escape(x) for x in split_into(2, 'see', string)]
self.body.append(r'\index{%s|see{%s}}' % (p1, p2))
elif type == 'seealso':
p1, p2 = [self.encode(x) for x in split_into(2, 'seealso', string)]
p1, p2 = [escape(x) for x in split_into(2, 'seealso', string)]
self.body.append(r'\index{%s|see{%s}}' % (p1, p2))
else:
logger.warning(__('unknown index entry type %s found'), type)

View File

@ -10,3 +10,7 @@ A :index:`famous` :index:`equation`:
.. index:: Einstein, relativity
and some text.
.. index:: main {
An index entry containing non paired curly brace

View File

@ -1201,6 +1201,7 @@ def test_latex_index(app, status, warning):
result = (app.outdir / 'Python.tex').text(encoding='utf8')
assert 'A \\index{famous}famous \\index{equation}equation:\n' in result
assert '\n\\index{Einstein}\\index{relativity}\\ignorespaces \nand' in result
assert '\n\\index{main \\sphinxleftcurlybrace}\\ignorespaces ' in result
@pytest.mark.sphinx('latex', testroot='latex-equations')

View File

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
"""
test_ext_autodoc_importer
~~~~~~~~~~~~~~~~~~~~~~~~~
Test the autodoc extension.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from sphinx.ext.autodoc.importer import _MockObject
def test_MockObject():
mock = _MockObject()
assert isinstance(mock.some_attr, _MockObject)
assert isinstance(mock.some_method, _MockObject)
assert isinstance(mock.attr1.attr2, _MockObject)
assert isinstance(mock.attr1.attr2.meth(), _MockObject)
class SubClass(mock.SomeClass):
"""docstring of SubClass"""
def method(self):
return "string"
obj = SubClass()
assert SubClass.__doc__ == "docstring of SubClass"
assert isinstance(obj, SubClass)
assert obj.method() == "string"
assert isinstance(obj.other_method(), SubClass)

View File

@ -157,6 +157,17 @@ def test_get_catalogs_with_compact(tempdir):
assert domains == set(['test1', 'test2', 'sub'])
def test_get_catalogs_excluded(tempdir):
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES' / '.git').makedirs()
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES' / 'en_dom.po').write_text('#')
(tempdir / 'loc1' / 'en' / 'LC_MESSAGES' / '.git' / 'no_no.po').write_text('#')
catalogs = i18n.find_catalog_source_files(
[tempdir / 'loc1'], 'en', force_all=False, excluded=lambda path: '.git' in path)
domains = set(c.domain for c in catalogs)
assert domains == set(['en_dom'])
def test_format_date():
date = datetime.date(2016, 2, 7)