Skip to content

Commit 1d15480

Browse files
Support full calls in interp_call().
1 parent 24e245e commit 1d15480

File tree

5 files changed

+789
-129
lines changed

5 files changed

+789
-129
lines changed

Lib/test/_code_definitions.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ def spam_with_globals_and_builtins():
5757
print(res)
5858

5959

60+
def spam_full_args(a, b, /, c, d, *args, e, f, **kwargs):
61+
return (a, b, c, d, e, f, args, kwargs)
62+
63+
64+
def spam_full_args_with_defaults(a=-1, b=-2, /, c=-3, d=-4, *args,
65+
e=-5, f=-6, **kwargs):
66+
return (a, b, c, d, e, f, args, kwargs)
67+
68+
6069
def spam_args_attrs_and_builtins(a, b, /, c, d, *args, e, f, **kwargs):
6170
if args.__len__() > 2:
6271
return None
@@ -67,6 +76,10 @@ def spam_returns_arg(x):
6776
return x
6877

6978

79+
def spam_raises():
80+
raise Exception('spam!')
81+
82+
7083
def spam_with_inner_not_closure():
7184
def eggs():
7285
pass
@@ -177,8 +190,11 @@ def ham_C_closure(z):
177190
spam_minimal,
178191
spam_with_builtins,
179192
spam_with_globals_and_builtins,
193+
spam_full_args,
194+
spam_full_args_with_defaults,
180195
spam_args_attrs_and_builtins,
181196
spam_returns_arg,
197+
spam_raises,
182198
spam_with_inner_not_closure,
183199
spam_with_inner_closure,
184200
spam_annotated,
@@ -219,8 +235,10 @@ def ham_C_closure(z):
219235
spam,
220236
spam_minimal,
221237
spam_with_builtins,
238+
spam_full_args,
222239
spam_args_attrs_and_builtins,
223240
spam_returns_arg,
241+
spam_raises,
224242
spam_annotated,
225243
spam_with_inner_not_closure,
226244
spam_with_inner_closure,
@@ -238,6 +256,7 @@ def ham_C_closure(z):
238256
STATELESS_CODE = [
239257
*STATELESS_FUNCTIONS,
240258
script_with_globals,
259+
spam_full_args_with_defaults,
241260
spam_with_globals_and_builtins,
242261
spam_full,
243262
]
@@ -248,6 +267,7 @@ def ham_C_closure(z):
248267
script_with_explicit_empty_return,
249268
spam_minimal,
250269
spam_with_builtins,
270+
spam_raises,
251271
spam_with_inner_not_closure,
252272
spam_with_inner_closure,
253273
]

Lib/test/support/interpreters/__init__.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,13 @@ def exec(self, code, /):
226226
if excinfo is not None:
227227
raise ExecutionFailed(excinfo)
228228

229-
def call(self, callable, /):
229+
def _call(self, callable, args, kwargs):
230+
res, excinfo = _interpreters.call(self._id, callable, args, kwargs, restrict=True)
231+
if excinfo is not None:
232+
raise ExecutionFailed(excinfo)
233+
return res
234+
235+
def call(self, callable, /, *args, **kwargs):
230236
"""Call the object in the interpreter with given args/kwargs.
231237
232238
Only functions that take no arguments and have no closure
@@ -239,20 +245,13 @@ def call(self, callable, /):
239245
and an ExecutionFailed exception is raised, much like what
240246
happens with Interpreter.exec().
241247
"""
242-
# XXX Support args and kwargs.
243-
# XXX Support arbitrary callables.
244-
# XXX Support returning the return value (e.g. via pickle).
245-
excinfo = _interpreters.call(self._id, callable, restrict=True)
246-
if excinfo is not None:
247-
raise ExecutionFailed(excinfo)
248+
return self._call(callable, args, kwargs)
248249

