Merge branch '1.8' into 5433_latex_ImportError

This commit is contained in:
Takeshi KOMIYA 2018-09-18 22:50:54 +09:00 committed by GitHub
commit 2c0359f3a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 64 additions and 41 deletions

View File

@ -19,6 +19,10 @@ Bugs fixed
* #5418: Incorrect default path for sphinx-build -d/doctrees files * #5418: Incorrect default path for sphinx-build -d/doctrees files
* #5421: autodoc emits deprecation warning for :confval:`autodoc_default_flags` * #5421: autodoc emits deprecation warning for :confval:`autodoc_default_flags`
* #5422: lambda object causes PicklingError on storing environment * #5422: lambda object causes PicklingError on storing environment
* #5417: Sphinx fails to build with syntax error in Python 2.7.5
* #4911: add latexpdf to make.bat for non make-mode
* #5436: Autodoc does not work with enum subclasses with properties/methods
* #5437: autodoc: crashed on modules importing eggs
* #5433: latex: ImportError: cannot import name 'DEFAULT_SETTINGS' * #5433: latex: ImportError: cannot import name 'DEFAULT_SETTINGS'
Testing Testing
@ -36,6 +40,7 @@ Dependencies
``xelatex/lualatex``), instructs ``make latexpdf`` to use :program:`xindy` ``xelatex/lualatex``), instructs ``make latexpdf`` to use :program:`xindy`
for general index. Make sure your LaTeX distribution includes it. for general index. Make sure your LaTeX distribution includes it.
(refs: #5134) (refs: #5134)
* LaTeX: ``latexmk`` is required for ``make latexpdf`` on Windows
Incompatible changes Incompatible changes
-------------------- --------------------

View File

@ -4,7 +4,7 @@
.. image:: https://img.shields.io/pypi/v/sphinx.svg .. image:: https://img.shields.io/pypi/v/sphinx.svg
:target: https://pypi.org/project/Sphinx/ :target: https://pypi.org/project/Sphinx/
:alt: Package on PyPi :alt: Package on PyPI
.. image:: https://readthedocs.org/projects/sphinx/badge/?version=master .. image:: https://readthedocs.org/projects/sphinx/badge/?version=master
:target: http://www.sphinx-doc.org/ :target: http://www.sphinx-doc.org/

View File

@ -16,7 +16,7 @@ import warnings
from collections import namedtuple from collections import namedtuple
from types import FunctionType, MethodType, ModuleType from types import FunctionType, MethodType, ModuleType
from six import PY2 from six import PY2, iteritems
from sphinx.util import logging from sphinx.util import logging
from sphinx.util.inspect import isenumclass, safe_getattr from sphinx.util.inspect import isenumclass, safe_getattr
@ -248,6 +248,11 @@ def get_object_members(subject, objpath, attrgetter, analyzer=None):
if name not in members: if name not in members:
members[name] = Attribute(name, True, value) members[name] = Attribute(name, True, value)
superclass = subject.__mro__[1]
for name, value in iteritems(obj_dict):
if name not in superclass.__dict__:
members[name] = Attribute(name, True, value)
# other members # other members
for name in dir(subject): for name in dir(subject):
try: try:

View File

@ -153,7 +153,7 @@ class TestDirective(SphinxDirective):
if self.name == 'doctest' and 'pyversion' in self.options: if self.name == 'doctest' and 'pyversion' in self.options:
try: try:
spec = self.options['pyversion'] spec = self.options['pyversion']
python_version = '.'.join(str(v) for v in sys.version_info[:3]) python_version = '.'.join([str(v) for v in sys.version_info[:3]])
if not is_allowed_version(spec, python_version): if not is_allowed_version(spec, python_version):
flag = doctest.OPTIONFLAGS_BY_NAME['SKIP'] flag = doctest.OPTIONFLAGS_BY_NAME['SKIP']
node['options'][flag] = True # Skip the test node['options'][flag] = True # Skip the test

View File

@ -427,6 +427,6 @@ def inspect_main(argv):
if __name__ == '__main__': if __name__ == '__main__':
import logging # type: ignore import logging # type: ignore
logging.basicConfig() logging.basicConfig() # type: ignore
inspect_main(argv=sys.argv[1:]) # type: ignore inspect_main(argv=sys.argv[1:]) # type: ignore

View File

@ -32,7 +32,7 @@ class ModuleAnalyzer(object):
def for_string(cls, string, modname, srcname='<string>'): def for_string(cls, string, modname, srcname='<string>'):
# type: (unicode, unicode, unicode) -> ModuleAnalyzer # type: (unicode, unicode, unicode) -> ModuleAnalyzer
if isinstance(string, bytes): if isinstance(string, bytes):
return cls(BytesIO(string), modname, srcname) return cls(BytesIO(string), modname, srcname) # type: ignore
return cls(StringIO(string), modname, srcname, decoded=True) # type: ignore return cls(StringIO(string), modname, srcname, decoded=True) # type: ignore
@classmethod @classmethod

View File

@ -31,6 +31,7 @@ if "%1" == "help" (
echo. devhelp to make HTML files and a Devhelp project echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. latexpdf to make LaTeX files and run them through platex/dvipdfmx
echo. text to make text files echo. text to make text files
echo. man to make manual pages echo. man to make manual pages
echo. texinfo to make Texinfo files echo. texinfo to make Texinfo files

View File

@ -30,7 +30,7 @@ class path(text_type):
# type: (unicode, unicode, unicode) -> path # type: (unicode, unicode, unicode) -> path
if isinstance(s, str): if isinstance(s, str):
s = s.decode(encoding, errors) s = s.decode(encoding, errors)
return text_type.__new__(cls, s) return text_type.__new__(cls, s) # type: ignore
return text_type.__new__(cls, s) # type: ignore return text_type.__new__(cls, s) # type: ignore
@property @property

View File

@ -314,8 +314,9 @@ def get_module_source(modname):
filename += 'w' filename += 'w'
elif not (lfilename.endswith('.py') or lfilename.endswith('.pyw')): elif not (lfilename.endswith('.py') or lfilename.endswith('.pyw')):
raise PycodeError('source is not a .py file: %r' % filename) raise PycodeError('source is not a .py file: %r' % filename)
elif '.egg' in filename: elif ('.egg' + os.path.sep) in filename:
eggpath, _ = re.split('(?<=\\.egg)/', filename) pat = '(?<=\\.egg)' + re.escape(os.path.sep)
eggpath, _ = re.split(pat, filename, 1)
if path.isfile(eggpath): if path.isfile(eggpath):
return 'file', filename return 'file', filename

View File

@ -73,7 +73,7 @@ def get_image_size(filename):
def guess_mimetype_for_stream(stream, default=None): def guess_mimetype_for_stream(stream, default=None):
# type: (IO, unicode) -> unicode # type: (IO, unicode) -> unicode
imgtype = imghdr.what(stream) imgtype = imghdr.what(stream) # type: ignore
if imgtype: if imgtype:
return 'image/' + imgtype return 'image/' + imgtype
else: else:
@ -141,4 +141,4 @@ def test_svg(h, f):
# install test_svg() to imghdr # install test_svg() to imghdr
# refs: https://docs.python.org/3.6/library/imghdr.html#imghdr.tests # refs: https://docs.python.org/3.6/library/imghdr.html#imghdr.tests
imghdr.tests.append(test_svg) imghdr.tests.append(test_svg) # type: ignore

View File

@ -235,7 +235,7 @@ def abspath(pathdir):
try: try:
pathdir = pathdir.decode(fs_encoding) pathdir = pathdir.decode(fs_encoding)
except UnicodeDecodeError: except UnicodeDecodeError:
raise UnicodeDecodeError('multibyte filename not supported on ' raise UnicodeDecodeError('multibyte filename not supported on ' # type: ignore
'this filesystem encoding ' 'this filesystem encoding '
'(%r)' % fs_encoding) '(%r)' % fs_encoding)
return pathdir return pathdir

View File

@ -34,7 +34,7 @@ except ImportError:
from urllib3.exceptions import InsecureRequestWarning # type: ignore from urllib3.exceptions import InsecureRequestWarning # type: ignore
except ImportError: except ImportError:
# for requests < 2.4.0 # for requests < 2.4.0
InsecureRequestWarning = None InsecureRequestWarning = None # type: ignore
try: try:
from requests.packages.urllib3.exceptions import InsecurePlatformWarning from requests.packages.urllib3.exceptions import InsecurePlatformWarning
@ -44,7 +44,7 @@ except ImportError:
from urllib3.exceptions import InsecurePlatformWarning # type: ignore from urllib3.exceptions import InsecurePlatformWarning # type: ignore
except ImportError: except ImportError:
# for requests < 2.4.0 # for requests < 2.4.0
InsecurePlatformWarning = None InsecurePlatformWarning = None # type: ignore
# try to load requests[security] (but only if SSL is available) # try to load requests[security] (but only if SSL is available)
try: try:

View File

@ -223,19 +223,6 @@ class InstAttCls(object):
"""Docstring for instance attribute InstAttCls.ia2.""" """Docstring for instance attribute InstAttCls.ia2."""
class EnumCls(enum.Enum):
"""
this is enum class
"""
#: doc for val1
val1 = 12
val2 = 23 #: doc for val2
val3 = 34
"""doc for val3"""
val4 = 34
class CustomIter(object): class CustomIter(object):
def __init__(self): def __init__(self):
"""Create a new `CustomIter`.""" """Create a new `CustomIter`."""

View File

@ -0,0 +1,19 @@
from __future__ import absolute_import
import enum
class EnumCls(enum.Enum):
"""
this is enum class
"""
#: doc for val1
val1 = 12
val2 = 23 #: doc for val2
val3 = 34
"""doc for val3"""
val4 = 34
def say_hello(self):
"""a method says hello to you."""
pass

View File

@ -829,7 +829,6 @@ def test_autodoc_ignore_module_all(app):
'.. py:class:: CustomDataDescriptor2(doc)', '.. py:class:: CustomDataDescriptor2(doc)',
'.. py:class:: CustomDataDescriptorMeta', '.. py:class:: CustomDataDescriptorMeta',
'.. py:class:: CustomDict', '.. py:class:: CustomDict',
'.. py:class:: EnumCls',
'.. py:class:: InstAttCls()', '.. py:class:: InstAttCls()',
'.. py:class:: Outer', '.. py:class:: Outer',
' .. py:class:: Outer.Inner', ' .. py:class:: Outer.Inner',
@ -1263,48 +1262,54 @@ def test_instance_attributes(app):
def test_enum_class(app): def test_enum_class(app):
options = {"members": None, options = {"members": None,
"undoc-members": True} "undoc-members": True}
actual = do_autodoc(app, 'class', 'target.EnumCls', options) actual = do_autodoc(app, 'class', 'target.enum.EnumCls', options)
assert list(actual) == [ assert list(actual) == [
'', '',
'.. py:class:: EnumCls', '.. py:class:: EnumCls',
' :module: target', ' :module: target.enum',
'', '',
' this is enum class', ' this is enum class',
' ', ' ',
' ', ' ',
' .. py:method:: EnumCls.say_hello()',
' :module: target.enum',
' ',
' a method says hello to you.',
' ',
' ',
' .. py:attribute:: EnumCls.val1', ' .. py:attribute:: EnumCls.val1',
' :module: target', ' :module: target.enum',
' :annotation: = 12', ' :annotation: = 12',
' ', ' ',
' doc for val1', ' doc for val1',
' ', ' ',
' ', ' ',
' .. py:attribute:: EnumCls.val2', ' .. py:attribute:: EnumCls.val2',
' :module: target', ' :module: target.enum',
' :annotation: = 23', ' :annotation: = 23',
' ', ' ',
' doc for val2', ' doc for val2',
' ', ' ',
' ', ' ',
' .. py:attribute:: EnumCls.val3', ' .. py:attribute:: EnumCls.val3',
' :module: target', ' :module: target.enum',
' :annotation: = 34', ' :annotation: = 34',
' ', ' ',
' doc for val3', ' doc for val3',
' ', ' ',
' ', ' ',
' .. py:attribute:: EnumCls.val4', ' .. py:attribute:: EnumCls.val4',
' :module: target', ' :module: target.enum',
' :annotation: = 34', ' :annotation: = 34',
' ' ' '
] ]
# checks for an attribute of EnumClass # checks for an attribute of EnumClass
actual = do_autodoc(app, 'attribute', 'target.EnumCls.val1') actual = do_autodoc(app, 'attribute', 'target.enum.EnumCls.val1')
assert list(actual) == [ assert list(actual) == [
'', '',
'.. py:attribute:: EnumCls.val1', '.. py:attribute:: EnumCls.val1',
' :module: target', ' :module: target.enum',
' :annotation: = 12', ' :annotation: = 12',
'', '',
' doc for val1', ' doc for val1',
@ -1473,7 +1478,7 @@ def test_merge_autodoc_default_flags2(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc') @pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_default_options(app): def test_autodoc_default_options(app):
# no settings # no settings
actual = do_autodoc(app, 'class', 'target.EnumCls') actual = do_autodoc(app, 'class', 'target.enum.EnumCls')
assert ' .. py:attribute:: EnumCls.val1' not in actual assert ' .. py:attribute:: EnumCls.val1' not in actual
assert ' .. py:attribute:: EnumCls.val4' not in actual assert ' .. py:attribute:: EnumCls.val4' not in actual
actual = do_autodoc(app, 'class', 'target.CustomIter') actual = do_autodoc(app, 'class', 'target.CustomIter')
@ -1481,7 +1486,7 @@ def test_autodoc_default_options(app):
# with :members: # with :members:
app.config.autodoc_default_options = {'members': None} app.config.autodoc_default_options = {'members': None}
actual = do_autodoc(app, 'class', 'target.EnumCls') actual = do_autodoc(app, 'class', 'target.enum.EnumCls')
assert ' .. py:attribute:: EnumCls.val1' in actual assert ' .. py:attribute:: EnumCls.val1' in actual
assert ' .. py:attribute:: EnumCls.val4' not in actual assert ' .. py:attribute:: EnumCls.val4' not in actual
@ -1490,7 +1495,7 @@ def test_autodoc_default_options(app):
'members': None, 'members': None,
'undoc-members': None, 'undoc-members': None,
} }
actual = do_autodoc(app, 'class', 'target.EnumCls') actual = do_autodoc(app, 'class', 'target.enum.EnumCls')
assert ' .. py:attribute:: EnumCls.val1' in actual assert ' .. py:attribute:: EnumCls.val1' in actual
assert ' .. py:attribute:: EnumCls.val4' in actual assert ' .. py:attribute:: EnumCls.val4' in actual
@ -1516,7 +1521,7 @@ def test_autodoc_default_options(app):
'members': None, 'members': None,
'exclude-members': None, 'exclude-members': None,
} }
actual = do_autodoc(app, 'class', 'target.EnumCls') actual = do_autodoc(app, 'class', 'target.enum.EnumCls')
assert ' .. py:attribute:: EnumCls.val1' in actual assert ' .. py:attribute:: EnumCls.val1' in actual
assert ' .. py:attribute:: EnumCls.val4' not in actual assert ' .. py:attribute:: EnumCls.val4' not in actual
app.config.autodoc_default_options = { app.config.autodoc_default_options = {
@ -1540,7 +1545,7 @@ def test_autodoc_default_options(app):
def test_autodoc_default_options_with_values(app): def test_autodoc_default_options_with_values(app):
# with :members: # with :members:
app.config.autodoc_default_options = {'members': 'val1,val2'} app.config.autodoc_default_options = {'members': 'val1,val2'}
actual = do_autodoc(app, 'class', 'target.EnumCls') actual = do_autodoc(app, 'class', 'target.enum.EnumCls')
assert ' .. py:attribute:: EnumCls.val1' in actual assert ' .. py:attribute:: EnumCls.val1' in actual
assert ' .. py:attribute:: EnumCls.val2' in actual assert ' .. py:attribute:: EnumCls.val2' in actual
assert ' .. py:attribute:: EnumCls.val3' not in actual assert ' .. py:attribute:: EnumCls.val3' not in actual
@ -1564,7 +1569,7 @@ def test_autodoc_default_options_with_values(app):
'members': None, 'members': None,
'exclude-members': 'val1' 'exclude-members': 'val1'
} }
actual = do_autodoc(app, 'class', 'target.EnumCls') actual = do_autodoc(app, 'class', 'target.enum.EnumCls')
assert ' .. py:attribute:: EnumCls.val1' not in actual assert ' .. py:attribute:: EnumCls.val1' not in actual
assert ' .. py:attribute:: EnumCls.val2' in actual assert ' .. py:attribute:: EnumCls.val2' in actual
assert ' .. py:attribute:: EnumCls.val3' in actual assert ' .. py:attribute:: EnumCls.val3' in actual