|
@@ -47,3 +47,136 @@ assert not isgeneratorfunction(a.not_gen_instance)
|
|
|
assert isgeneratorfunction(a.gen_instance)
|
|
assert isgeneratorfunction(a.gen_instance)
|
|
|
assert not isgeneratorfunction(A.not_gen_instance)
|
|
assert not isgeneratorfunction(A.not_gen_instance)
|
|
|
assert isgeneratorfunction(A.gen_instance)
|
|
assert isgeneratorfunction(A.gen_instance)
|
|
|
|
|
+
|
|
|
|
|
+# ---------------- inspect.signature ----------------
|
|
|
|
|
+from inspect import signature, Parameter
|
|
|
|
|
+
|
|
|
|
|
+# simple positional-or-keyword parameters
|
|
|
|
|
+def f1(a, b):
|
|
|
|
|
+ return a + b
|
|
|
|
|
+
|
|
|
|
|
+sig = signature(f1)
|
|
|
|
|
+assert str(sig) == '(a, b)'
|
|
|
|
|
+params = sig.parameters
|
|
|
|
|
+assert list(params) == ['a', 'b']
|
|
|
|
|
+assert params['a'].name == 'a'
|
|
|
|
|
+assert params['a'].kind == Parameter.POSITIONAL_OR_KEYWORD
|
|
|
|
|
+assert params['a'].default is Parameter.empty
|
|
|
|
|
+assert params['b'].kind == Parameter.POSITIONAL_OR_KEYWORD
|
|
|
|
|
+
|
|
|
|
|
+# no parameters
|
|
|
|
|
+def f2():
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+sig = signature(f2)
|
|
|
|
|
+assert str(sig) == '()'
|
|
|
|
|
+assert len(sig.parameters) == 0
|
|
|
|
|
+
|
|
|
|
|
+# default values
|
|
|
|
|
+def f3(a, b=2, c='x'):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+sig = signature(f3)
|
|
|
|
|
+assert str(sig) == "(a, b=2, c='x')"
|
|
|
|
|
+params = sig.parameters
|
|
|
|
|
+assert params['a'].default is Parameter.empty
|
|
|
|
|
+assert params['b'].default == 2
|
|
|
|
|
+assert params['c'].default == 'x'
|
|
|
|
|
+
|
|
|
|
|
+# *args and **kwargs
|
|
|
|
|
+def f4(a, *args, **kwargs):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+sig = signature(f4)
|
|
|
|
|
+assert str(sig) == '(a, *args, **kwargs)'
|
|
|
|
|
+params = sig.parameters
|
|
|
|
|
+assert list(params) == ['a', 'args', 'kwargs']
|
|
|
|
|
+assert params['a'].kind == Parameter.POSITIONAL_OR_KEYWORD
|
|
|
|
|
+assert params['args'].kind == Parameter.VAR_POSITIONAL
|
|
|
|
|
+assert params['args'].default is Parameter.empty
|
|
|
|
|
+assert params['kwargs'].kind == Parameter.VAR_KEYWORD
|
|
|
|
|
+assert params['kwargs'].default is Parameter.empty
|
|
|
|
|
+
|
|
|
|
|
+# keyword-only parameters (defaults after *args)
|
|
|
|
|
+def f5(a, *c, b=1, **d):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+sig = signature(f5)
|
|
|
|
|
+assert str(sig) == '(a, *c, b=1, **d)'
|
|
|
|
|
+assert list(sig.parameters) == ['a', 'c', 'b', 'd']
|
|
|
|
|
+assert sig.parameters['b'].kind == Parameter.KEYWORD_ONLY
|
|
|
|
|
+assert sig.parameters['b'].default == 1
|
|
|
|
|
+
|
|
|
|
|
+# lambda
|
|
|
|
|
+sig = signature(lambda x, y=3: x + y)
|
|
|
|
|
+assert str(sig) == '(x, y=3)'
|
|
|
|
|
+assert list(sig.parameters) == ['x', 'y']
|
|
|
|
|
+assert sig.parameters['y'].default == 3
|
|
|
|
|
+
|
|
|
|
|
+# generator function
|
|
|
|
|
+sig = signature(g)
|
|
|
|
|
+assert str(sig) == '(a, b)'
|
|
|
|
|
+
|
|
|
|
|
+# methods: bound methods drop `self`, unbound functions keep it
|
|
|
|
|
+class B:
|
|
|
|
|
+ def m(self, x, y=1):
|
|
|
|
|
+ pass
|
|
|
|
|
+ @staticmethod
|
|
|
|
|
+ def sm(x, y):
|
|
|
|
|
+ pass
|
|
|
|
|
+ @classmethod
|
|
|
|
|
+ def cm(cls, x):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+b = B()
|
|
|
|
|
+assert str(signature(B.m)) == '(self, x, y=1)'
|
|
|
|
|
+assert str(signature(b.m)) == '(x, y=1)'
|
|
|
|
|
+assert list(signature(b.m).parameters) == ['x', 'y']
|
|
|
|
|
+assert str(signature(B.sm)) == '(x, y)'
|
|
|
|
|
+assert str(signature(b.sm)) == '(x, y)'
|
|
|
|
|
+assert str(signature(B.cm)) == '(x)'
|
|
|
|
|
+assert str(signature(b.cm)) == '(x)'
|
|
|
|
|
+
|
|
|
|
|
+# calling signature() on a class inspects __init__ (without `self`)
|
|
|
|
|
+class C:
|
|
|
|
|
+ def __init__(self, a, b=5):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+sig = signature(C)
|
|
|
|
|
+assert str(sig) == '(a, b=5)'
|
|
|
|
|
+assert list(sig.parameters) == ['a', 'b']
|
|
|
|
|
+
|
|
|
|
|
+# decorated function (plain wrapper)
|
|
|
|
|
+def deco(fn):
|
|
|
|
|
+ def wrapper(*args, **kwargs):
|
|
|
|
|
+ return fn(*args, **kwargs)
|
|
|
|
|
+ return wrapper
|
|
|
|
|
+
|
|
|
|
|
+@deco
|
|
|
|
|
+def f6(a, b):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+assert str(signature(f6)) == '(*args, **kwargs)'
|
|
|
|
|
+
|
|
|
|
|
+# Parameter equality / repr basics
|
|
|
|
|
+p = signature(f3).parameters['b']
|
|
|
|
|
+assert p.name == 'b'
|
|
|
|
|
+assert p.default == 2
|
|
|
|
|
+assert p.kind == Parameter.POSITIONAL_OR_KEYWORD
|
|
|
|
|
+
|
|
|
|
|
+# kinds are distinct
|
|
|
|
|
+kinds = [
|
|
|
|
|
+ Parameter.POSITIONAL_OR_KEYWORD,
|
|
|
|
|
+ Parameter.VAR_POSITIONAL,
|
|
|
|
|
+ Parameter.KEYWORD_ONLY,
|
|
|
|
|
+ Parameter.VAR_KEYWORD,
|
|
|
|
|
+]
|
|
|
|
|
+assert len(set(kinds)) == 4
|
|
|
|
|
+
|
|
|
|
|
+# non-callable raises TypeError
|
|
|
|
|
+try:
|
|
|
|
|
+ signature(42)
|
|
|
|
|
+ print('failed to raise TypeError')
|
|
|
|
|
+ exit(1)
|
|
|
|
|
+except TypeError:
|
|
|
|
|
+ pass
|