kopia lustrzana https://github.com/micropython/micropython-lib
inspect: Support closures/generators/async-funcs in inspect.signature.
This is a follow-up to b4565b41ea (PR #1043),
to support closures, async functions and generators in `inspect.signature`.
Signed-off-by: Damien George <damien@micropython.org>
pull/1049/head
rodzic
7d0a1f86be
commit
852f2cceff
|
|
@ -1,7 +1,10 @@
|
|||
import sys
|
||||
|
||||
# Generator function.
|
||||
_g = lambda: (yield)
|
||||
|
||||
# Closure type.
|
||||
_ct = type((lambda x: (lambda: x))(None))
|
||||
|
||||
def getmembers(obj, pred=None):
|
||||
res = []
|
||||
|
|
@ -111,9 +114,16 @@ def signature(f):
|
|||
elif t is type(setattr):
|
||||
# A three-parameter built-in.
|
||||
num_args = 3
|
||||
elif t is type(signature):
|
||||
elif t is type(signature) or t is type(_g) or t is _ct:
|
||||
# A bytecode function, work out the number of arguments by inspecting the bytecode data.
|
||||
fun_obj = uctypes.struct(id(f), (uctypes.ARRAY | 0, uctypes.LONG | 4))
|
||||
fun_ptr = id(f)
|
||||
num_closed_over = 0
|
||||
if t is _ct:
|
||||
# A closure, the function is the second word.
|
||||
clo_ptr = uctypes.struct(fun_ptr, (uctypes.ARRAY | 0, uctypes.LONG | 3))
|
||||
fun_ptr = clo_ptr[1]
|
||||
num_closed_over = clo_ptr[2]
|
||||
fun_obj = uctypes.struct(fun_ptr, (uctypes.ARRAY | 0, uctypes.LONG | 4))
|
||||
bytecode = uctypes.bytearray_at(fun_obj[3], 8)
|
||||
# See py/bc.h:MP_BC_PRELUDE_SIG_DECODE_INTO macro.
|
||||
i = 0
|
||||
|
|
@ -127,7 +137,7 @@ def signature(f):
|
|||
i += 1
|
||||
A |= (z & 0x4) << n
|
||||
K |= ((z & 0x08) >> 3) << n
|
||||
num_args = A + K
|
||||
num_args = A + K - num_closed_over
|
||||
else:
|
||||
raise NotImplementedError("unsupported function type")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
metadata(version="0.2.0")
|
||||
metadata(version="0.2.1")
|
||||
|
||||
module("inspect.py")
|
||||
|
|
|
|||
|
|
@ -11,6 +11,22 @@ def gen():
|
|||
yield 1
|
||||
|
||||
|
||||
def make_closure():
|
||||
a = 1
|
||||
b = 2
|
||||
def closure(x):
|
||||
return a + b + x
|
||||
return closure
|
||||
|
||||
|
||||
def make_gen_closure():
|
||||
a = 1
|
||||
b = 2
|
||||
def gen_closure(x):
|
||||
yield a + b + x
|
||||
return gen_closure
|
||||
|
||||
|
||||
class Class:
|
||||
def meth(self):
|
||||
pass
|
||||
|
|
@ -71,3 +87,6 @@ class TestInspect(unittest.TestCase):
|
|||
self.assertEqual(len(inspect.signature(lambda x, y: 0).parameters), 2)
|
||||
self.assertEqual(len(inspect.signature(lambda x, y, z: 0).parameters), 3)
|
||||
self.assertEqual(len(inspect.signature(lambda x, y, *, z: 0).parameters), 3)
|
||||
self.assertEqual(len(inspect.signature(gen).parameters), 0)
|
||||
self.assertEqual(len(inspect.signature(make_closure()).parameters), 1)
|
||||
self.assertEqual(len(inspect.signature(make_gen_closure()).parameters), 1)
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue