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.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