970_inspect.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. from inspect import isgeneratorfunction
  2. def f(a, b):
  3. return a + b
  4. assert not isgeneratorfunction(f)
  5. def g(a, b):
  6. yield a
  7. yield b
  8. assert isgeneratorfunction(g)
  9. class A:
  10. @staticmethod
  11. def non_gen(a, b):
  12. return a + b
  13. @staticmethod
  14. def gen(a, b):
  15. yield a
  16. yield b
  17. @classmethod
  18. def non_gen_class(cls, a, b):
  19. return a + b
  20. @classmethod
  21. def gen_class(cls, a, b):
  22. yield a
  23. yield b
  24. def not_gen_instance(self, a, b):
  25. return a + b
  26. def gen_instance(self, a, b):
  27. yield a
  28. yield b
  29. a = A()
  30. assert not isgeneratorfunction(a.non_gen)
  31. assert isgeneratorfunction(a.gen)
  32. assert not isgeneratorfunction(A.non_gen)
  33. assert isgeneratorfunction(A.gen)
  34. assert not isgeneratorfunction(a.non_gen_class)
  35. assert isgeneratorfunction(a.gen_class)
  36. assert not isgeneratorfunction(A.non_gen_class)
  37. assert isgeneratorfunction(A.gen_class)
  38. assert not isgeneratorfunction(a.not_gen_instance)
  39. assert isgeneratorfunction(a.gen_instance)
  40. assert not isgeneratorfunction(A.not_gen_instance)
  41. assert isgeneratorfunction(A.gen_instance)
  42. # ---------------- inspect.signature ----------------
  43. from inspect import signature, Parameter
  44. # simple positional-or-keyword parameters
  45. def f1(a, b):
  46. return a + b
  47. sig = signature(f1)
  48. assert str(sig) == '(a, b)'
  49. params = sig.parameters
  50. assert list(params) == ['a', 'b']
  51. assert params['a'].name == 'a'
  52. assert params['a'].kind == Parameter.POSITIONAL_OR_KEYWORD
  53. assert params['a'].default is Parameter.empty
  54. assert params['b'].kind == Parameter.POSITIONAL_OR_KEYWORD
  55. # no parameters
  56. def f2():
  57. pass
  58. sig = signature(f2)
  59. assert str(sig) == '()'
  60. assert len(sig.parameters) == 0
  61. # default values
  62. def f3(a, b=2, c='x'):
  63. pass
  64. sig = signature(f3)
  65. assert str(sig) == "(a, b=2, c='x')"
  66. params = sig.parameters
  67. assert params['a'].default is Parameter.empty
  68. assert params['b'].default == 2
  69. assert params['c'].default == 'x'
  70. # *args and **kwargs
  71. def f4(a, *args, **kwargs):
  72. pass
  73. sig = signature(f4)
  74. assert str(sig) == '(a, *args, **kwargs)'
  75. params = sig.parameters
  76. assert list(params) == ['a', 'args', 'kwargs']
  77. assert params['a'].kind == Parameter.POSITIONAL_OR_KEYWORD
  78. assert params['args'].kind == Parameter.VAR_POSITIONAL
  79. assert params['args'].default is Parameter.empty
  80. assert params['kwargs'].kind == Parameter.VAR_KEYWORD
  81. assert params['kwargs'].default is Parameter.empty
  82. # keyword-only parameters (defaults after *args)
  83. def f5(a, *c, b=1, **d):
  84. pass
  85. sig = signature(f5)
  86. assert str(sig) == '(a, *c, b=1, **d)'
  87. assert list(sig.parameters) == ['a', 'c', 'b', 'd']
  88. assert sig.parameters['b'].kind == Parameter.KEYWORD_ONLY
  89. assert sig.parameters['b'].default == 1
  90. # lambda
  91. sig = signature(lambda x, y=3: x + y)
  92. assert str(sig) == '(x, y=3)'
  93. assert list(sig.parameters) == ['x', 'y']
  94. assert sig.parameters['y'].default == 3
  95. # generator function
  96. sig = signature(g)
  97. assert str(sig) == '(a, b)'
  98. # methods: bound methods drop `self`, unbound functions keep it
  99. class B:
  100. def m(self, x, y=1):
  101. pass
  102. @staticmethod
  103. def sm(x, y):
  104. pass
  105. @classmethod
  106. def cm(cls, x):
  107. pass
  108. b = B()
  109. assert str(signature(B.m)) == '(self, x, y=1)'
  110. assert str(signature(b.m)) == '(x, y=1)'
  111. assert list(signature(b.m).parameters) == ['x', 'y']
  112. assert str(signature(B.sm)) == '(x, y)'
  113. assert str(signature(b.sm)) == '(x, y)'
  114. assert str(signature(B.cm)) == '(x)'
  115. assert str(signature(b.cm)) == '(x)'
  116. # calling signature() on a class inspects __init__ (without `self`)
  117. class C:
  118. def __init__(self, a, b=5):
  119. pass
  120. sig = signature(C)
  121. assert str(sig) == '(a, b=5)'
  122. assert list(sig.parameters) == ['a', 'b']
  123. # decorated function (plain wrapper)
  124. def deco(fn):
  125. def wrapper(*args, **kwargs):
  126. return fn(*args, **kwargs)
  127. return wrapper
  128. @deco
  129. def f6(a, b):
  130. pass
  131. assert str(signature(f6)) == '(*args, **kwargs)'
  132. # Parameter equality / repr basics
  133. p = signature(f3).parameters['b']
  134. assert p.name == 'b'
  135. assert p.default == 2
  136. assert p.kind == Parameter.POSITIONAL_OR_KEYWORD
  137. # kinds are distinct
  138. kinds = [
  139. Parameter.POSITIONAL_OR_KEYWORD,
  140. Parameter.VAR_POSITIONAL,
  141. Parameter.KEYWORD_ONLY,
  142. Parameter.VAR_KEYWORD,
  143. ]
  144. assert len(set(kinds)) == 4
  145. # non-callable raises TypeError
  146. try:
  147. signature(42)
  148. print('failed to raise TypeError')
  149. exit(1)
  150. except TypeError:
  151. pass