mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
refactor: Add sphinx.util.inspect.signature()
As a successor of sphinx.util.inspect.Singnature, this adds signature() function behaves like `inspect.signature()`. It is very similar to way of python's inspect module. In addition, this also adds stringify_annotation() helper to sphinx.util.inspect module. With these two functions, we can move to python's Signature object to represent function signatures perfectly. It's natural design for python developers than ever.
This commit is contained in:
parent
ae8fc43024
commit
5867416612
4
CHANGES
4
CHANGES
@ -21,9 +21,7 @@ Deprecated
|
|||||||
* ``sphinx.roles.Index``
|
* ``sphinx.roles.Index``
|
||||||
* ``sphinx.util.detect_encoding()``
|
* ``sphinx.util.detect_encoding()``
|
||||||
* ``sphinx.util.get_module_source()``
|
* ``sphinx.util.get_module_source()``
|
||||||
* ``sphinx.util.inspect.Signature.format_annotation()``
|
* ``sphinx.util.inspect.Signature``
|
||||||
* ``sphinx.util.inspect.Signature.format_annotation_new()``
|
|
||||||
* ``sphinx.util.inspect.Signature.format_annotation_old()``
|
|
||||||
|
|
||||||
Features added
|
Features added
|
||||||
--------------
|
--------------
|
||||||
|
@ -81,20 +81,11 @@ The following is a list of deprecated interfaces.
|
|||||||
- 4.0
|
- 4.0
|
||||||
- N/A
|
- N/A
|
||||||
|
|
||||||
* - ``sphinx.util.inspect.Signature.format_annotation()``
|
* - ``sphinx.util.inspect.Signature``
|
||||||
- 2.4
|
- 2.4
|
||||||
- 4.0
|
- 4.0
|
||||||
- ``sphinx.util.typing.stringify()``
|
- ``sphinx.util.inspect.signature`` and
|
||||||
|
``sphinx.util.inspect.stringify_signature()``
|
||||||
* - ``sphinx.util.inspect.Signature.format_annotation_new()``
|
|
||||||
- 2.4
|
|
||||||
- 4.0
|
|
||||||
- ``sphinx.util.typing.stringify()``
|
|
||||||
|
|
||||||
* - ``sphinx.util.inspect.Signature.format_annotation_old()``
|
|
||||||
- 2.4
|
|
||||||
- 4.0
|
|
||||||
- ``sphinx.util.typing.stringify()``
|
|
||||||
|
|
||||||
* - ``sphinx.builders.gettext.POHEADER``
|
* - ``sphinx.builders.gettext.POHEADER``
|
||||||
- 2.3
|
- 2.3
|
||||||
|
@ -33,7 +33,7 @@ from sphinx.util import logging
|
|||||||
from sphinx.util import rpartition
|
from sphinx.util import rpartition
|
||||||
from sphinx.util.docstrings import prepare_docstring
|
from sphinx.util.docstrings import prepare_docstring
|
||||||
from sphinx.util.inspect import (
|
from sphinx.util.inspect import (
|
||||||
Signature, getdoc, object_description, safe_getattr, safe_getmembers
|
getdoc, object_description, safe_getattr, safe_getmembers, stringify_signature
|
||||||
)
|
)
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@ -983,9 +983,10 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
|
|||||||
not inspect.isbuiltin(self.object) and
|
not inspect.isbuiltin(self.object) and
|
||||||
not inspect.isclass(self.object) and
|
not inspect.isclass(self.object) and
|
||||||
hasattr(self.object, '__call__')):
|
hasattr(self.object, '__call__')):
|
||||||
args = Signature(self.object.__call__).format_args(**kwargs)
|
sig = inspect.signature(self.object.__call__)
|
||||||
else:
|
else:
|
||||||
args = Signature(self.object).format_args(**kwargs)
|
sig = inspect.signature(self.object)
|
||||||
|
args = stringify_signature(sig, **kwargs)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
if (inspect.is_builtin_class_method(self.object, '__new__') and
|
if (inspect.is_builtin_class_method(self.object, '__new__') and
|
||||||
inspect.is_builtin_class_method(self.object, '__init__')):
|
inspect.is_builtin_class_method(self.object, '__init__')):
|
||||||
@ -995,11 +996,11 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
|
|||||||
# typing) we try to use the constructor signature as function
|
# typing) we try to use the constructor signature as function
|
||||||
# signature without the first argument.
|
# signature without the first argument.
|
||||||
try:
|
try:
|
||||||
sig = Signature(self.object.__new__, bound_method=True, has_retval=False)
|
sig = inspect.signature(self.object.__new__, bound_method=True)
|
||||||
args = sig.format_args(**kwargs)
|
args = stringify_signature(sig, show_return_annotation=False, **kwargs)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
sig = Signature(self.object.__init__, bound_method=True, has_retval=False)
|
sig = inspect.signature(self.object.__init__, bound_method=True)
|
||||||
args = sig.format_args(**kwargs)
|
args = stringify_signature(sig, show_return_annotation=False, **kwargs)
|
||||||
|
|
||||||
# escape backslashes for reST
|
# escape backslashes for reST
|
||||||
args = args.replace('\\', '\\\\')
|
args = args.replace('\\', '\\\\')
|
||||||
@ -1080,8 +1081,8 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
|||||||
not(inspect.ismethod(initmeth) or inspect.isfunction(initmeth)):
|
not(inspect.ismethod(initmeth) or inspect.isfunction(initmeth)):
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
sig = Signature(initmeth, bound_method=True, has_retval=False)
|
sig = inspect.signature(initmeth, bound_method=True)
|
||||||
return sig.format_args(**kwargs)
|
return stringify_signature(sig, show_return_annotation=False, **kwargs)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# still not possible: happens e.g. for old-style classes
|
# still not possible: happens e.g. for old-style classes
|
||||||
# with __init__ in C
|
# with __init__ in C
|
||||||
@ -1283,9 +1284,11 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
|
|||||||
# can never get arguments of a C function or method
|
# can never get arguments of a C function or method
|
||||||
return None
|
return None
|
||||||
if inspect.isstaticmethod(self.object, cls=self.parent, name=self.object_name):
|
if inspect.isstaticmethod(self.object, cls=self.parent, name=self.object_name):
|
||||||
args = Signature(self.object, bound_method=False).format_args(**kwargs)
|
sig = inspect.signature(self.object, bound_method=False)
|
||||||
else:
|
else:
|
||||||
args = Signature(self.object, bound_method=True).format_args(**kwargs)
|
sig = inspect.signature(self.object, bound_method=True)
|
||||||
|
args = stringify_signature(sig, **kwargs)
|
||||||
|
|
||||||
# escape backslashes for reST
|
# escape backslashes for reST
|
||||||
args = args.replace('\\', '\\\\')
|
args = args.replace('\\', '\\\\')
|
||||||
return args
|
return args
|
||||||
|
@ -315,6 +315,112 @@ def is_builtin_class_method(obj: Any, attr_name: str) -> bool:
|
|||||||
return getattr(builtins, safe_getattr(cls, '__name__', '')) is cls
|
return getattr(builtins, safe_getattr(cls, '__name__', '')) is cls
|
||||||
|
|
||||||
|
|
||||||
|
def signature(subject: Callable, bound_method: bool = False) -> inspect.Signature:
|
||||||
|
"""Return a Signature object for the given *subject*.
|
||||||
|
|
||||||
|
:param bound_method: Specify *subject* is a bound method or not
|
||||||
|
"""
|
||||||
|
# check subject is not a built-in class (ex. int, str)
|
||||||
|
if (isinstance(subject, type) and
|
||||||
|
is_builtin_class_method(subject, "__new__") and
|
||||||
|
is_builtin_class_method(subject, "__init__")):
|
||||||
|
raise TypeError("can't compute signature for built-in type {}".format(subject))
|
||||||
|
|
||||||
|
try:
|
||||||
|
signature = inspect.signature(subject)
|
||||||
|
parameters = list(signature.parameters.values())
|
||||||
|
return_annotation = signature.return_annotation
|
||||||
|
except IndexError:
|
||||||
|
# Until python 3.6.4, cpython has been crashed on inspection for
|
||||||
|
# partialmethods not having any arguments.
|
||||||
|
# https://bugs.python.org/issue33009
|
||||||
|
if hasattr(subject, '_partialmethod'):
|
||||||
|
parameters = []
|
||||||
|
return_annotation = inspect.Parameter.empty
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Update unresolved annotations using ``get_type_hints()``.
|
||||||
|
annotations = typing.get_type_hints(subject)
|
||||||
|
for i, param in enumerate(parameters):
|
||||||
|
if isinstance(param.annotation, str) and param.name in annotations:
|
||||||
|
parameters[i] = param.replace(annotation=annotations[param.name])
|
||||||
|
if 'return' in annotations:
|
||||||
|
return_annotation = annotations['return']
|
||||||
|
except Exception:
|
||||||
|
# ``get_type_hints()`` does not support some kind of objects like partial,
|
||||||
|
# ForwardRef and so on.
|
||||||
|
pass
|
||||||
|
|
||||||
|
if bound_method:
|
||||||
|
if inspect.ismethod(subject):
|
||||||
|
# ``inspect.signature()`` considers the subject is a bound method and removes
|
||||||
|
# first argument from signature. Therefore no skips are needed here.
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if len(parameters) > 0:
|
||||||
|
parameters.pop(0)
|
||||||
|
|
||||||
|
return inspect.Signature(parameters, return_annotation=return_annotation)
|
||||||
|
|
||||||
|
|
||||||
|
def stringify_signature(sig: inspect.Signature, show_annotation: bool = True,
|
||||||
|
show_return_annotation: bool = True) -> str:
|
||||||
|
"""Stringify a Signature object.
|
||||||
|
|
||||||
|
:param show_annotation: Show annotation in result
|
||||||
|
"""
|
||||||
|
args = []
|
||||||
|
last_kind = None
|
||||||
|
for param in sig.parameters.values():
|
||||||
|
# insert '*' between POSITIONAL args and KEYWORD_ONLY args::
|
||||||
|
# func(a, b, *, c, d):
|
||||||
|
if param.kind == param.KEYWORD_ONLY and last_kind in (param.POSITIONAL_OR_KEYWORD,
|
||||||
|
param.POSITIONAL_ONLY,
|
||||||
|
None):
|
||||||
|
args.append('*')
|
||||||
|
|
||||||
|
arg = StringIO()
|
||||||
|
if param.kind in (param.POSITIONAL_ONLY,
|
||||||
|
param.POSITIONAL_OR_KEYWORD,
|
||||||
|
param.KEYWORD_ONLY):
|
||||||
|
arg.write(param.name)
|
||||||
|
if show_annotation and param.annotation is not param.empty:
|
||||||
|
arg.write(': ')
|
||||||
|
arg.write(stringify_annotation(param.annotation))
|
||||||
|
if param.default is not param.empty:
|
||||||
|
if show_annotation and param.annotation is not param.empty:
|
||||||
|
arg.write(' = ')
|
||||||
|
arg.write(object_description(param.default))
|
||||||
|
else:
|
||||||
|
arg.write('=')
|
||||||
|
arg.write(object_description(param.default))
|
||||||
|
elif param.kind == param.VAR_POSITIONAL:
|
||||||
|
arg.write('*')
|
||||||
|
arg.write(param.name)
|
||||||
|
if show_annotation and param.annotation is not param.empty:
|
||||||
|
arg.write(': ')
|
||||||
|
arg.write(stringify_annotation(param.annotation))
|
||||||
|
elif param.kind == param.VAR_KEYWORD:
|
||||||
|
arg.write('**')
|
||||||
|
arg.write(param.name)
|
||||||
|
if show_annotation and param.annotation is not param.empty:
|
||||||
|
arg.write(': ')
|
||||||
|
arg.write(stringify_annotation(param.annotation))
|
||||||
|
|
||||||
|
args.append(arg.getvalue())
|
||||||
|
last_kind = param.kind
|
||||||
|
|
||||||
|
if (sig.return_annotation is inspect.Parameter.empty or
|
||||||
|
show_annotation is False or
|
||||||
|
show_return_annotation is False):
|
||||||
|
return '(%s)' % ', '.join(args)
|
||||||
|
else:
|
||||||
|
annotation = stringify_annotation(sig.return_annotation)
|
||||||
|
return '(%s) -> %s' % (', '.join(args), annotation)
|
||||||
|
|
||||||
|
|
||||||
class Parameter:
|
class Parameter:
|
||||||
"""Fake parameter class for python2."""
|
"""Fake parameter class for python2."""
|
||||||
POSITIONAL_ONLY = 0
|
POSITIONAL_ONLY = 0
|
||||||
@ -342,6 +448,9 @@ class Signature:
|
|||||||
|
|
||||||
def __init__(self, subject: Callable, bound_method: bool = False,
|
def __init__(self, subject: Callable, bound_method: bool = False,
|
||||||
has_retval: bool = True) -> None:
|
has_retval: bool = True) -> None:
|
||||||
|
warnings.warn('sphinx.util.inspect.Signature() is deprecated',
|
||||||
|
RemovedInSphinx40Warning)
|
||||||
|
|
||||||
# check subject is not a built-in class (ex. int, str)
|
# check subject is not a built-in class (ex. int, str)
|
||||||
if (isinstance(subject, type) and
|
if (isinstance(subject, type) and
|
||||||
is_builtin_class_method(subject, "__new__") and
|
is_builtin_class_method(subject, "__new__") and
|
||||||
@ -467,20 +576,14 @@ class Signature:
|
|||||||
|
|
||||||
def format_annotation(self, annotation: Any) -> str:
|
def format_annotation(self, annotation: Any) -> str:
|
||||||
"""Return formatted representation of a type annotation."""
|
"""Return formatted representation of a type annotation."""
|
||||||
warnings.warn('format_annotation() is deprecated',
|
|
||||||
RemovedInSphinx40Warning)
|
|
||||||
return stringify_annotation(annotation)
|
return stringify_annotation(annotation)
|
||||||
|
|
||||||
def format_annotation_new(self, annotation: Any) -> str:
|
def format_annotation_new(self, annotation: Any) -> str:
|
||||||
"""format_annotation() for py37+"""
|
"""format_annotation() for py37+"""
|
||||||
warnings.warn('format_annotation_new() is deprecated',
|
|
||||||
RemovedInSphinx40Warning)
|
|
||||||
return stringify_annotation(annotation)
|
return stringify_annotation(annotation)
|
||||||
|
|
||||||
def format_annotation_old(self, annotation: Any) -> str:
|
def format_annotation_old(self, annotation: Any) -> str:
|
||||||
"""format_annotation() for py36 or below"""
|
"""format_annotation() for py36 or below"""
|
||||||
warnings.warn('format_annotation_old() is deprecated',
|
|
||||||
RemovedInSphinx40Warning)
|
|
||||||
return stringify_annotation(annotation)
|
return stringify_annotation(annotation)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1318,13 +1318,13 @@ def test_partialmethod(app):
|
|||||||
' refs: https://docs.python.jp/3/library/functools.html#functools.partialmethod',
|
' refs: https://docs.python.jp/3/library/functools.html#functools.partialmethod',
|
||||||
' ',
|
' ',
|
||||||
' ',
|
' ',
|
||||||
' .. py:method:: Cell.set_alive() -> None',
|
' .. py:method:: Cell.set_alive()',
|
||||||
' :module: target.partialmethod',
|
' :module: target.partialmethod',
|
||||||
' ',
|
' ',
|
||||||
' Make a cell alive.',
|
' Make a cell alive.',
|
||||||
' ',
|
' ',
|
||||||
' ',
|
' ',
|
||||||
' .. py:method:: Cell.set_dead() -> None',
|
' .. py:method:: Cell.set_dead()',
|
||||||
' :module: target.partialmethod',
|
' :module: target.partialmethod',
|
||||||
' ',
|
' ',
|
||||||
' Make a cell dead.',
|
' Make a cell dead.',
|
||||||
@ -1336,11 +1336,6 @@ def test_partialmethod(app):
|
|||||||
' Update state of cell to *state*.',
|
' Update state of cell to *state*.',
|
||||||
' ',
|
' ',
|
||||||
]
|
]
|
||||||
if (sys.version_info < (3, 5, 4) or
|
|
||||||
(3, 6, 5) <= sys.version_info < (3, 7) or
|
|
||||||
(3, 7, 0, 'beta', 3) <= sys.version_info):
|
|
||||||
# TODO: this condition should be updated after 3.7-final release.
|
|
||||||
expected = '\n'.join(expected).replace(' -> None', '').split('\n')
|
|
||||||
|
|
||||||
options = {"members": None}
|
options = {"members": None}
|
||||||
actual = do_autodoc(app, 'class', 'target.partialmethod.Cell', options)
|
actual = do_autodoc(app, 'class', 'target.partialmethod.Cell', options)
|
||||||
|
@ -17,6 +17,7 @@ import types
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from sphinx.util import inspect
|
from sphinx.util import inspect
|
||||||
|
from sphinx.util.inspect import stringify_signature
|
||||||
|
|
||||||
|
|
||||||
def test_getargspec():
|
def test_getargspec():
|
||||||
@ -89,39 +90,39 @@ def test_getargspec_bound_methods():
|
|||||||
assert expected_bound == inspect.getargspec(wrapped_bound_method)
|
assert expected_bound == inspect.getargspec(wrapped_bound_method)
|
||||||
|
|
||||||
|
|
||||||
def test_Signature():
|
def test_signature():
|
||||||
# literals
|
# literals
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
inspect.Signature(1)
|
inspect.signature(1)
|
||||||
|
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
inspect.Signature('')
|
inspect.signature('')
|
||||||
|
|
||||||
# builitin classes
|
# builitin classes
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
inspect.Signature(int)
|
inspect.signature(int)
|
||||||
|
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
inspect.Signature(str)
|
inspect.signature(str)
|
||||||
|
|
||||||
# normal function
|
# normal function
|
||||||
def func(a, b, c=1, d=2, *e, **f):
|
def func(a, b, c=1, d=2, *e, **f):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
sig = inspect.Signature(func).format_args()
|
sig = inspect.stringify_signature(inspect.signature(func))
|
||||||
assert sig == '(a, b, c=1, d=2, *e, **f)'
|
assert sig == '(a, b, c=1, d=2, *e, **f)'
|
||||||
|
|
||||||
|
|
||||||
def test_Signature_partial():
|
def test_signature_partial():
|
||||||
def fun(a, b, c=1, d=2):
|
def fun(a, b, c=1, d=2):
|
||||||
pass
|
pass
|
||||||
p = functools.partial(fun, 10, c=11)
|
p = functools.partial(fun, 10, c=11)
|
||||||
|
|
||||||
sig = inspect.Signature(p).format_args()
|
sig = inspect.signature(p)
|
||||||
assert sig == '(b, *, c=11, d=2)'
|
assert stringify_signature(sig) == '(b, *, c=11, d=2)'
|
||||||
|
|
||||||
|
|
||||||
def test_Signature_methods():
|
def test_signature_methods():
|
||||||
class Foo:
|
class Foo:
|
||||||
def meth1(self, arg1, **kwargs):
|
def meth1(self, arg1, **kwargs):
|
||||||
pass
|
pass
|
||||||
@ -139,36 +140,36 @@ def test_Signature_methods():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# unbound method
|
# unbound method
|
||||||
sig = inspect.Signature(Foo.meth1).format_args()
|
sig = inspect.signature(Foo.meth1)
|
||||||
assert sig == '(self, arg1, **kwargs)'
|
assert stringify_signature(sig) == '(self, arg1, **kwargs)'
|
||||||
|
|
||||||
sig = inspect.Signature(Foo.meth1, bound_method=True).format_args()
|
sig = inspect.signature(Foo.meth1, bound_method=True)
|
||||||
assert sig == '(arg1, **kwargs)'
|
assert stringify_signature(sig) == '(arg1, **kwargs)'
|
||||||
|
|
||||||
# bound method
|
# bound method
|
||||||
sig = inspect.Signature(Foo().meth1).format_args()
|
sig = inspect.signature(Foo().meth1)
|
||||||
assert sig == '(arg1, **kwargs)'
|
assert stringify_signature(sig) == '(arg1, **kwargs)'
|
||||||
|
|
||||||
# class method
|
# class method
|
||||||
sig = inspect.Signature(Foo.meth2).format_args()
|
sig = inspect.signature(Foo.meth2)
|
||||||
assert sig == '(arg1, *args, **kwargs)'
|
assert stringify_signature(sig) == '(arg1, *args, **kwargs)'
|
||||||
|
|
||||||
sig = inspect.Signature(Foo().meth2).format_args()
|
sig = inspect.signature(Foo().meth2)
|
||||||
assert sig == '(arg1, *args, **kwargs)'
|
assert stringify_signature(sig) == '(arg1, *args, **kwargs)'
|
||||||
|
|
||||||
# static method
|
# static method
|
||||||
sig = inspect.Signature(Foo.meth3).format_args()
|
sig = inspect.signature(Foo.meth3)
|
||||||
assert sig == '(arg1, *args, **kwargs)'
|
assert stringify_signature(sig) == '(arg1, *args, **kwargs)'
|
||||||
|
|
||||||
sig = inspect.Signature(Foo().meth3).format_args()
|
sig = inspect.signature(Foo().meth3)
|
||||||
assert sig == '(arg1, *args, **kwargs)'
|
assert stringify_signature(sig) == '(arg1, *args, **kwargs)'
|
||||||
|
|
||||||
# wrapped bound method
|
# wrapped bound method
|
||||||
sig = inspect.Signature(wrapped_bound_method).format_args()
|
sig = inspect.signature(wrapped_bound_method)
|
||||||
assert sig == '(arg1, **kwargs)'
|
assert stringify_signature(sig) == '(arg1, **kwargs)'
|
||||||
|
|
||||||
|
|
||||||
def test_Signature_partialmethod():
|
def test_signature_partialmethod():
|
||||||
from functools import partialmethod
|
from functools import partialmethod
|
||||||
|
|
||||||
class Foo:
|
class Foo:
|
||||||
@ -183,116 +184,115 @@ def test_Signature_partialmethod():
|
|||||||
baz = partialmethod(meth2, 1, 2)
|
baz = partialmethod(meth2, 1, 2)
|
||||||
|
|
||||||
subject = Foo()
|
subject = Foo()
|
||||||
sig = inspect.Signature(subject.foo).format_args()
|
sig = inspect.signature(subject.foo)
|
||||||
assert sig == '(arg3=None, arg4=None)'
|
assert stringify_signature(sig) == '(arg3=None, arg4=None)'
|
||||||
|
|
||||||
sig = inspect.Signature(subject.bar).format_args()
|
sig = inspect.signature(subject.bar)
|
||||||
assert sig == '(arg2, *, arg3=3, arg4=None)'
|
assert stringify_signature(sig) == '(arg2, *, arg3=3, arg4=None)'
|
||||||
|
|
||||||
sig = inspect.Signature(subject.baz).format_args()
|
sig = inspect.signature(subject.baz)
|
||||||
assert sig == '()'
|
assert stringify_signature(sig) == '()'
|
||||||
|
|
||||||
|
|
||||||
def test_Signature_annotations():
|
def test_signature_annotations():
|
||||||
from typing_test_data import (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10,
|
from typing_test_data import (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10,
|
||||||
f11, f12, f13, f14, f15, f16, f17, f18, f19, Node)
|
f11, f12, f13, f14, f15, f16, f17, f18, f19, Node)
|
||||||
|
|
||||||
# Class annotations
|
# Class annotations
|
||||||
sig = inspect.Signature(f0).format_args()
|
sig = inspect.signature(f0)
|
||||||
assert sig == '(x: int, y: numbers.Integral) -> None'
|
assert stringify_signature(sig) == '(x: int, y: numbers.Integral) -> None'
|
||||||
|
|
||||||
# Generic types with concrete parameters
|
# Generic types with concrete parameters
|
||||||
sig = inspect.Signature(f1).format_args()
|
sig = inspect.signature(f1)
|
||||||
assert sig == '(x: List[int]) -> List[int]'
|
assert stringify_signature(sig) == '(x: List[int]) -> List[int]'
|
||||||
|
|
||||||
# TypeVars and generic types with TypeVars
|
# TypeVars and generic types with TypeVars
|
||||||
sig = inspect.Signature(f2).format_args()
|
sig = inspect.signature(f2)
|
||||||
assert sig == '(x: List[T], y: List[T_co], z: T) -> List[T_contra]'
|
assert stringify_signature(sig) == '(x: List[T], y: List[T_co], z: T) -> List[T_contra]'
|
||||||
|
|
||||||
# Union types
|
# Union types
|
||||||
sig = inspect.Signature(f3).format_args()
|
sig = inspect.signature(f3)
|
||||||
assert sig == '(x: Union[str, numbers.Integral]) -> None'
|
assert stringify_signature(sig) == '(x: Union[str, numbers.Integral]) -> None'
|
||||||
|
|
||||||
# Quoted annotations
|
# Quoted annotations
|
||||||
sig = inspect.Signature(f4).format_args()
|
sig = inspect.signature(f4)
|
||||||
assert sig == '(x: str, y: str) -> None'
|
assert stringify_signature(sig) == '(x: str, y: str) -> None'
|
||||||
|
|
||||||
# Keyword-only arguments
|
# Keyword-only arguments
|
||||||
sig = inspect.Signature(f5).format_args()
|
sig = inspect.signature(f5)
|
||||||
assert sig == '(x: int, *, y: str, z: str) -> None'
|
assert stringify_signature(sig) == '(x: int, *, y: str, z: str) -> None'
|
||||||
|
|
||||||
# Keyword-only arguments with varargs
|
# Keyword-only arguments with varargs
|
||||||
sig = inspect.Signature(f6).format_args()
|
sig = inspect.signature(f6)
|
||||||
assert sig == '(x: int, *args, y: str, z: str) -> None'
|
assert stringify_signature(sig) == '(x: int, *args, y: str, z: str) -> None'
|
||||||
|
|
||||||
# Space around '=' for defaults
|
# Space around '=' for defaults
|
||||||
sig = inspect.Signature(f7).format_args()
|
sig = inspect.signature(f7)
|
||||||
assert sig == '(x: int = None, y: dict = {}) -> None'
|
assert stringify_signature(sig) == '(x: int = None, y: dict = {}) -> None'
|
||||||
|
|
||||||
# Callable types
|
# Callable types
|
||||||
sig = inspect.Signature(f8).format_args()
|
sig = inspect.signature(f8)
|
||||||
assert sig == '(x: Callable[[int, str], int]) -> None'
|
assert stringify_signature(sig) == '(x: Callable[[int, str], int]) -> None'
|
||||||
|
|
||||||
sig = inspect.Signature(f9).format_args()
|
sig = inspect.signature(f9)
|
||||||
assert sig == '(x: Callable) -> None'
|
assert stringify_signature(sig) == '(x: Callable) -> None'
|
||||||
|
|
||||||
# Tuple types
|
# Tuple types
|
||||||
sig = inspect.Signature(f10).format_args()
|
sig = inspect.signature(f10)
|
||||||
assert sig == '(x: Tuple[int, str], y: Tuple[int, ...]) -> None'
|
assert stringify_signature(sig) == '(x: Tuple[int, str], y: Tuple[int, ...]) -> None'
|
||||||
|
|
||||||
# Instance annotations
|
# Instance annotations
|
||||||
sig = inspect.Signature(f11).format_args()
|
sig = inspect.signature(f11)
|
||||||
assert sig == '(x: CustomAnnotation, y: 123) -> None'
|
assert stringify_signature(sig) == '(x: CustomAnnotation, y: 123) -> None'
|
||||||
|
|
||||||
# has_retval=False
|
|
||||||
sig = inspect.Signature(f11, has_retval=False).format_args()
|
|
||||||
assert sig == '(x: CustomAnnotation, y: 123)'
|
|
||||||
|
|
||||||
# tuple with more than two items
|
# tuple with more than two items
|
||||||
sig = inspect.Signature(f12).format_args()
|
sig = inspect.signature(f12)
|
||||||
assert sig == '() -> Tuple[int, str, int]'
|
assert stringify_signature(sig) == '() -> Tuple[int, str, int]'
|
||||||
|
|
||||||
# optional
|
# optional
|
||||||
sig = inspect.Signature(f13).format_args()
|
sig = inspect.signature(f13)
|
||||||
assert sig == '() -> Optional[str]'
|
assert stringify_signature(sig) == '() -> Optional[str]'
|
||||||
|
|
||||||
# Any
|
# Any
|
||||||
sig = inspect.Signature(f14).format_args()
|
sig = inspect.signature(f14)
|
||||||
assert sig == '() -> Any'
|
assert stringify_signature(sig) == '() -> Any'
|
||||||
|
|
||||||
# ForwardRef
|
# ForwardRef
|
||||||
sig = inspect.Signature(f15).format_args()
|
sig = inspect.signature(f15)
|
||||||
assert sig == '(x: Unknown, y: int) -> Any'
|
assert stringify_signature(sig) == '(x: Unknown, y: int) -> Any'
|
||||||
|
|
||||||
# keyword only arguments (1)
|
# keyword only arguments (1)
|
||||||
sig = inspect.Signature(f16).format_args()
|
sig = inspect.signature(f16)
|
||||||
assert sig == '(arg1, arg2, *, arg3=None, arg4=None)'
|
assert stringify_signature(sig) == '(arg1, arg2, *, arg3=None, arg4=None)'
|
||||||
|
|
||||||
# keyword only arguments (2)
|
# keyword only arguments (2)
|
||||||
sig = inspect.Signature(f17).format_args()
|
sig = inspect.signature(f17)
|
||||||
assert sig == '(*, arg3, arg4)'
|
assert stringify_signature(sig) == '(*, arg3, arg4)'
|
||||||
|
|
||||||
sig = inspect.Signature(f18).format_args()
|
sig = inspect.signature(f18)
|
||||||
assert sig == '(self, arg1: Union[int, Tuple] = 10) -> List[Dict]'
|
assert stringify_signature(sig) == '(self, arg1: Union[int, Tuple] = 10) -> List[Dict]'
|
||||||
|
|
||||||
# annotations for variadic and keyword parameters
|
# annotations for variadic and keyword parameters
|
||||||
sig = inspect.Signature(f19).format_args()
|
sig = inspect.signature(f19)
|
||||||
assert sig == '(*args: int, **kwargs: str)'
|
assert stringify_signature(sig) == '(*args: int, **kwargs: str)'
|
||||||
|
|
||||||
# type hints by string
|
# type hints by string
|
||||||
sig = inspect.Signature(Node.children).format_args()
|
sig = inspect.signature(Node.children)
|
||||||
if (3, 5, 0) <= sys.version_info < (3, 5, 3):
|
if (3, 5, 0) <= sys.version_info < (3, 5, 3):
|
||||||
assert sig == '(self) -> List[Node]'
|
assert stringify_signature(sig) == '(self) -> List[Node]'
|
||||||
else:
|
else:
|
||||||
assert sig == '(self) -> List[typing_test_data.Node]'
|
assert stringify_signature(sig) == '(self) -> List[typing_test_data.Node]'
|
||||||
|
|
||||||
sig = inspect.Signature(Node.__init__).format_args()
|
sig = inspect.signature(Node.__init__)
|
||||||
assert sig == '(self, parent: Optional[Node]) -> None'
|
assert stringify_signature(sig) == '(self, parent: Optional[Node]) -> None'
|
||||||
|
|
||||||
# show_annotation is False
|
# show_annotation is False
|
||||||
sig = inspect.Signature(f7).format_args(show_annotation=False)
|
sig = inspect.signature(f7)
|
||||||
assert sig == '(x=None, y={})'
|
assert stringify_signature(sig, show_annotation=False) == '(x=None, y={})'
|
||||||
|
|
||||||
|
# show_return_annotation is False
|
||||||
|
sig = inspect.signature(f7)
|
||||||
|
assert stringify_signature(sig, show_return_annotation=False) == '(x: int = None, y: dict = {})'
|
||||||
|
|
||||||
def test_safe_getattr_with_default():
|
def test_safe_getattr_with_default():
|
||||||
class Foo:
|
class Foo:
|
||||||
|
Loading…
Reference in New Issue
Block a user