[3.14] gh-132775: Expand the Capability of Interpreter.call() (gh-133484) by miss-islington · Pull Request #134933 · python/cpython · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62,987 changes: 31,514 additions & 31,473 deletions Doc/data/python3.14.abi

Large diffs are not rendered by default.

35 changes: 27 additions & 8 deletions Include/internal/pycore_crossinterp.h
20 changes: 20 additions & 0 deletions Lib/test/_code_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ def spam_with_globals_and_builtins():
print(res)


def spam_full_args(a, b, /, c, d, *args, e, f, **kwargs):
return (a, b, c, d, e, f, args, kwargs)


def spam_full_args_with_defaults(a=-1, b=-2, /, c=-3, d=-4, *args,
e=-5, f=-6, **kwargs):
return (a, b, c, d, e, f, args, kwargs)


def spam_args_attrs_and_builtins(a, b, /, c, d, *args, e, f, **kwargs):
if args.__len__() > 2:
return None
Expand All @@ -67,6 +76,10 @@ def spam_returns_arg(x):
return x


def spam_raises():
raise Exception('spam!')


def spam_with_inner_not_closure():
def eggs():
pass
Expand Down Expand Up @@ -177,8 +190,11 @@ def ham_C_closure(z):
spam_minimal,
spam_with_builtins,
spam_with_globals_and_builtins,
spam_full_args,
spam_full_args_with_defaults,
spam_args_attrs_and_builtins,
spam_returns_arg,
spam_raises,
spam_with_inner_not_closure,
spam_with_inner_closure,
spam_annotated,
Expand Down Expand Up @@ -219,8 +235,10 @@ def ham_C_closure(z):
spam,
spam_minimal,
spam_with_builtins,
spam_full_args,
spam_args_attrs_and_builtins,
spam_returns_arg,
spam_raises,
spam_annotated,
spam_with_inner_not_closure,
spam_with_inner_closure,
Expand All @@ -238,6 +256,7 @@ def ham_C_closure(z):
STATELESS_CODE = [
*STATELESS_FUNCTIONS,
script_with_globals,
spam_full_args_with_defaults,
spam_with_globals_and_builtins,
spam_full,
]
Expand All @@ -248,6 +267,7 @@ def ham_C_closure(z):
script_with_explicit_empty_return,
spam_minimal,
spam_with_builtins,
spam_raises,
spam_with_inner_not_closure,
spam_with_inner_closure,
]
Expand Down
31 changes: 15 additions & 16 deletions Lib/test/support/interpreters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,33 +226,32 @@ def exec(self, code, /):
if excinfo is not None:
raise ExecutionFailed(excinfo)

def call(self, callable, /):
"""Call the object in the interpreter with given args/kwargs.
def _call(self, callable, args, kwargs):
res, excinfo = _interpreters.call(self._id, callable, args, kwargs, restrict=True)
if excinfo is not None:
raise ExecutionFailed(excinfo)
return res

Only functions that take no arguments and have no closure
are supported.
def call(self, callable, /, *args, **kwargs):
"""Call the object in the interpreter with given args/kwargs.

The return value is discarded.
Nearly all callables, args, kwargs, and return values are
supported. All "shareable" objects are supported, as are
"stateless" functions (meaning non-closures that do not use
any globals). This method will fall back to pickle.

If the callable raises an exception then the error display
(including full traceback) is send back between the interpreters
(including full traceback) is sent back between the interpreters
and an ExecutionFailed exception is raised, much like what
happens with Interpreter.exec().
"""
# XXX Support args and kwargs.
# XXX Support arbitrary callables.
# XXX Support returning the return value (e.g. via pickle).
excinfo = _interpreters.call(self._id, callable, restrict=True)
if excinfo is not None:
raise ExecutionFailed(excinfo)
return self._call(callable, args, kwargs)

def call_in_thread(self, callable, /):
def call_in_thread(self, callable, /, *args, **kwargs):
"""Return a new thread that calls the object in the interpreter.

The return value and any raised exception are discarded.
"""
def task():
self.call(callable)
t = threading.Thread(target=task)
t = threading.Thread(target=self._call, args=(callable, args, kwargs))
t.start()
return t
48 changes: 46 additions & 2 deletions Lib/test/test_code.py
Loading