mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch 'master' into drop-iteritems
This commit is contained in:
@@ -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():
|
||||
|
||||
@@ -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)'
|
||||
@@ -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
|
||||
@@ -38,3 +38,10 @@ module
|
||||
:type y: tuple(str, float)
|
||||
:rtype: list
|
||||
|
||||
.. py:attribute:: attr1
|
||||
|
||||
:type: ModTopLevel
|
||||
|
||||
.. py:attribute:: attr2
|
||||
|
||||
:type: :doc:`index`
|
||||
|
||||
@@ -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`."""
|
||||
|
||||
8
tests/roots/test-ext-autodoc/target/callable.py
Normal file
8
tests/roots/test-ext-autodoc/target/callable.py
Normal file
@@ -0,0 +1,8 @@
|
||||
class Callable():
|
||||
"""A callable object that behaves like a function."""
|
||||
|
||||
def __call__(self, arg1, arg2, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
function = Callable()
|
||||
8
tests/roots/test-ext-autodoc/target/coroutine.py
Normal file
8
tests/roots/test-ext-autodoc/target/coroutine.py
Normal 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"
|
||||
19
tests/roots/test-ext-autodoc/target/enum.py
Normal file
19
tests/roots/test-ext-autodoc/target/enum.py
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
17
tests/test_errors.py
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user