GeezerVison is showing github.com — GH-137630: Convert ``_interpreters`` to use Argument Clinic by AA-Turner · Pull Request #137631 · python/cpython
Conversation
AA-Turner
commented
Aug 11, 2025
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
cc @ericsnowcurrently @serhiy-storchaka
Changes split up into commits, one per module-level function. If this PR is too large, happy to break it up into smaller pieces. The only unconverted function is _interpreters.new_config(), which AC does't support.
The pydoc diff is below.
$ diff -u --color pydoc-interpreters-HEAD.txt pydoc-interpreters-AC.txt
--- pydoc-interpreters-HEAD.txt 2025-08-11 05:05:56.067834200 +0100
+++ pydoc-interpreters-AC.txt 2025-08-11 05:07:05.140207800 +0100
@@ -185,23 +185,18 @@
| args
FUNCTIONS
- call(...)
- call(id, callable, args=None, kwargs=None, *, restrict=False)
-
+ call(id, /, callable, args=(), kwargs={}, *, preserve_exc=False, restrict=False)
Call the provided object in the identified interpreter.
- Pass the given args and kwargs, if possible.
- capture_exception(...)
- capture_exception(exc=None) -> types.SimpleNamespace
+ Pass the given args and kwargs, if possible.
- Return a snapshot of an exception. If "exc" is None
- then the current exception, if any, is used (but not cleared).
+ capture_exception(exc_arg=None, /)
+ Return a snapshot of an exception.
+ If *exc* is None then the current exception, if any, is used (but not cleared).
The returned snapshot is the same as what _interpreters.exec() returns.
- create(...)
- create([config], *, reqrefs=False) -> ID
-
+ create(config='isolated', /, *, reqrefs=False)
Create a new interpreter and return a unique generated ID.
The caller is responsible for destroying the interpreter before exiting,
@@ -209,29 +204,26 @@
automatically by passing "reqrefs=True" and then using _incref() and
_decref() appropriately.
- "config" must be a valid interpreter config or the name of a
- predefined config ("isolated" or "legacy"). The default
- is "isolated".
-
- decref(...)
+ *config* must be a valid interpreter config or the name of a
+ predefined config ('isolated' or 'legacy'). The default
+ is 'isolated'.
- destroy(...)
- destroy(id, *, restrict=False)
+ decref(id, /, *, restrict=False)
+ destroy(id, /, *, restrict=False)
Destroy the identified interpreter.
Attempting to destroy the current interpreter raises InterpreterError.
So does an unrecognized ID.
- exec(...)
- exec(id, code, shared=None, *, restrict=False)
-
+ exec(id, /, code, shared={}, *, restrict=False)
Execute the provided code in the identified interpreter.
+
This is equivalent to running the builtin exec() under the target
interpreter, using the __dict__ of its __main__ module as both
globals and locals.
- "code" may be a string containing the text of a Python script.
+ *code* may be a string containing the text of a Python script.
Functions (and code objects) are also supported, with some restrictions.
The code/function must not take any arguments or be a closure
@@ -240,42 +232,27 @@
If a function is provided, its code object is used and all its state
is ignored, including its __globals__ dict.
- get_config(...)
- get_config(id, *, restrict=False) -> types.SimpleNamespace
-
+ get_config(id, /, *, restrict=False)
Return a representation of the config used to initialize the interpreter.
get_current()
- get_current() -> (ID, whence)
-
Return the ID of current interpreter.
get_main()
- get_main() -> (ID, whence)
-
- Return the ID of main interpreter.
+ Return the ID of main interpreter.
- incref(...)
-
- is_running(...)
- is_running(id, *, restrict=False) -> bool
+ incref(id, /, *, implieslink=False, restrict=False)
+ is_running(id, /, *, restrict=False)
Return whether or not the identified interpreter is running.
- is_shareable(...)
- is_shareable(obj) -> bool
-
- Return True if the object's data may be shared between interpreters and
- False otherwise.
-
- list_all(...)
- list_all() -> [(ID, whence)]
+ is_shareable(obj, /)
+ Return True if the object's data may be shared between interpreters and False otherwise.
+ list_all(*, require_ready=False)
Return a list containing the ID of every existing interpreter.
- new_config(...)
- new_config(name='isolated', /, **overrides) -> type.SimpleNamespace
-
+ new_config(name='isolated', /, **overrides)
Return a representation of a new PyInterpreterConfig.
The name determines the initial values of the config. Supported named
@@ -284,30 +261,23 @@
Any keyword arguments are set on the corresponding config fields,
overriding the initial values.
- run_func(...)
- run_func(id, func, shared=None, *, restrict=False)
-
+ run_func(id, /, func, shared={}, *, restrict=False)
Execute the body of the provided function in the identified interpreter.
+
Code objects are also supported. In both cases, closures and args
are not supported. Methods and other callables are not supported either.
- (See _interpreters.exec().
-
- run_string(...)
- run_string(id, script, shared=None, *, restrict=False)
+ (See _interpreters.exec().)
+ run_string(id, /, script, shared={}, *, restrict=False)
Execute the provided string in the identified interpreter.
- (See _interpreters.exec().
-
- set___main___attrs(...)
- set___main___attrs(id, ns, *, restrict=False)
+ (See _interpreters.exec().)
+ set___main___attrs(id, ns, /, *, restrict=False)
Bind the given attributes in the interpreter's __main__ module.
- whence(...)
- whence(id) -> int
-
+ whence(id, /)
Return an identifier for where the interpreter was created.
DATA
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Many keyword-or-positional parameters were made positional-only.
- Incorrect names of some parameters.
- Mark up does not work here.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
|
|
|
|
|
/*[clinic input]
|
|
|
_interpreters.create
|
|
|
config as configobj: object(py_default="'isolated'") = NULL
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't the default value None?
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per the docstring, "The default is 'isolated'.". I think showing this is more helpful than None, what do you think?
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that in long term, it would be better to rename "restricted" to "restrict" and get rid of "restrict as restricted". That syntax is used to avoid name conflicts (with C keywords and other variable) and too large diffs, but if the parameter is only used once and does not conflict with other names, it is worth to rename it.
I would prefer to backport this to 3.14, but it is too late to break ABI.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
AA-Turner reacted with thumbs up emoji
I think that in long term, it would be better to rename "restricted" to "restrict" and get rid of "restrict as restricted".
I agree. It would be good to have clarity on the status as a verb or a noun, though -- is the parameter taking an action to restrict an interpreter, or is it communicating that the interpreter is already restricted.
The 'restricted' arguments were introduced via #117490. The only effect at the C level is checking for a _PyInterpreterState_WHENCE_STDLIB whence value & failing otherwise, so I would suggest it is more correct to use 'restrict' as the argument name. This would make sense as in we restrict .call() to only operate on interpreters from the stdlib module.
Should we make the change in this PR? _interpreters is a private module, and we can't backport these AC changes anyway due to the ABI breakage (which is annoying, I had also wanted to backport).
A
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant renaming the C variable to match the parameter name.
Anyway, this is not so important. LGTM. 👍
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
AA-Turner reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Reviewers
ericsnowcurrently
Awaiting requested review from ericsnowcurrently
ericsnowcurrently is a code owner
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|