mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #7002 from tk0miya/refactor_Signature2
refactor: Add sphinx.util.inspect.signature()
This commit is contained in:
commit
6fa592f111
4
CHANGES
4
CHANGES
@ -21,9 +21,7 @@ Deprecated
|
||||
* ``sphinx.roles.Index``
|
||||
* ``sphinx.util.detect_encoding()``
|
||||
* ``sphinx.util.get_module_source()``
|
||||
* ``sphinx.util.inspect.Signature.format_annotation()``
|
||||
* ``sphinx.util.inspect.Signature.format_annotation_new()``
|
||||
* ``sphinx.util.inspect.Signature.format_annotation_old()``
|
||||
* ``sphinx.util.inspect.Signature``
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
@ -81,20 +81,11 @@ The following is a list of deprecated interfaces.
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.util.inspect.Signature.format_annotation()``
|
||||
* - ``sphinx.util.inspect.Signature``
|
||||
- 2.4
|
||||
- 4.0
|
||||
- ``sphinx.util.typing.stringify()``
|
||||
|
||||
* - ``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.util.inspect.signature`` and
|
||||
``sphinx.util.inspect.stringify_signature()``
|
||||
|
||||
* - ``sphinx.builders.gettext.POHEADER``
|
||||
- 2.3
|
||||
|
@ -33,7 +33,7 @@ from sphinx.util import logging
|
||||
from sphinx.util import rpartition
|
||||
from sphinx.util.docstrings import prepare_docstring
|
||||
from sphinx.util.inspect import (
|
||||
Signature, getdoc, object_description, safe_getattr, safe_getmembers
|
||||
getdoc, object_description, safe_getattr, safe_getmembers, stringify_signature
|
||||
)
|
||||
|
||||
if False:
|
||||
@ -983,9 +983,10 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
|
||||
not inspect.isbuiltin(self.object) and
|
||||
not inspect.isclass(self.object) and
|
||||
hasattr(self.object, '__call__')):
|
||||
args = Signature(self.object.__call__).format_args(**kwargs)
|
||||
sig = inspect.signature(self.object.__call__)
|
||||
else:
|
||||
args = Signature(self.object).format_args(**kwargs)
|
||||
sig = inspect.signature(self.object)
|
||||
args = stringify_signature(sig, **kwargs)
|
||||
except TypeError:
|
||||
if (inspect.is_builtin_class_method(self.object, '__new__') and
|
||||
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
|
||||
# signature without the first argument.
|
||||
try:
|
||||
sig = Signature(self.object.__new__, bound_method=True, has_retval=False)
|
||||
args = sig.format_args(**kwargs)
|
||||
sig = inspect.signature(self.object.__new__, bound_method=True)
|
||||
args = stringify_signature(sig, show_return_annotation=False, **kwargs)
|
||||
except TypeError:
|
||||
sig = Signature(self.object.__init__, bound_method=True, has_retval=False)
|
||||
args = sig.format_args(**kwargs)
|
||||
sig = inspect.signature(self.object.__init__, bound_method=True)
|
||||
args = stringify_signature(sig, show_return_annotation=False, **kwargs)
|
||||
|
||||
# escape backslashes for reST
|
||||
args = args.replace('\\', '\\\\')
|
||||
@ -1080,8 +1081,8 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
not(inspect.ismethod(initmeth) or inspect.isfunction(initmeth)):
|
||||
return None
|
||||
try:
|
||||
sig = Signature(initmeth, bound_method=True, has_retval=False)
|
||||
return sig.format_args(**kwargs)
|
||||
sig = inspect.signature(initmeth, bound_method=True)
|
||||
return stringify_signature(sig, show_return_annotation=False, **kwargs)
|
||||
except TypeError:
|
||||
# still not possible: happens e.g. for old-style classes
|
||||
# with __init__ in C
|
||||
@ -1283,9 +1284,11 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
|
||||
# can never get arguments of a C function or method
|
||||
return None
|
||||
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:
|
||||
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
|
||||
args = args.replace('\\', '\\\\')
|
||||
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
|
||||
|
||||
|
||||
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:
|
||||
"""Fake parameter class for python2."""
|
||||
POSITIONAL_ONLY = 0
|
||||
@ -342,6 +448,9 @@ class Signature:
|
||||
|
||||
def __init__(self, subject: Callable, bound_method: bool = False,
|
||||
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)
|
||||
if (isinstance(subject, type) and
|
||||
is_builtin_class_method(subject, "__new__") and
|
||||
@ -467,20 +576,14 @@ class Signature:
|
||||
|
||||
def format_annotation(self, annotation: Any) -> str:
|
||||
"""Return formatted representation of a type annotation."""
|
||||
warnings.warn('format_annotation() is deprecated',
|
||||
RemovedInSphinx40Warning)
|
||||
return stringify_annotation(annotation)
|
||||
|
||||
def format_annotation_new(self, annotation: Any) -> str:
|
||||
"""format_annotation() for py37+"""
|
||||
warnings.warn('format_annotation_new() is deprecated',
|
||||
RemovedInSphinx40Warning)
|
||||
return stringify_annotation(annotation)
|
||||
|
||||
def format_annotation_old(self, annotation: Any) -> str:
|
||||
"""format_annotation() for py36 or below"""
|
||||
warnings.warn('format_annotation_old() is deprecated',
|
||||
RemovedInSphinx40Warning)
|
||||
return stringify_annotation(annotation)
|
||||
|
||||
|
||||
|
@ -1318,13 +1318,13 @@ def test_partialmethod(app):
|
||||
' 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',
|
||||
' ',
|
||||
' Make a cell alive.',
|
||||
' ',
|
||||
' ',
|
||||
' .. py:method:: Cell.set_dead() -> None',
|
||||
' .. py:method:: Cell.set_dead()',
|
||||
' :module: target.partialmethod',
|
||||
' ',
|
||||
' Make a cell dead.',
|
||||
@ -1336,11 +1336,6 @@ def test_partialmethod(app):
|
||||
' 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}
|
||||
actual = do_autodoc(app, 'class', 'target.partialmethod.Cell', options)
|
||||
|
@ -17,6 +17,7 @@ import types
|
||||
import pytest
|
||||
|
||||
from sphinx.util import inspect
|
||||
from sphinx.util.inspect import stringify_signature
|
||||
|
||||
|
||||
def test_getargspec():
|
||||
@ -89,39 +90,39 @@ def test_getargspec_bound_methods():
|
||||
assert expected_bound == inspect.getargspec(wrapped_bound_method)
|
||||
|
||||
|
||||
def test_Signature():
|
||||
def test_signature():
|
||||
# literals
|
||||
with pytest.raises(TypeError):
|
||||
inspect.Signature(1)
|
||||
inspect.signature(1)
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
inspect.Signature('')
|
||||
inspect.signature('')
|
||||
|
||||
# builitin classes
|
||||
with pytest.raises(TypeError):
|
||||
inspect.Signature(int)
|
||||
inspect.signature(int)
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
inspect.Signature(str)
|
||||
inspect.signature(str)
|
||||
|
||||
# normal function
|
||||
def func(a, b, c=1, d=2, *e, **f):
|
||||
pass
|
||||
|
||||
sig = inspect.Signature(func).format_args()
|
||||
sig = inspect.stringify_signature(inspect.signature(func))
|
||||
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):
|
||||
pass
|
||||
p = functools.partial(fun, 10, c=11)
|
||||
|
||||
sig = inspect.Signature(p).format_args()
|
||||
assert sig == '(b, *, c=11, d=2)'
|
||||
sig = inspect.signature(p)
|
||||
assert stringify_signature(sig) == '(b, *, c=11, d=2)'
|
||||
|
||||
|
||||
def test_Signature_methods():
|
||||
def test_signature_methods():
|
||||
class Foo:
|
||||
def meth1(self, arg1, **kwargs):
|
||||
pass
|
||||
@ -139,36 +140,36 @@ def test_Signature_methods():
|
||||
pass
|
||||
|
||||
# unbound method
|
||||
sig = inspect.Signature(Foo.meth1).format_args()
|
||||
assert sig == '(self, arg1, **kwargs)'
|
||||
sig = inspect.signature(Foo.meth1)
|
||||
assert stringify_signature(sig) == '(self, arg1, **kwargs)'
|
||||
|
||||
sig = inspect.Signature(Foo.meth1, bound_method=True).format_args()
|
||||
assert sig == '(arg1, **kwargs)'
|
||||
sig = inspect.signature(Foo.meth1, bound_method=True)
|
||||
assert stringify_signature(sig) == '(arg1, **kwargs)'
|
||||
|
||||
# bound method
|
||||
sig = inspect.Signature(Foo().meth1).format_args()
|
||||
assert sig == '(arg1, **kwargs)'
|
||||
sig = inspect.signature(Foo().meth1)
|
||||
assert stringify_signature(sig) == '(arg1, **kwargs)'
|
||||
|
||||
# class method
|
||||
sig = inspect.Signature(Foo.meth2).format_args()
|
||||
assert sig == '(arg1, *args, **kwargs)'
|
||||
sig = inspect.signature(Foo.meth2)
|
||||
assert stringify_signature(sig) == '(arg1, *args, **kwargs)'
|
||||
|
||||
sig = inspect.Signature(Foo().meth2).format_args()
|
||||
assert sig == '(arg1, *args, **kwargs)'
|
||||
sig = inspect.signature(Foo().meth2)
|
||||
assert stringify_signature(sig) == '(arg1, *args, **kwargs)'
|
||||
|
||||
# static method
|
||||
sig = inspect.Signature(Foo.meth3).format_args()
|
||||
assert sig == '(arg1, *args, **kwargs)'
|
||||
sig = inspect.signature(Foo.meth3)
|
||||
assert stringify_signature(sig) == '(arg1, *args, **kwargs)'
|
||||
|
||||
sig = inspect.Signature(Foo().meth3).format_args()
|
||||
assert sig == '(arg1, *args, **kwargs)'
|
||||
sig = inspect.signature(Foo().meth3)
|
||||
assert stringify_signature(sig) == '(arg1, *args, **kwargs)'
|
||||
|
||||
# wrapped bound method
|
||||
sig = inspect.Signature(wrapped_bound_method).format_args()
|
||||
assert sig == '(arg1, **kwargs)'
|
||||
sig = inspect.signature(wrapped_bound_method)
|
||||
assert stringify_signature(sig) == '(arg1, **kwargs)'
|
||||
|
||||
|
||||
def test_Signature_partialmethod():
|
||||
def test_signature_partialmethod():
|
||||
from functools import partialmethod
|
||||
|
||||
class Foo:
|
||||
@ -183,116 +184,115 @@ def test_Signature_partialmethod():
|
||||
baz = partialmethod(meth2, 1, 2)
|
||||
|
||||
subject = Foo()
|
||||
sig = inspect.Signature(subject.foo).format_args()
|
||||
assert sig == '(arg3=None, arg4=None)'
|
||||
sig = inspect.signature(subject.foo)
|
||||
assert stringify_signature(sig) == '(arg3=None, arg4=None)'
|
||||
|
||||
sig = inspect.Signature(subject.bar).format_args()
|
||||
assert sig == '(arg2, *, arg3=3, arg4=None)'
|
||||
sig = inspect.signature(subject.bar)
|
||||
assert stringify_signature(sig) == '(arg2, *, arg3=3, arg4=None)'
|
||||
|
||||
sig = inspect.Signature(subject.baz).format_args()
|
||||
assert sig == '()'
|
||||
sig = inspect.signature(subject.baz)
|
||||
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,
|
||||
f11, f12, f13, f14, f15, f16, f17, f18, f19, Node)
|
||||
|
||||
# Class annotations
|
||||
sig = inspect.Signature(f0).format_args()
|
||||
assert sig == '(x: int, y: numbers.Integral) -> None'
|
||||
sig = inspect.signature(f0)
|
||||
assert stringify_signature(sig) == '(x: int, y: numbers.Integral) -> None'
|
||||
|
||||
# Generic types with concrete parameters
|
||||
sig = inspect.Signature(f1).format_args()
|
||||
assert sig == '(x: List[int]) -> List[int]'
|
||||
sig = inspect.signature(f1)
|
||||
assert stringify_signature(sig) == '(x: List[int]) -> List[int]'
|
||||
|
||||
# TypeVars and generic types with TypeVars
|
||||
sig = inspect.Signature(f2).format_args()
|
||||
assert sig == '(x: List[T], y: List[T_co], z: T) -> List[T_contra]'
|
||||
sig = inspect.signature(f2)
|
||||
assert stringify_signature(sig) == '(x: List[T], y: List[T_co], z: T) -> List[T_contra]'
|
||||
|
||||
# Union types
|
||||
sig = inspect.Signature(f3).format_args()
|
||||
assert sig == '(x: Union[str, numbers.Integral]) -> None'
|
||||
sig = inspect.signature(f3)
|
||||
assert stringify_signature(sig) == '(x: Union[str, numbers.Integral]) -> None'
|
||||
|
||||
# Quoted annotations
|
||||
sig = inspect.Signature(f4).format_args()
|
||||
assert sig == '(x: str, y: str) -> None'
|
||||
sig = inspect.signature(f4)
|
||||
assert stringify_signature(sig) == '(x: str, y: str) -> None'
|
||||
|
||||
# Keyword-only arguments
|
||||
sig = inspect.Signature(f5).format_args()
|
||||
assert sig == '(x: int, *, y: str, z: str) -> None'
|
||||
sig = inspect.signature(f5)
|
||||
assert stringify_signature(sig) == '(x: int, *, y: str, z: str) -> None'
|
||||
|
||||
# Keyword-only arguments with varargs
|
||||
sig = inspect.Signature(f6).format_args()
|
||||
assert sig == '(x: int, *args, y: str, z: str) -> None'
|
||||
sig = inspect.signature(f6)
|
||||
assert stringify_signature(sig) == '(x: int, *args, y: str, z: str) -> None'
|
||||
|
||||
# Space around '=' for defaults
|
||||
sig = inspect.Signature(f7).format_args()
|
||||
assert sig == '(x: int = None, y: dict = {}) -> None'
|
||||
sig = inspect.signature(f7)
|
||||
assert stringify_signature(sig) == '(x: int = None, y: dict = {}) -> None'
|
||||
|
||||
# Callable types
|
||||
sig = inspect.Signature(f8).format_args()
|
||||
assert sig == '(x: Callable[[int, str], int]) -> None'
|
||||
sig = inspect.signature(f8)
|
||||
assert stringify_signature(sig) == '(x: Callable[[int, str], int]) -> None'
|
||||
|
||||
sig = inspect.Signature(f9).format_args()
|
||||
assert sig == '(x: Callable) -> None'
|
||||
sig = inspect.signature(f9)
|
||||
assert stringify_signature(sig) == '(x: Callable) -> None'
|
||||
|
||||
# Tuple types
|
||||
sig = inspect.Signature(f10).format_args()
|
||||
assert sig == '(x: Tuple[int, str], y: Tuple[int, ...]) -> None'
|
||||
sig = inspect.signature(f10)
|
||||
assert stringify_signature(sig) == '(x: Tuple[int, str], y: Tuple[int, ...]) -> None'
|
||||
|
||||
# Instance annotations
|
||||
sig = inspect.Signature(f11).format_args()
|
||||
assert sig == '(x: CustomAnnotation, y: 123) -> None'
|
||||
|
||||
# has_retval=False
|
||||
sig = inspect.Signature(f11, has_retval=False).format_args()
|
||||
assert sig == '(x: CustomAnnotation, y: 123)'
|
||||
sig = inspect.signature(f11)
|
||||
assert stringify_signature(sig) == '(x: CustomAnnotation, y: 123) -> None'
|
||||
|
||||
# tuple with more than two items
|
||||
sig = inspect.Signature(f12).format_args()
|
||||
assert sig == '() -> Tuple[int, str, int]'
|
||||
sig = inspect.signature(f12)
|
||||
assert stringify_signature(sig) == '() -> Tuple[int, str, int]'
|
||||
|
||||
# optional
|
||||
sig = inspect.Signature(f13).format_args()
|
||||
assert sig == '() -> Optional[str]'
|
||||
sig = inspect.signature(f13)
|
||||
assert stringify_signature(sig) == '() -> Optional[str]'
|
||||
|
||||
# Any
|
||||
sig = inspect.Signature(f14).format_args()
|
||||
assert sig == '() -> Any'
|
||||
sig = inspect.signature(f14)
|
||||
assert stringify_signature(sig) == '() -> Any'
|
||||
|
||||
# ForwardRef
|
||||
sig = inspect.Signature(f15).format_args()
|
||||
assert sig == '(x: Unknown, y: int) -> Any'
|
||||
sig = inspect.signature(f15)
|
||||
assert stringify_signature(sig) == '(x: Unknown, y: int) -> Any'
|
||||
|
||||
# keyword only arguments (1)
|
||||
sig = inspect.Signature(f16).format_args()
|
||||
assert sig == '(arg1, arg2, *, arg3=None, arg4=None)'
|
||||
sig = inspect.signature(f16)
|
||||
assert stringify_signature(sig) == '(arg1, arg2, *, arg3=None, arg4=None)'
|
||||
|
||||
# keyword only arguments (2)
|
||||
sig = inspect.Signature(f17).format_args()
|
||||
assert sig == '(*, arg3, arg4)'
|
||||
sig = inspect.signature(f17)
|
||||
assert stringify_signature(sig) == '(*, arg3, arg4)'
|
||||
|
||||
sig = inspect.Signature(f18).format_args()
|
||||
assert sig == '(self, arg1: Union[int, Tuple] = 10) -> List[Dict]'
|
||||
sig = inspect.signature(f18)
|
||||
assert stringify_signature(sig) == '(self, arg1: Union[int, Tuple] = 10) -> List[Dict]'
|
||||
|
||||
# annotations for variadic and keyword parameters
|
||||
sig = inspect.Signature(f19).format_args()
|
||||
assert sig == '(*args: int, **kwargs: str)'
|
||||
sig = inspect.signature(f19)
|
||||
assert stringify_signature(sig) == '(*args: int, **kwargs: str)'
|
||||
|
||||
# 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):
|
||||
assert sig == '(self) -> List[Node]'
|
||||
assert stringify_signature(sig) == '(self) -> List[Node]'
|
||||
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()
|
||||
assert sig == '(self, parent: Optional[Node]) -> None'
|
||||
sig = inspect.signature(Node.__init__)
|
||||
assert stringify_signature(sig) == '(self, parent: Optional[Node]) -> None'
|
||||
|
||||
# show_annotation is False
|
||||
sig = inspect.Signature(f7).format_args(show_annotation=False)
|
||||
assert sig == '(x=None, y={})'
|
||||
sig = inspect.signature(f7)
|
||||
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():
|
||||
class Foo:
|
||||
|
Loading…
Reference in New Issue
Block a user