Repository navigation
Implement CPython 3.14 subinterpreter APIs #8605
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
d8a4366
Add _interpreters and _interpchannels modules
youknowone 850a64f
Correct _interpreters and _interpchannels against CPython 3.14
youknowone eaa5326
Correct the stateless checks and error shapes of _interpreters agains…
youknowone a8d8a48
Correct cross-interpreter data conversion and channel argument parsing
youknowone dafe1b5
Correct interpreter ID parsing and the channel_send defaults lookup
youknowone 336cb76
Add the _interpqueues module and concurrent.interpreters._queues
youknowone 48201fb
Add the high-level concurrent.interpreters API
youknowone 89475dc
Destroy leftover subinterpreters when the main interpreter finalizes
youknowone 8cd6724
Absolutize the script path in run_file
youknowone b3e3151
Name types in error messages the way tp_name does
youknowone f563998
Gate script_code's source compilation on the compiler feature
youknowone 9e57d98
Skip test_pyinit_function_raises_exception
youknowone File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next
Next commit
Add _interpreters and _interpchannels modules
Apply the patch baseline for the low-level subinterpreter modules:
- crates/vm/src/stdlib/_interpreters.rs: create/destroy/list_all/get_main/
get_current/is_running/exec/call/run_string/run_func/set___main___attrs/
is_shareable/whence and the Interpreter*Error exceptions
- crates/vm/src/stdlib/_interpchannels.rs: channel create/destroy/send/recv/
list_all/list_interpreters/release/close and the Channel*Error exceptions
- crates/vm/src/vm/crossinterp.rs: cross-interpreter data protocol
- crates/vm/src/vm/{interpreter,mod,runtime,vm_new}.rs: interpreter registry
and lifecycle plumbing the modules need
- Lib/concurrent/interpreters/: high-level PEP 734 package
Assisted-by: Claude:claude-opus-5- Loading branch information
commit d8a4366122de7789ff4f018be653d68a30fdac9c
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| """Subinterpreters High Level Module.""" | ||
|
|
||
| # The high-level `concurrent.interpreters` API is built on `_interpreters`. | ||
| # This package is introduced incrementally; `_crossinterp` is shared with | ||
| # the low-level `_interpchannels` tests. | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| """Common code between queues and channels.""" | ||
|
|
||
|
|
||
| class ItemInterpreterDestroyed(Exception): | ||
| """Raised when trying to get an item whose interpreter was destroyed.""" | ||
|
|
||
|
|
||
| class classonly: | ||
| """A non-data descriptor that makes a value only visible on the class.""" | ||
|
|
||
| def __init__(self, value): | ||
| self.value = value | ||
| self.getter = classmethod(value).__get__ | ||
| self.name = None | ||
|
|
||
| def __set_name__(self, cls, name): | ||
| if self.name is not None: | ||
| raise TypeError('already used') | ||
| self.name = name | ||
|
|
||
| def __get__(self, obj, cls): | ||
| if obj is not None: | ||
| raise AttributeError(self.name) | ||
| return self.getter(None, cls) | ||
|
|
||
|
|
||
| class UnboundItem: | ||
| """Represents a cross-interpreter item no longer bound to an interpreter.""" | ||
|
|
||
| __slots__ = () | ||
|
|
||
| @classonly | ||
| def singleton(cls, kind, module, name='UNBOUND'): | ||
| doc = cls.__doc__ | ||
| if doc: | ||
| doc = doc.replace( | ||
| 'cross-interpreter container', kind, | ||
| ).replace( | ||
| 'cross-interpreter', kind, | ||
| ) | ||
| subclass = type( | ||
| f'Unbound{kind.capitalize()}Item', | ||
| (cls,), | ||
| { | ||
| "_MODULE": module, | ||
| "_NAME": name, | ||
| "__doc__": doc, | ||
| }, | ||
| ) | ||
| return object.__new__(subclass) | ||
|
|
||
| _MODULE = __name__ | ||
| _NAME = 'UNBOUND' | ||
|
|
||
| def __new__(cls): | ||
| raise Exception(f'use {cls._MODULE}.{cls._NAME}') | ||
|
|
||
| def __repr__(self): | ||
| return f'{self._MODULE}.{self._NAME}' | ||
|
|
||
|
|
||
| UNBOUND = object.__new__(UnboundItem) | ||
| UNBOUND_ERROR = object() | ||
| UNBOUND_REMOVE = object() | ||
|
|
||
| _UNBOUND_CONSTANT_TO_FLAG = { | ||
| UNBOUND_REMOVE: 1, | ||
| UNBOUND_ERROR: 2, | ||
| UNBOUND: 3, | ||
| } | ||
| _UNBOUND_FLAG_TO_CONSTANT = {v: k | ||
| for k, v in _UNBOUND_CONSTANT_TO_FLAG.items()} | ||
|
|
||
|
|
||
| def serialize_unbound(unbound): | ||
| op = unbound | ||
| try: | ||
| flag = _UNBOUND_CONSTANT_TO_FLAG[op] | ||
| except KeyError: | ||
| raise NotImplementedError(f'unsupported unbound replacement op {op!r}') | ||
| return flag, | ||
|
|
||
|
|
||
| def resolve_unbound(flag, exctype_destroyed): | ||
| try: | ||
| op = _UNBOUND_FLAG_TO_CONSTANT[flag] | ||
| except KeyError: | ||
| raise NotImplementedError(f'unsupported unbound replacement op {flag!r}') | ||
| if op is UNBOUND_REMOVE: | ||
| raise NotImplementedError | ||
| elif op is UNBOUND_ERROR: | ||
| raise exctype_destroyed("item's original interpreter destroyed") | ||
| elif op is UNBOUND: | ||
| return UNBOUND | ||
| else: | ||
| raise NotImplementedError(repr(op)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
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.
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.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
Repository: RustPython/RustPython
Length of output: 20485
🏁 Script executed:
Repository: RustPython/RustPython
Length of output: 50378
🏁 Script executed:
Repository: RustPython/RustPython
Length of output: 31791
🏁 Script executed:
Repository: RustPython/RustPython
Length of output: 38238
Preserve the logical view descriptor during cross-interpreter transfer.
clone_buffer()clones onlyself.buffer.desc, butinit_slice()andcast_to_1d()updateself.desc. The destination then uses the transferred descriptor, so sliced or cast memoryviews may have the exporter’s offset, length, shape, strides, or format. Copyself.descinto the cloned buffer and add sliced and cast transfer tests.🤖 Prompt for AI Agents