-
-
Notifications
You must be signed in to change notification settings - Fork 34.5k
bpo-32604: PEP 554 for use in test suite #19985
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
Changes from 1 commit
02086f7
b2fda3c
3667626
cb594dd
0448a8a
85fde9f
f6af61c
0decbee
3b35e1b
af90b25
90ec54b
049aa3a
9577395
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,147 @@ | ||
| :mod:`_interpreters` --- High-level Subinterpreters Module | ||
| ========================================================== | ||
|
|
||
| .. module:: _interpreters | ||
| :synopsis: High-level Subinterpreters Module. | ||
|
|
||
| **Source code:** :source:`Lib/test/support/_interpreters.py` | ||
|
|
||
| -------------- | ||
|
|
||
| This module provides high-level tools for working with sub-interpreters, | ||
| such as creating them, running code in them, or sending data between them. | ||
| It is a wrapper around the low-level `_xxsubinterpreters` module. | ||
|
|
||
| .. versionchanged:: added in 3.9 | ||
|
|
||
| Interpreter Objects | ||
| ------------------- | ||
|
|
||
| The Interpreter object represents a single interpreter. | ||
| .. class:: Interpreter(id) | ||
|
|
||
| The class implementing a subinterpreter object. | ||
|
|
||
| .. method:: is_running() | ||
|
|
||
| Return `True` if the identified interpreter is running. | ||
|
|
||
| .. method:: close() | ||
|
|
||
| Destroy the interpreter. Attempting to destroy the current | ||
| interpreter results in a `RuntimeError`. | ||
|
|
||
| .. method:: run(self, src_str, /, *, channels=None): | ||
|
|
||
| Run the given source code in the interpreter. This blocks | ||
| the current thread until done. `channels` should be in | ||
| the form : `(RecvChannel, SendChannel)`. | ||
|
|
||
| RecvChannel Objects | ||
| ------------------- | ||
|
|
||
| The RecvChannel object represents a recieving channel. | ||
|
|
||
| .. class:: RecvChannel(id) | ||
|
|
||
| This class represents the receiving end of a channel. | ||
|
|
||
| .. method:: recv() | ||
|
|
||
| Get the next object from the channel, and wait if | ||
| none have been sent. Associate the interpreter | ||
| with the channel. | ||
|
|
||
| .. method:: recv_nowait(default=None) | ||
|
|
||
| Like ``recv()``, but return the default result | ||
| instead of waiting. | ||
|
|
||
|
|
||
| SendChannel Objects | ||
| -------------------- | ||
|
|
||
| The ``SendChannel`` object represents a sending channel. | ||
|
|
||
| .. class:: SendChannel(id) | ||
|
|
||
| This class represents the sending end of a channel. | ||
|
|
||
| .. method:: send(obj) | ||
|
|
||
| Send the object ``obj`` to the receiving end of the channel | ||
| and wait. Associate the interpreter with the channel. | ||
|
|
||
| .. method:: send_nowait(obj) | ||
|
|
||
| Similar to ``send()``, but returns ``False`` if | ||
| *obj* is not immediately received instead of blocking. | ||
|
|
||
|
|
||
| This module defines the following global functions: | ||
|
|
||
|
|
||
| .. function:: is_shareable(obj) | ||
|
|
||
| Return ``True`` if the object's data can be shared between | ||
| interpreters. | ||
|
|
||
| .. function:: create_channel() | ||
|
|
||
| Create a new channel for passing data between interpreters. | ||
|
|
||
| .. function:: list_all_channels() | ||
|
|
||
| Return all open channels. | ||
|
|
||
| .. function:: create(*, isolated=True) | ||
|
|
||
| Initialize a new (idle) Python interpreter. Get the currently | ||
| running interpreter. This method returns an ``Interpreter`` object. | ||
|
|
||
| .. function:: get_current() | ||
|
|
||
| Get the currently running interpreter. This method returns | ||
| an ``Interpreter`` object. | ||
|
|
||
| .. function:: get_main() | ||
|
|
||
| Get the main interpreter. This method returns | ||
| an ``Interpreter`` object. | ||
|
|
||
| .. function:: list_all() | ||
|
|
||
| Get all existing interpreters. Returns a list | ||
| of ``Interpreter`` objects. | ||
|
|
||
| This module also defines the following exceptions. | ||
|
|
||
| .. exception:: RunFailedError | ||
|
|
||
| This exception, a subclass of :exc:`RuntimeError`, is raised when the | ||
| ``Interpreter.run()`` results in an uncaught exception. | ||
|
|
||
| .. exception:: ChannelError | ||
|
|
||
| This exception is a subclass of :exc:`Exception`, and is the base | ||
| class for all channel-related exceptions. | ||
|
|
||
| .. exception:: ChannelNotFoundError | ||
|
|
||
| This exception is a subclass of :exc:`ChannelError`, and is raised | ||
| when the the identified channel is not found. | ||
|
|
||
| .. exception:: ChannelEmptyError | ||
|
|
||
| This exception is a subclass of :exc:`ChannelError`, and is raised when | ||
| the channel is unexpectedly empty. | ||
|
|
||
| .. exception:: ChannelNotEmptyError | ||
|
|
||
| This exception is a subclass of :exc:`ChannelError`, and is raised when | ||
| the channel is unexpectedly not empty. | ||
|
|
||
| .. exception:: NotReceivedError | ||
|
|
||
| This exception is a subclass of :exc:`ChannelError`, and is raised when | ||
| nothing was waiting to receive a sent object. | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,235 @@ | ||||||||||||||||||||||
| """Subinterpreters High Level Module.""" | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| import logging | ||||||||||||||||||||||
| import _xxsubinterpreters as _interpreters | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| __all__ = ['Interpreter', 'SendChannel', 'RecvChannel', | ||||||||||||||||||||||
| 'is_shareable', 'create_channel', | ||||||||||||||||||||||
| 'list_all_channels', 'get_current', | ||||||||||||||||||||||
| 'get_current', 'create'] | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def create(*, isolated=True): | ||||||||||||||||||||||
| """ create() -> Interpreter | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
| Initialize a new (idle) Python interpreter. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| id = _interpreters.create() | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
| return Interpreter(id) | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def list_all(): | ||||||||||||||||||||||
| """ list_all() -> [Interpreter] | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Get all existing interpreters. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| return [Interpreter(id) for id in | ||||||||||||||||||||||
| _interpreters.list_all()] | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def get_current(): | ||||||||||||||||||||||
| """ get_current() -> Interpreter | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Get the currently running interpreter. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| id = _interpreters.get_current() | ||||||||||||||||||||||
| return Interpreter(id) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def get_main(): | ||||||||||||||||||||||
| """ get_main() -> Interpreter | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Get the main interpreter. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| id = _interpreters.get_main() | ||||||||||||||||||||||
| return Interpreter(id) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class Interpreter: | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def __init__(self, id): | ||||||||||||||||||||||
| self._id = id | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| @property | ||||||||||||||||||||||
| def id(self): | ||||||||||||||||||||||
| return self._id | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
| def is_running(self): | ||||||||||||||||||||||
| """is_running() -> bool | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Return whether or not the identified | ||||||||||||||||||||||
| interpreter is running. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| return _interpreters.is_running(self._id) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def close(self): | ||||||||||||||||||||||
| """close() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Finalize and destroy the interpreter. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Attempting to destroy the current | ||||||||||||||||||||||
| interpreter results in a RuntimeError. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| return _interpreters.destroy(self._id) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def run(self, src_str, /, *, channels=None): | ||||||||||||||||||||||
| """run(src_str, /, *, channels=None) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Run the given source code in the interpreter. | ||||||||||||||||||||||
| This blocks the current thread until done. | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| try: | ||||||||||||||||||||||
| _interpreters.run_string(self._id, src_str) | ||||||||||||||||||||||
| except RunFailedError as err: | ||||||||||||||||||||||
| logger.error(err) | ||||||||||||||||||||||
| raise | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def is_shareable(obj): | ||||||||||||||||||||||
| """ is_shareable(obj) -> Bool | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Return `True` if the object's data can be | ||||||||||||||||||||||
| shared between interpreters and `False` otherwise. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| return _interpreters.is_shareable(obj) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def create_channel(): | ||||||||||||||||||||||
| """ create_channel() -> (RecvChannel, SendChannel) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Create a new channel for passing data between | ||||||||||||||||||||||
| interpreters. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| cid = _interpreters.channel_create() | ||||||||||||||||||||||
| return (RecvChannel(cid), SendChannel(cid)) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def list_all_channels(): | ||||||||||||||||||||||
| """ list_all_channels() -> [(RecvChannel, SendChannel)] | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Get all open channels. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| return [(RecvChannel(cid), SendChannel(cid)) | ||||||||||||||||||||||
| for cid in _interpreters.channel_list_all()] | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def wait(timeout): | ||||||||||||||||||||||
| #The implementation for wait | ||||||||||||||||||||||
| # will be non trivial to be useful | ||||||||||||||||||||||
| import time | ||||||||||||||||||||||
| time.sleep(timeout) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
| class RecvChannel: | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def __init__(self, id): | ||||||||||||||||||||||
| self.id = id | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The ID should be read-only.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Making this readonly makes it hard to return RecvCnannel in methods like |
||||||||||||||||||||||
| def recv(self): | ||||||||||||||||||||||
| """ channel_recv() -> obj | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Get the next object from the channel, | ||||||||||||||||||||||
| and wait if none have been sent. | ||||||||||||||||||||||
| Associate the interpreter with the channel. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| try: | ||||||||||||||||||||||
| obj = _interpreters.channel_recv(self.id) | ||||||||||||||||||||||
| if obj == None: | ||||||||||||||||||||||
| wait(2) | ||||||||||||||||||||||
| obj = _interpreters.channel_recv(self.id) | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
| except _interpreters.ChannelEmptyError: | ||||||||||||||||||||||
| raise ChannelEmptyError | ||||||||||||||||||||||
| except _interpreters.ChannelNotFoundError: | ||||||||||||||||||||||
| raise ChannelNotFoundError | ||||||||||||||||||||||
| except _interpreters.ChannelClosedError: | ||||||||||||||||||||||
| raise ChannelClosedError | ||||||||||||||||||||||
| except _interpreters.RunFailedError: | ||||||||||||||||||||||
| raise RunFailedError | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
| return obj | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def recv_nowait(self, default=None): | ||||||||||||||||||||||
| """recv_nowait(default=None) -> object | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Like recv(), but return the default | ||||||||||||||||||||||
| instead of waiting. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| try: | ||||||||||||||||||||||
| obj = _interpreters.channel_recv(self.id) | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
| except _interpreters.ChannelEmptyError: | ||||||||||||||||||||||
| raise ChannelEmptyError | ||||||||||||||||||||||
| except _interpreters.ChannelNotFoundError: | ||||||||||||||||||||||
| raise ChannelNotFoundError | ||||||||||||||||||||||
| except _interpreters.ChannelClosedError: | ||||||||||||||||||||||
| raise ChannelClosedError | ||||||||||||||||||||||
| except _interpreters.RunFailedError: | ||||||||||||||||||||||
| raise RunFailedError | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
| return obj | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class SendChannel: | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def __init__(self, id): | ||||||||||||||||||||||
| self.id = id | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The ID should be read-only.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment as above. Making this readonly makes it hard to return SendChannel in methods like
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They're only read-only to users. Regardless, I'm not clear on why we would change the value ever, even in create_channel(). |
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def send(self, obj): | ||||||||||||||||||||||
| """ send(obj) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Send the object (i.e. its data) to the receiving | ||||||||||||||||||||||
| end of the channel and wait. Associate the interpreter | ||||||||||||||||||||||
| with the channel. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| try: | ||||||||||||||||||||||
| _interpreters.channel_send(self.id, obj) | ||||||||||||||||||||||
| wait(2) | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
| except _interpreters.ChannelNotFoundError: | ||||||||||||||||||||||
| raise ChannelNotFoundError | ||||||||||||||||||||||
| except _interpreters.ChannelClosedError: | ||||||||||||||||||||||
| raise ChannelClosedError | ||||||||||||||||||||||
| except _interpreters.RunFailedError: | ||||||||||||||||||||||
| raise RunFailedError | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def send_nowait(self, obj): | ||||||||||||||||||||||
| """ send_nowait(obj) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Like send(), but return False if not received. | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| try: | ||||||||||||||||||||||
| _interpreters.channel_send(self.id, obj) | ||||||||||||||||||||||
| except _interpreters.ChannelNotFoundError: | ||||||||||||||||||||||
| raise ChannelNotFoundError | ||||||||||||||||||||||
| except _interpreters.ChannelClosedError: | ||||||||||||||||||||||
| raise ChannelClosedError | ||||||||||||||||||||||
| except _interpreters.RunFailedError: | ||||||||||||||||||||||
| raise RunFailedError | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| recv_obj = _interpreters.channel_recv(self.id) | ||||||||||||||||||||||
| if recv_obj: | ||||||||||||||||||||||
| return obj | ||||||||||||||||||||||
| else: | ||||||||||||||||||||||
| return False | ||||||||||||||||||||||
|
nanjekyejoannah marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class ChannelError(Exception): | ||||||||||||||||||||||
| pass | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class ChannelNotFoundError(ChannelError): | ||||||||||||||||||||||
| pass | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class ChannelEmptyError(ChannelError): | ||||||||||||||||||||||
| pass | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class ChannelNotEmptyError(ChannelError): | ||||||||||||||||||||||
| pass | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class NotReceivedError(ChannelError): | ||||||||||||||||||||||
| pass | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class ChannelClosedError(ChannelError): | ||||||||||||||||||||||
| pass | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class ChannelReleasedError(ChannelClosedError): | ||||||||||||||||||||||
| pass | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| class RunFailedError(RuntimeError): | ||||||||||||||||||||||
| pass | ||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.