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
Damien George 2025-10-06 13:10:44 +11:00
rodzic 7d0a1f86be
commit 852f2cceff
3 zmienionych plików z 33 dodań i 4 usunięć

Wyświetl plik

@ -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")

Wyświetl plik

@ -1,3 +1,3 @@
metadata(version="0.2.0")
metadata(version="0.2.1")
module("inspect.py")

Wyświetl plik

@ -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)