249-
def call_in_thread(self, callable, /):
250+
def call_in_thread(self, callable, /, *args, **kwargs):
250251
"""Return a new thread that calls the object in the interpreter.
251252
252253
The return value and any raised exception are discarded.
253254
"""
254-
def task():
255-
self.call(callable)
256-
t = threading.Thread(target=task)
255+
t = threading.Thread(target=self._call, args=(callable, args, kwargs))
257256
t.start()
258257
return t

Lib/test/test_code.py

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,26 @@ def test_local_kinds(self):
701701
'checks': CO_FAST_LOCAL,
702702
'res': CO_FAST_LOCAL,
703703
},
704+
defs.spam_full_args: {
705+
'a': POSONLY,
706+
'b': POSONLY,
707+
'c': POSORKW,
708+
'd': POSORKW,
709+
'e': KWONLY,
710+
'f': KWONLY,
711+
'args': VARARGS,
712+
'kwargs': VARKWARGS,
713+
},
714+
defs.spam_full_args_with_defaults: {
715+
'a': POSONLY,
716+
'b': POSONLY,
717+
'c': POSORKW,
718+
'd': POSORKW,
719+
'e': KWONLY,
720+
'f': KWONLY,
721+
'args': VARARGS,
722+
'kwargs': VARKWARGS,
723+
},
704724
defs.spam_args_attrs_and_builtins: {
705725
'a': POSONLY,
706726
'b': POSONLY,
@@ -714,6 +734,7 @@ def test_local_kinds(self):
714734
defs.spam_returns_arg: {
715735
'x': POSORKW,
716736
},
737+
defs.spam_raises: {},
717738
defs.spam_with_inner_not_closure: {
718739
'eggs': CO_FAST_LOCAL,
719740
},
@@ -934,6 +955,20 @@ def new_var_counts(*,
934955
purelocals=5,
935956
globalvars=6,
936957
),
958+
defs.spam_full_args: new_var_counts(
959+
posonly=2,
960+
posorkw=2,
961+
kwonly=2,
962+
varargs=1,
963+
varkwargs=1,
964+
),
965+
defs.spam_full_args_with_defaults: new_var_counts(
966+
posonly=2,
967+
posorkw=2,
968+
kwonly=2,
969+
varargs=1,
970+
varkwargs=1,
971+
),
937972
defs.spam_args_attrs_and_builtins: new_var_counts(
938973
posonly=2,
939974
posorkw=2,
@@ -945,6 +980,9 @@ def new_var_counts(*,
945980
defs.spam_returns_arg: new_var_counts(
946981
posorkw=1,
947982
),
983+
defs.spam_raises: new_var_counts(
984+
globalvars=1,
985+
),
948986
defs.spam_with_inner_not_closure: new_var_counts(
949987
purelocals=1,
950988
),
@@ -1097,10 +1135,16 @@ def new_var_counts(*,
10971135
def test_stateless(self):
10981136
self.maxDiff = None
10991137

1138+
STATELESS_FUNCTIONS = [
1139+
*defs.STATELESS_FUNCTIONS,
1140+
# stateless with defaults
1141+
defs.spam_full_args_with_defaults,
1142+
]
1143+
11001144
for func in defs.STATELESS_CODE:
11011145
with self.subTest((func, '(code)')):
11021146
_testinternalcapi.verify_stateless_code(func.__code__)
1103-
for func in defs.STATELESS_FUNCTIONS:
1147+
for func in STATELESS_FUNCTIONS:
11041148
with self.subTest((func, '(func)')):
11051149
_testinternalcapi.verify_stateless_code(func)
11061150

@@ -1110,7 +1154,7 @@ def test_stateless(self):
11101154
with self.assertRaises(Exception):
11111155
_testinternalcapi.verify_stateless_code(func.__code__)
11121156

1113-
if func not in defs.STATELESS_FUNCTIONS:
1157+
if func not in STATELESS_FUNCTIONS:
11141158
with self.subTest((func, '(func)')):
11151159
with self.assertRaises(Exception):
11161160
_testinternalcapi.verify_stateless_code(func)

0 commit comments

Comments
 (0)