Merge branch 'master' into drop-iteritems

This commit is contained in:
Takeshi KOMIYA
2018-09-22 22:17:38 +09:00
committed by GitHub
223 changed files with 119771 additions and 16409 deletions

View File

@@ -9,7 +9,6 @@
import os
import shutil
import sys
import docutils
import pytest
@@ -22,13 +21,6 @@ pytest_plugins = 'sphinx.testing.fixtures'
# Exclude 'roots' dirs for pytest test collector
collect_ignore = ['roots']
# Disable Python version-specific
if sys.version_info < (3,):
collect_ignore += ['py3']
if sys.version_info < (3, 5):
collect_ignore += ['py35']
@pytest.fixture(scope='session')
def rootdir():

View File

@@ -1,26 +0,0 @@
# -*- coding: utf-8 -*-
"""
py3/test_util_inspect
~~~~~~~~~~~~~~~~~~~~~
Tests util.inspect functions.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from sphinx.util import inspect
def test_Signature_keyword_only_arguments():
def func1(arg1, arg2, *, arg3=None, arg4=None):
pass
def func2(*, arg3, arg4):
pass
sig = inspect.Signature(func1).format_args()
assert sig == '(arg1, arg2, *, arg3=None, arg4=None)'
sig = inspect.Signature(func2).format_args()
assert sig == '(*, arg3, arg4)'

View File

@@ -1,348 +0,0 @@
# -*- coding: utf-8 -*-
"""
test_autodoc
~~~~~~~~~~~~
Test the autodoc extension. This tests mainly the Documenters; the auto
directives are tested in a test source file translated by test_build.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
# "raises" imported for usage by autodoc
import sys
import pytest
import six
from docutils.statemachine import ViewList
from six import StringIO
from sphinx.ext.autodoc import FunctionDocumenter, ALL, Options
from sphinx.testing.util import SphinxTestApp, Struct
from sphinx.util import logging
from sphinx.util import save_traceback # NOQA
app = None
@pytest.fixture(scope='module', autouse=True)
def setup_module(rootdir, sphinx_test_tempdir):
global app
srcdir = sphinx_test_tempdir / 'autodoc-root'
if not srcdir.exists():
(rootdir / 'test-root').copytree(srcdir)
app = SphinxTestApp(srcdir=srcdir)
app.builder.env.app = app
app.builder.env.temp_data['docname'] = 'dummy'
app.connect('autodoc-process-docstring', process_docstring)
app.connect('autodoc-process-signature', process_signature)
app.connect('autodoc-skip-member', skip_member)
yield
app.cleanup()
directive = options = None
@pytest.fixture
def setup_test():
global options, directive
global processed_docstrings, processed_signatures
options = Options(
inherited_members = False,
undoc_members = False,
private_members = False,
special_members = False,
imported_members = False,
show_inheritance = False,
noindex = False,
annotation = None,
synopsis = '',
platform = '',
deprecated = False,
members = [],
member_order = 'alphabetic',
exclude_members = set(),
)
directive = Struct(
env = app.builder.env,
genopt = options,
result = ViewList(),
filename_set = set(),
)
processed_docstrings = []
processed_signatures = []
processed_docstrings = []
processed_signatures = []
def process_docstring(app, what, name, obj, options, lines):
processed_docstrings.append((what, name))
if name == 'bar':
lines.extend(['42', ''])
def process_signature(app, what, name, obj, options, args, retann):
processed_signatures.append((what, name))
if name == 'bar':
return '42', None
def skip_member(app, what, name, obj, skip, options):
if name in ('__special1__', '__special2__'):
return skip
if name.startswith('_'):
return True
if name == 'skipmeth':
return True
@pytest.mark.usefixtures('setup_test')
def test_generate():
logging.setup(app, app._status, app._warning)
def assert_warns(warn_str, objtype, name, **kw):
inst = app.registry.documenters[objtype](directive, name)
inst.generate(**kw)
assert len(directive.result) == 0, directive.result
assert warn_str in app._warning.getvalue()
app._warning.truncate(0)
def assert_works(objtype, name, **kw):
inst = app.registry.documenters[objtype](directive, name)
inst.generate(**kw)
assert directive.result
# print '\n'.join(directive.result)
assert app._warning.getvalue() == ''
del directive.result[:]
def assert_processes(items, objtype, name, **kw):
del processed_docstrings[:]
del processed_signatures[:]
assert_works(objtype, name, **kw)
assert set(processed_docstrings) | set(processed_signatures) == set(items)
def assert_result_contains(item, objtype, name, **kw):
inst = app.registry.documenters[objtype](directive, name)
inst.generate(**kw)
# print '\n'.join(directive.result)
assert app._warning.getvalue() == ''
assert item in directive.result
del directive.result[:]
def assert_order(items, objtype, name, member_order, **kw):
inst = app.registry.documenters[objtype](directive, name)
inst.options.member_order = member_order
inst.generate(**kw)
assert app._warning.getvalue() == ''
items = list(reversed(items))
lineiter = iter(directive.result)
# for line in directive.result:
# if line.strip():
# print repr(line)
while items:
item = items.pop()
for line in lineiter:
if line == item:
break
else: # ran out of items!
assert False, ('item %r not found in result or not in the '
' correct order' % item)
del directive.result[:]
options.members = []
# no module found?
assert_warns("import for autodocumenting 'foobar'",
'function', 'foobar', more_content=None)
# importing
assert_warns("failed to import module 'test_foobar'",
'module', 'test_foobar', more_content=None)
# attributes missing
assert_warns("failed to import function 'foobar' from module 'util'",
'function', 'util.foobar', more_content=None)
# method missing
assert_warns("failed to import method 'Class.foobar' from module 'test_autodoc_py35';",
'method', 'test_autodoc_py35.Class.foobar', more_content=None)
# test auto and given content mixing
directive.env.ref_context['py:module'] = 'test_autodoc_py35'
assert_result_contains(' Function.', 'method', 'Class.meth')
add_content = ViewList()
add_content.append('Content.', '', 0)
assert_result_contains(' Function.', 'method',
'Class.meth', more_content=add_content)
assert_result_contains(' Content.', 'method',
'Class.meth', more_content=add_content)
# test check_module
inst = FunctionDocumenter(directive, 'save_traceback')
inst.generate(check_module=True)
assert len(directive.result) == 0
# assert that exceptions can be documented
assert_works('exception', 'test_autodoc_py35.CustomEx', all_members=True)
assert_works('exception', 'test_autodoc_py35.CustomEx')
# test diverse inclusion settings for members
should = [('class', 'test_autodoc_py35.Class')]
assert_processes(should, 'class', 'Class')
should.extend([('method', 'test_autodoc_py35.Class.meth')])
options.members = ['meth']
options.exclude_members = set(['excludemeth'])
assert_processes(should, 'class', 'Class')
should.extend([('attribute', 'test_autodoc_py35.Class.prop'),
('attribute', 'test_autodoc_py35.Class.descr'),
('attribute', 'test_autodoc_py35.Class.attr'),
('attribute', 'test_autodoc_py35.Class.docattr'),
('attribute', 'test_autodoc_py35.Class.udocattr'),
('attribute', 'test_autodoc_py35.Class.mdocattr'),
('attribute', 'test_autodoc_py35.Class.inst_attr_comment'),
('attribute', 'test_autodoc_py35.Class.inst_attr_inline'),
('attribute', 'test_autodoc_py35.Class.inst_attr_string'),
('method', 'test_autodoc_py35.Class.moore'),
])
if six.PY3 and sys.version_info[:2] >= (3, 5):
should.extend([
('method', 'test_autodoc_py35.Class.do_coroutine'),
])
options.members = ALL
assert_processes(should, 'class', 'Class')
options.undoc_members = True
should.extend((('attribute', 'test_autodoc_py35.Class.skipattr'),
('method', 'test_autodoc_py35.Class.undocmeth'),
('method', 'test_autodoc_py35.Class.roger')))
assert_processes(should, 'class', 'Class')
options.inherited_members = True
should.append(('method', 'test_autodoc_py35.Class.inheritedmeth'))
assert_processes(should, 'class', 'Class')
# test special members
options.special_members = ['__special1__']
should.append(('method', 'test_autodoc_py35.Class.__special1__'))
assert_processes(should, 'class', 'Class')
options.special_members = ALL
should.append(('method', 'test_autodoc_py35.Class.__special2__'))
assert_processes(should, 'class', 'Class')
options.special_members = False
# --- generate fodder ------------
__all__ = ['Class']
#: documentation for the integer
integer = 1
class CustomEx(Exception):
"""My custom exception."""
def f(self):
"""Exception method."""
class CustomDataDescriptor(object):
"""Descriptor class docstring."""
def __init__(self, doc):
self.__doc__ = doc
def __get__(self, obj, type=None):
if obj is None:
return self
return 42
def meth(self):
"""Function."""
return "The Answer"
def _funky_classmethod(name, b, c, d, docstring=None):
"""Generates a classmethod for a class from a template by filling out
some arguments."""
def template(cls, a, b, c, d=4, e=5, f=6):
return a, b, c, d, e, f
from functools import partial
function = partial(template, b=b, c=c, d=d)
function.__name__ = name
function.__doc__ = docstring
return classmethod(function)
class Base(object):
def inheritedmeth(self):
"""Inherited function."""
if six.PY3 and sys.version_info[:2] >= (3, 5):
async def _other_coro_func():
return "run"
class Class(Base):
"""Class to document."""
descr = CustomDataDescriptor("Descriptor instance docstring.")
def meth(self):
"""Function."""
def undocmeth(self):
pass
def skipmeth(self):
"""Method that should be skipped."""
def excludemeth(self):
"""Method that should be excluded."""
# should not be documented
skipattr = 'foo'
#: should be documented -- süß
attr = 'bar'
@property
def prop(self):
"""Property."""
docattr = 'baz'
"""should likewise be documented -- süß"""
udocattr = 'quux'
u"""should be documented as well - süß"""
# initialized to any class imported from another module
mdocattr = StringIO()
"""should be documented as well - süß"""
roger = _funky_classmethod("roger", 2, 3, 4)
moore = _funky_classmethod("moore", 9, 8, 7,
docstring="moore(a, e, f) -> happiness")
def __init__(self, arg):
self.inst_attr_inline = None #: an inline documented instance attr
#: a documented instance attribute
self.inst_attr_comment = None
self.inst_attr_string = None
"""a documented instance attribute"""
def __special1__(self):
"""documented special method"""
def __special2__(self):
# undocumented special method
pass
if six.PY3 and sys.version_info[:2] >= (3, 5):
async def do_coroutine(self):
"""A documented coroutine function"""
attr_coro_result = await _other_coro_func() # NOQA

