Skip to content

Commit a81430b

Browse files
committed
inspect: Support closures,generators,async-funcs in inspect.signature.
Signed-off-by: Damien George <damien@micropython.org>
1 parent 3eaf027 commit a81430b

File tree

3 files changed

+33
-4
lines changed

3 files changed

+33
-4
lines changed

python-stdlib/inspect/inspect.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import sys
22

3+
# Generator function.
34
_g = lambda: (yield)
45

6+
# Closure type.
7+
_ct = type((lambda x: (lambda: x))(None))
58

69
def getmembers(obj, pred=None):
710
res = []
@@ -111,9 +114,16 @@ def signature(f):
111114
elif t is type(setattr):
112115
# A three-parameter built-in.
113116
num_args = 3
114-
elif t is type(signature):
117+
elif t is type(signature) or t is type(_g) or t is _ct:
115118
# A bytecode function, work out the number of arguments by inspecting the bytecode data.
116-
fun_obj = uctypes.struct(id(f), (uctypes.ARRAY | 0, uctypes.LONG | 4))
119+
fun_ptr = id(f)
120+
num_closed_over = 0
121+
if t is _ct:
122+
# A closure, the function is the second word.
123+
clo_ptr = uctypes.struct(fun_ptr, (uctypes.ARRAY | 0, uctypes.LONG | 3))
124+
fun_ptr = clo_ptr[1]
125+
num_closed_over = clo_ptr[2]
126+
fun_obj = uctypes.struct(fun_ptr, (uctypes.ARRAY | 0, uctypes.LONG | 4))
117127
bytecode = uctypes.bytearray_at(fun_obj[3], 8)
118128
# See py/bc.h:MP_BC_PRELUDE_SIG_DECODE_INTO macro.
119129
i = 0
@@ -127,7 +137,7 @@ def signature(f):
127137
i += 1
128138
A |= (z & 0x4) << n
129139
K |= ((z & 0x08) >> 3) << n
130-
num_args = A + K
140+
num_args = A + K - num_closed_over
131141
else:
132142
raise NotImplementedError("unsupported function type")
133143

python-stdlib/inspect/manifest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
metadata(version="0.2.0")
1+
metadata(version="0.2.1")
22

33
module("inspect.py")

python-stdlib/inspect/test_inspect.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,22 @@ def gen():
1111
yield 1
1212

1313

14+
def make_closure():
15+
a = 1
16+
b = 2
17+
def closure(x):
18+
return a + b + x
19+
return closure
20+
21+
22+
def make_gen_closure():
23+
a = 1
24+
b = 2
25+
def gen_closure(x):
26+
yield a + b + x
27+
return gen_closure
28+
29+
1430
class Class:
1531
def meth(self):
1632
pass
@@ -71,3 +87,6 @@ def test_signature(self):
7187
self.assertEqual(len(inspect.signature(lambda x, y: 0).parameters), 2)
7288
self.assertEqual(len(inspect.signature(lambda x, y, z: 0).parameters), 3)
7389
self.assertEqual(len(inspect.signature(lambda x, y, *, z: 0).parameters), 3)
90+
self.assertEqual(len(inspect.signature(gen).parameters), 0)
91+
self.assertEqual(len(inspect.signature(make_closure()).parameters), 1)
92+
self.assertEqual(len(inspect.signature(make_gen_closure()).parameters), 1)

0 commit comments

Comments
 (0)