summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_inspect.py
diff options
context:
space:
mode:
authorYury Selivanov <yselivanov@sprymix.com>2014-01-31 19:48:37 (GMT)
committerYury Selivanov <yselivanov@sprymix.com>2014-01-31 19:48:37 (GMT)
commit63da7c7b0ca728a41b6269c4678392efb7f26625 (patch)
tree0e6f6d57448161a2faf9d3b00a40c57664432086 /Lib/test/test_inspect.py
parent4ded1f35532b7da37df2bba37a7ad32334349270 (diff)
downloadcpython-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.py60
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):