View File

@@ -38,3 +38,10 @@ module
:type y: tuple(str, float)
:rtype: list
.. py:attribute:: attr1
:type: ModTopLevel
.. py:attribute:: attr2
:type: :doc:`index`

View File

@@ -223,19 +223,6 @@ class InstAttCls(object):
"""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):
def __init__(self):
"""Create a new `CustomIter`."""

View File

@@ -0,0 +1,8 @@
class Callable():
"""A callable object that behaves like a function."""
def __call__(self, arg1, arg2, **kwargs):
pass
function = Callable()

View File

@@ -0,0 +1,8 @@
class AsyncClass:
async def do_coroutine(self):
"""A documented coroutine function"""
attr_coro_result = await _other_coro_func() # NOQA
async def _other_coro_func():
return "run"

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

@@ -17,7 +17,6 @@ from warnings import catch_warnings
import pytest
from docutils.statemachine import ViewList
from six import PY3
from sphinx.ext.autodoc import (
ModuleLevelDocumenter, cut_lines, between, ALL,
@@ -30,11 +29,6 @@ from sphinx.util.docutils import LoggingReporter
app = None
if PY3:
ROGER_METHOD = ' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)'
else:
ROGER_METHOD = ' .. py:classmethod:: Class.roger(a, e=5, f=6)'
IS_PYPY = platform.python_implementation() == 'PyPy'
@@ -722,7 +716,7 @@ def test_autodoc_undoc_members(app):
' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.prop',
ROGER_METHOD,
' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
' .. py:attribute:: Class.skipattr',
' .. py:method:: Class.skipmeth()',
' .. py:attribute:: Class.udocattr',
@@ -802,7 +796,7 @@ def test_autodoc_special_members(app):
' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.prop',
ROGER_METHOD,
' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
' .. py:attribute:: Class.skipattr',
' .. py:method:: Class.skipmeth()',
' .. py:attribute:: Class.udocattr',
@@ -829,7 +823,6 @@ def test_autodoc_ignore_module_all(app):
'.. py:class:: CustomDataDescriptor2(doc)',
'.. py:class:: CustomDataDescriptorMeta',
'.. py:class:: CustomDict',
'.. py:class:: EnumCls',
'.. py:class:: InstAttCls()',
'.. py:class:: Outer',
' .. py:class:: Outer.Inner',
@@ -876,11 +869,6 @@ def test_autodoc_subclass_of_builtin_class(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_inner_class(app):
if PY3:
builtins = ' alias of :class:`builtins.dict`'
else:
builtins = ' alias of :class:`__builtin__.dict`'
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.Outer', options)
assert list(actual) == [
@@ -906,7 +894,7 @@ def test_autodoc_inner_class(app):
' .. py:attribute:: Outer.factory',
' :module: target',
' ',
builtins
' alias of :class:`builtins.dict`'
]
actual = do_autodoc(app, 'class', 'target.Outer.Inner', options)
@@ -975,7 +963,7 @@ def test_autodoc_member_order(app):
' .. py:attribute:: Class.docattr',
' .. py:attribute:: Class.udocattr',
' .. py:attribute:: Class.mdocattr',
ROGER_METHOD,
' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.inst_attr_inline',
' .. py:attribute:: Class.inst_attr_comment',
@@ -994,7 +982,7 @@ def test_autodoc_member_order(app):
' .. py:method:: Class.excludemeth()',
' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
ROGER_METHOD,
' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
' .. py:method:: Class.skipmeth()',
' .. py:method:: Class.undocmeth()',
' .. py:attribute:: Class._private_inst_attr',
@@ -1029,7 +1017,7 @@ def test_autodoc_member_order(app):
' .. py:method:: Class.meth()',
' .. py:classmethod:: Class.moore(a, e, f) -> happiness',
' .. py:attribute:: Class.prop',
ROGER_METHOD,
' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)',
' .. py:attribute:: Class.skipattr',
' .. py:method:: Class.skipmeth()',
' .. py:attribute:: Class.udocattr',
@@ -1263,48 +1251,54 @@ def test_instance_attributes(app):
def test_enum_class(app):
options = {"members": None,
"undoc-members": True}
actual = do_autodoc(app, 'class', 'target.EnumCls', options)
actual = do_autodoc(app, 'class', 'target.enum.EnumCls', options)
assert list(actual) == [
'',
'.. py:class:: EnumCls',
' :module: target',
' :module: target.enum',
'',
' this is enum class',
' ',
' ',
' .. py:method:: EnumCls.say_hello()',
' :module: target.enum',
' ',
' a method says hello to you.',
' ',
' ',
' .. py:attribute:: EnumCls.val1',
' :module: target',
' :module: target.enum',
' :annotation: = 12',
' ',
' doc for val1',
' ',
' ',
' .. py:attribute:: EnumCls.val2',
' :module: target',
' :module: target.enum',
' :annotation: = 23',
' ',
' doc for val2',
' ',
' ',
' .. py:attribute:: EnumCls.val3',
' :module: target',
' :module: target.enum',
' :annotation: = 34',
' ',
' doc for val3',
' ',
' ',
' .. py:attribute:: EnumCls.val4',
' :module: target',
' :module: target.enum',
' :annotation: = 34',
' '
]
# 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) == [
'',
'.. py:attribute:: EnumCls.val1',
' :module: target',
' :module: target.enum',
' :annotation: = 12',
'',
' doc for val1',
@@ -1341,6 +1335,19 @@ def test_descriptor_class(app):
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autofunction_for_callable(app):
actual = do_autodoc(app, 'function', 'target.callable.function')
assert list(actual) == [
'',
'.. py:function:: function(arg1, arg2, **kwargs)',
' :module: target.callable',
'',
' A callable object that behaves like a function.',
' '
]
@pytest.mark.sphinx('html', testroot='root')
def test_mocked_module_imports(app):
options = {"members": 'TestAutodoc,decoratedFunction'}
@@ -1408,8 +1415,24 @@ def test_partialfunction():
assert call_autodoc('module', 'target.partialfunction') == expected
@pytest.mark.skipif(sys.version_info < (3, 4),
reason='functools.partialmethod is available on py34 or above')
@pytest.mark.usefixtures('setup_test')
def test_coroutine():
options = {"members": None}
actual = do_autodoc(app, 'class', 'target.coroutine.AsyncClass', options)
assert list(actual) == [
'',
'.. py:class:: AsyncClass',
' :module: target.coroutine',
'',
' ',
' .. py:method:: AsyncClass.do_coroutine()',
' :module: target.coroutine',
' ',
' A documented coroutine function',
' '
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_partialmethod(app):
expected = [
@@ -1473,7 +1496,7 @@ def test_merge_autodoc_default_flags2(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_default_options(app):
# 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.val4' not in actual
actual = do_autodoc(app, 'class', 'target.CustomIter')
@@ -1481,7 +1504,7 @@ def test_autodoc_default_options(app):
# with :members:
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.val4' not in actual
@@ -1490,7 +1513,7 @@ def test_autodoc_default_options(app):
'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.val4' in actual
@@ -1516,7 +1539,7 @@ def test_autodoc_default_options(app):
'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.val4' not in actual
app.config.autodoc_default_options = {
@@ -1540,7 +1563,7 @@ def test_autodoc_default_options(app):
def test_autodoc_default_options_with_values(app):
# with :members:
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.val2' in actual
assert ' .. py:attribute:: EnumCls.val3' not in actual
@@ -1564,7 +1587,7 @@ def test_autodoc_default_options_with_values(app):
'members': None,
'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.val2' in actual
assert ' .. py:attribute:: EnumCls.val3' in actual

View File

@@ -33,11 +33,6 @@ def nonascii_srcdir(request, rootdir, sphinx_test_tempdir):
# If supported, build in a non-ASCII source dir
test_name = u'\u65e5\u672c\u8a9e'
basedir = sphinx_test_tempdir / request.node.originalname
# Windows with versions prior to 3.2 (I think) doesn't support unicode on system path
# so we force a non-unicode path in that case
if (sys.platform == "win32" and
not (sys.version_info.major >= 3 and sys.version_info.minor >= 2)):
return basedir / 'all'
try:
srcdir = basedir / test_name
if not srcdir.exists():

View File

@@ -16,10 +16,9 @@ from itertools import cycle, chain
import pytest
from html5lib import getTreeBuilder, HTMLParser
from six import PY3
from sphinx.errors import ConfigError
from sphinx.testing.util import remove_unicode_literals, strip_escseq
from sphinx.testing.util import strip_escseq
from sphinx.util.inventory import InventoryFile
@@ -30,10 +29,10 @@ ENV_WARNINGS = """\
%(root)s/autodoc_fodder.py:docstring of autodoc_fodder.MarkupError:\\d+: \
WARNING: Explicit markup ends without a blank line; unexpected unindent.
%(root)s/index.rst:\\d+: WARNING: Encoding 'utf-8-sig' used for reading included \
file u'%(root)s/wrongenc.inc' seems to be wrong, try giving an :encoding: option
file '%(root)s/wrongenc.inc' seems to be wrong, try giving an :encoding: option
%(root)s/index.rst:\\d+: WARNING: image file not readable: foo.png
%(root)s/index.rst:\\d+: WARNING: download file not readable: %(root)s/nonexisting.png
%(root)s/index.rst:\\d+: WARNING: invalid single index entry u''
%(root)s/index.rst:\\d+: WARNING: invalid single index entry ''
%(root)s/undecodable.rst:\\d+: WARNING: undecodable source characters, replacing \
with "\\?": b?'here: >>>(\\\\|/)xbb<<<((\\\\|/)r)?'
"""
@@ -45,10 +44,6 @@ HTML_WARNINGS = ENV_WARNINGS + """\
%(root)s/index.rst:\\d+: WARNING: Could not lex literal_block as "c". Highlighting skipped.
"""
if PY3:
ENV_WARNINGS = remove_unicode_literals(ENV_WARNINGS)
HTML_WARNINGS = remove_unicode_literals(HTML_WARNINGS)
etree_cache = {}

View File

@@ -17,11 +17,10 @@ from shutil import copyfile
from subprocess import Popen, PIPE
import pytest
from six import PY3
from test_build_html import ENV_WARNINGS
from sphinx.errors import SphinxError
from sphinx.testing.util import remove_unicode_literals, strip_escseq
from sphinx.testing.util import strip_escseq
from sphinx.util import docutils
from sphinx.util.osutil import cd, ensuredir
from sphinx.writers.latex import LaTeXTranslator
@@ -40,9 +39,6 @@ LATEX_WARNINGS = ENV_WARNINGS + """\
%(root)s/index.rst:\\d+: WARNING: Could not lex literal_block as "c". Highlighting skipped.
"""
if PY3:
LATEX_WARNINGS = remove_unicode_literals(LATEX_WARNINGS)
# only run latex if all needed packages are there
def kpsetest(*filenames):

View File

@@ -15,10 +15,9 @@ import re
from subprocess import Popen, PIPE
import pytest
from six import PY3
from test_build_html import ENV_WARNINGS
from sphinx.testing.util import remove_unicode_literals, strip_escseq
from sphinx.testing.util import strip_escseq
from sphinx.writers.texinfo import TexinfoTranslator
@@ -30,9 +29,6 @@ TEXINFO_WARNINGS = ENV_WARNINGS + """\
\\['application/pdf', 'image/svg\\+xml'\\] \\(svgimg.\\*\\)
"""
if PY3:
TEXINFO_WARNINGS = remove_unicode_literals(TEXINFO_WARNINGS)
@pytest.mark.sphinx('texinfo', testroot='warnings', freshenv=True)
def test_texinfo_warnings(app, status, warning):

View File

@@ -11,7 +11,6 @@
"""
import mock
import pytest
from six import PY3
import sphinx
from sphinx.config import Config, ENUM, string_classes, check_confval_types
@@ -136,19 +135,6 @@ def test_errors_warnings(logger, tempdir):
assert cfg.project == u'Jägermeister'
assert logger.called is False
# test the warning for bytestrings with non-ascii content
# bytestrings with non-ascii content are a syntax error in python3 so we
# skip the test there
if PY3:
return
(tempdir / 'conf.py').write_text(
u'# -*- coding: latin-1\nproject = "fooä"\n', encoding='latin-1')
cfg = Config.read(tempdir, {}, None)
assert logger.warning.called is False
cfg.check_unicode()
assert logger.warning.called is True
def test_errors_if_setup_is_not_callable(tempdir, make_app):
# test the error to call setup() in the config file
@@ -242,7 +228,7 @@ TYPECHECK_WARNINGS = [
('value8', B(), None, C(), False), # sibling type
('value9', None, None, 'foo', False), # no default or no annotations
('value10', None, None, 123, False), # no default or no annotations
('value11', None, [str], u'bar', False if PY3 else True), # str vs unicode
('value11', None, [str], u'bar', False), # str vs unicode
('value12', 'string', None, u'bar', False), # str vs unicode
('value13', None, string_classes, 'bar', False), # string_classes
('value14', None, string_classes, u'bar', False), # string_classes

View File

@@ -10,7 +10,6 @@
"""
import re
import sys
import pytest
@@ -82,9 +81,6 @@ def test_texinfo(app, status, warning):
@pytest.mark.sphinx('html', testroot='docutilsconf',
docutilsconf='[general]\nsource_link=true\n')
@pytest.mark.skip(sys.platform == "win32" and
not (sys.version_info.major >= 3 and sys.version_info.minor >= 2),
reason="Python < 3.2 on Win32 doesn't handle non-ASCII paths right")
def test_docutils_source_link_with_nonascii_file(app, status, warning):
srcdir = path(app.srcdir)
mb_name = u'\u65e5\u672c\u8a9e'

View File

@@ -113,7 +113,10 @@ def test_domain_py_xrefs(app, status, warning):
assert_refnode(refnodes[9], False, False, 'str', 'class')
assert_refnode(refnodes[10], False, False, 'float', 'class')
assert_refnode(refnodes[11], False, False, 'list', 'class')
assert len(refnodes) == 12
assert_refnode(refnodes[11], False, False, 'list', 'class')
assert_refnode(refnodes[12], False, False, 'ModTopLevel', 'class')
assert_refnode(refnodes[13], False, False, 'index', 'doc', domain='std')
assert len(refnodes) == 14
doctree = app.env.get_doctree('module_option')
refnodes = list(doctree.traverse(addnodes.pending_xref))

17
tests/test_errors.py Normal file
View File

@@ -0,0 +1,17 @@
import sys
from sphinx.errors import ExtensionError
def test_extension_error_repr():
exc = ExtensionError("foo")
assert repr(exc) == "ExtensionError('foo')"
def test_extension_error_with_orig_exc_repr():
exc = ExtensionError("foo", Exception("bar"))
if sys.version_info < (3, 7):
expected = "ExtensionError('foo', Exception('bar',))"
else:
expected = "ExtensionError('foo', Exception('bar'))"
assert repr(exc) == expected

View File

@@ -14,7 +14,6 @@ from collections import Counter
import pytest
from packaging.specifiers import InvalidSpecifier
from packaging.version import InvalidVersion
from six import PY2
from sphinx.ext.doctest import is_allowed_version
@@ -112,9 +111,6 @@ def record(directive, part, should_skip):
return 'Recorded {} {} {}'.format(directive, part, should_skip)
@pytest.mark.xfail(
PY2, reason='node.source points to document instead of filename',
)
@pytest.mark.sphinx('doctest', testroot='ext-doctest-with-autodoc')
def test_reporting_with_autodoc(app, status, warning, capfd):
# Patch builder to get a copy of the output

View File

@@ -12,8 +12,6 @@
import os
import sys
from six import PY2
import sphinx
from sphinx.pycode import ModuleAnalyzer
@@ -24,20 +22,14 @@ def test_ModuleAnalyzer_for_string():
analyzer = ModuleAnalyzer.for_string('print("Hello world")', 'module_name')
assert analyzer.modname == 'module_name'
assert analyzer.srcname == '<string>'
if PY2:
assert analyzer.encoding == 'ascii'
else:
assert analyzer.encoding is None
assert analyzer.encoding is None
def test_ModuleAnalyzer_for_file():
analyzer = ModuleAnalyzer.for_string(SPHINX_MODULE_PATH, 'sphinx')
assert analyzer.modname == 'sphinx'
assert analyzer.srcname == '<string>'
if PY2:
assert analyzer.encoding == 'ascii'
else:
assert analyzer.encoding is None
assert analyzer.encoding is None
def test_ModuleAnalyzer_for_module():

View File

@@ -12,7 +12,6 @@
import sys
import pytest
from six import PY2
from sphinx.pycode.parser import Parser
@@ -135,7 +134,6 @@ def test_complex_assignment():
assert parser.definitions == {}
@pytest.mark.skipif(PY2, reason='tests for py3 syntax')
def test_complex_assignment_py3():
source = ('a, *b, c = (1, 2, 3, 4) #: unpack assignment\n'
'd, *self.attr = (5, 6, 7) #: unpack assignment2\n'

View File

@@ -13,7 +13,7 @@ import sys
import time
import pytest
from six import PY2, text_type, StringIO
from six import text_type, StringIO
from six.moves import input
from sphinx import application
@@ -37,12 +37,7 @@ def mock_input(answers, needanswer=False):
raise AssertionError('answer for %r missing and no default '
'present' % prompt)
called.add(prompt)
if PY2:
prompt = str(prompt) # Python2.x raw_input emulation
# `raw_input` encode `prompt` by default encoding to print.
else:
prompt = text_type(prompt) # Python3.x input emulation
# `input` decode prompt by default encoding before print.
prompt = text_type(prompt)
for question in answers:
if prompt.startswith(qs.PROMPT_PREFIX + question):
return answers[question]

View File

@@ -13,7 +13,6 @@ import sys
from textwrap import dedent
import pytest
from six import PY3
from sphinx.util import inspect
@@ -25,15 +24,11 @@ def test_getargspec():
spec = inspect.getargspec(func)
assert spec.args == ['a', 'b', 'c', 'd']
assert spec.varargs == 'e'
if PY3:
assert spec.varkw == 'f'
assert spec.defaults == (1, 2)
assert spec.kwonlyargs == []
assert spec.kwonlydefaults is None
assert spec.annotations == {}
else:
assert spec.keywords == 'f'
assert spec.defaults == [1, 2]
assert spec.varkw == 'f'
assert spec.defaults == (1, 2)
assert spec.kwonlyargs == []
assert spec.kwonlydefaults is None
assert spec.annotations == {}
def test_getargspec_partial():
@@ -42,19 +37,13 @@ def test_getargspec_partial():
partial = functools.partial(func1, 10, c=11)
spec = inspect.getargspec(partial)
if PY3:
assert spec.args == ['b']
assert spec.varargs is None
assert spec.varkw == 'f'
assert spec.defaults is None
assert spec.kwonlyargs == ['c', 'd']
assert spec.kwonlydefaults == {'c': 11, 'd': 2}
assert spec.annotations == {}
else:
assert spec.args == ['b', 'd']
assert spec.varargs == 'e'
assert spec.keywords == 'f'
assert spec.defaults == [2]
assert spec.args == ['b']
assert spec.varargs is None
assert spec.varkw == 'f'
assert spec.defaults is None
assert spec.kwonlyargs == ['c', 'd']
assert spec.kwonlydefaults == {'c': 11, 'd': 2}
assert spec.annotations == {}
def test_getargspec_partial2():
@@ -62,19 +51,8 @@ def test_getargspec_partial2():
pass
p = functools.partial(fun, 10, c=11)
if PY3:
# Python 3's partial is rather cleverer than Python 2's, and we
# have to jump through some hoops to define an equivalent function
# in a way that won't confuse Python 2's parser:
ns = {}
exec(dedent("""
def f_expected(b, *, c=11, d=2):
pass
"""), ns)
f_expected = ns["f_expected"]
else:
def f_expected(b, d=2):
pass
def f_expected(b, *, c=11, d=2):
pass
expected = inspect.getargspec(f_expected)
assert expected == inspect.getargspec(p)
@@ -105,13 +83,8 @@ def test_getargspec_bound_methods():
pass
assert expected_unbound == inspect.getargspec(Foo.method)
if PY3 and sys.version_info >= (3, 4, 4):
# On py2, the inspect functions don't properly handle bound
# methods (they include a spurious 'self' argument)
assert expected_bound == inspect.getargspec(bound_method)
# On py2, the inspect functions can't properly handle wrapped
# functions (no __wrapped__ support)
assert expected_bound == inspect.getargspec(wrapped_bound_method)
assert expected_bound == inspect.getargspec(bound_method)
assert expected_bound == inspect.getargspec(wrapped_bound_method)
def test_Signature():
@@ -143,10 +116,7 @@ def test_Signature_partial():
p = functools.partial(fun, 10, c=11)
sig = inspect.Signature(p).format_args()
if sys.version_info < (3,):
assert sig == '(b, d=2)'
else:
assert sig == '(b, *, c=11, d=2)'
assert sig == '(b, *, c=11, d=2)'
def test_Signature_methods():
@@ -193,16 +163,9 @@ def test_Signature_methods():
# wrapped bound method
sig = inspect.Signature(wrapped_bound_method).format_args()
if sys.version_info < (3,):
assert sig == '(*args, **kwargs)'
elif sys.version_info < (3, 4, 4):
assert sig == '(self, arg1, **kwargs)'
else:
assert sig == '(arg1, **kwargs)'
assert sig == '(arg1, **kwargs)'
@pytest.mark.skipif(sys.version_info < (3, 4),
reason='functools.partialmethod is available on py34 or above')
def test_Signature_partialmethod():
from functools import partialmethod
@@ -228,11 +191,9 @@ def test_Signature_partialmethod():
assert sig == '()'
@pytest.mark.skipif(sys.version_info < (3, 4),
reason='type annotation test is available on py34 or above')
def test_Signature_annotations():
from typing_test_data import (
f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, Node)
from typing_test_data import (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10,
f11, f12, f13, f14, f15, f16, Node)
# Class annotations
sig = inspect.Signature(f0).format_args()
@@ -297,6 +258,14 @@ def test_Signature_annotations():
sig = inspect.Signature(f14).format_args()
assert sig == '() -> Any'
# keyword only arguments (1)
sig = inspect.Signature(f15).format_args()
assert sig == '(arg1, arg2, *, arg3=None, arg4=None)'
# keyword only arguments (2)
sig = inspect.Signature(f16).format_args()
assert sig == '(*, arg3, arg4)'
# type hints by string
sig = inspect.Signature(Node.children).format_args()
if (3, 5, 0) <= sys.version_info < (3, 5, 3):
@@ -376,37 +345,25 @@ def test_dictionary_sorting():
def test_set_sorting():
set_ = set("gfedcba")
description = inspect.object_description(set_)
if PY3:
assert description == "{'a', 'b', 'c', 'd', 'e', 'f', 'g'}"
else:
assert description == "set(['a', 'b', 'c', 'd', 'e', 'f', 'g'])"
assert description == "{'a', 'b', 'c', 'd', 'e', 'f', 'g'}"
def test_set_sorting_fallback():
set_ = set((None, 1))
description = inspect.object_description(set_)
if PY3:
assert description in ("{1, None}", "{None, 1}")
else:
assert description in ("set([1, None])", "set([None, 1])")
assert description in ("{1, None}", "{None, 1}")
def test_frozenset_sorting():
frozenset_ = frozenset("gfedcba")
description = inspect.object_description(frozenset_)
if PY3:
assert description == "frozenset({'a', 'b', 'c', 'd', 'e', 'f', 'g'})"
else:
assert description == "frozenset(['a', 'b', 'c', 'd', 'e', 'f', 'g'])"
assert description == "frozenset({'a', 'b', 'c', 'd', 'e', 'f', 'g'})"
def test_frozenset_sorting_fallback():
frozenset_ = frozenset((None, 1))
description = inspect.object_description(frozenset_)
if PY3:
assert description in ("frozenset({1, None})", "frozenset({None, 1})")
else:
assert description in ("frozenset([1, None])", "frozenset([None, 1])")
assert description in ("frozenset({1, None})", "frozenset({None, 1})")
def test_dict_customtype():
@@ -437,10 +394,5 @@ def test_isstaticmethod():
assert inspect.isstaticmethod(Foo.method1, Foo, 'method1') is True
assert inspect.isstaticmethod(Foo.method2, Foo, 'method2') is False
if sys.version_info < (3, 0):
assert inspect.isstaticmethod(Bar.method1, Bar, 'method1') is False
assert inspect.isstaticmethod(Bar.method2, Bar, 'method2') is False
else:
assert inspect.isstaticmethod(Bar.method1, Bar, 'method1') is True
assert inspect.isstaticmethod(Bar.method2, Bar, 'method2') is False
assert inspect.isstaticmethod(Bar.method1, Bar, 'method1') is True
assert inspect.isstaticmethod(Bar.method2, Bar, 'method2') is False

View File

@@ -76,6 +76,13 @@ def f14() -> Any:
pass
def f15(arg1, arg2, *, arg3=None, arg4=None):
pass
def f16(*, arg3, arg4):
pass
class Node:
def __init__(self, parent: Optional['Node']) -> None:
pass