diff options
author | Yury Selivanov <yselivanov@sprymix.com> | 2014-01-31 19:48:37 (GMT) |
---|---|---|
committer | Yury Selivanov <yselivanov@sprymix.com> | 2014-01-31 19:48:37 (GMT) |
commit | 63da7c7b0ca728a41b6269c4678392efb7f26625 (patch) | |
tree | 0e6f6d57448161a2faf9d3b00a40c57664432086 /Lib/test/test_inspect.py | |
parent | 4ded1f35532b7da37df2bba37a7ad32334349270 (diff) | |
download | cpython-63da7c7b0ca728a41b6269c4678392efb7f26625.zip cpython-63da7c7b0ca728a41b6269c4678392efb7f26625.tar.gz cpython-63da7c7b0ca728a41b6269c4678392efb7f26625.tar.bz2 |
inspect.signature: Support duck-types of Python functions (Cython, for instance) #17159
Diffstat (limited to 'Lib/test/test_inspect.py')
-rw-r--r-- | Lib/test/test_inspect.py | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 477f601..e42545d 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1740,6 +1740,66 @@ class TestSignatureObject(unittest.TestCase): with self.assertRaisesRegex(TypeError, 'is not a Python builtin'): inspect.Signature.from_builtin(42) + def test_signature_from_functionlike_object(self): + def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs): + pass + + class funclike: + # Has to be callable, and have correct + # __code__, __annotations__, __defaults__, __name__, + # and __kwdefaults__ attributes + + def __init__(self, func): + self.__name__ = func.__name__ + self.__code__ = func.__code__ + self.__annotations__ = func.__annotations__ + self.__defaults__ = func.__defaults__ + self.__kwdefaults__ = func.__kwdefaults__ + self.func = func + + def __call__(self, *args, **kwargs): + return self.func(*args, **kwargs) + + sig_func = inspect.Signature.from_function(func) + + sig_funclike = inspect.Signature.from_function(funclike(func)) + self.assertEqual(sig_funclike, sig_func) + + sig_funclike = inspect.signature(funclike(func)) + self.assertEqual(sig_funclike, sig_func) + + # If object is not a duck type of function, then + # signature will try to get a signature for its '__call__' + # method + fl = funclike(func) + del fl.__defaults__ + self.assertEqual(self.signature(fl), + ((('args', ..., ..., "var_positional"), + ('kwargs', ..., ..., "var_keyword")), + ...)) + + def test_signature_functionlike_class(self): + # We only want to duck type function-like objects, + # not classes. + + def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs): + pass + + class funclike: + def __init__(self, marker): + pass + + __name__ = func.__name__ + __code__ = func.__code__ + __annotations__ = func.__annotations__ + __defaults__ = func.__defaults__ + __kwdefaults__ = func.__kwdefaults__ + + with self.assertRaisesRegex(TypeError, 'is not a Python function'): + inspect.Signature.from_function(funclike) + + self.assertEqual(str(inspect.signature(funclike)), '(marker)') + def test_signature_on_method(self): class Test: def __init__(*args): |