mirror of
https://github.com/python/cpython.git
synced 2025-08-04 17:08:35 +00:00
bpo-32604: PEP 554 for use in test suite (GH-19985)
* PEP 554 for use in test suite * 📜🤖 Added by blurb_it. * Fix space * Add doc to doc tree * Move to modules doc tree * Fix suspicious doc errors * Fix test__all * Docs docs docs * Support isolated and fix wait * Fix white space * Remove undefined from __all__ * Fix recv and add exceptions * Remove unused exceptions, fix pep 8 formatting errors and fix _NOT_SET in recv_nowait() Co-authored-by: nanjekyejoannah <joannah.nanjekye@ibm.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
This commit is contained in:
parent
c105f7d895
commit
9d17cbf33d
4 changed files with 865 additions and 0 deletions
183
Lib/test/support/interpreters.py
Normal file
183
Lib/test/support/interpreters.py
Normal file
|
@ -0,0 +1,183 @@
|
|||
"""Subinterpreters High Level Module."""
|
||||
|
||||
import _xxsubinterpreters as _interpreters
|
||||
|
||||
# aliases:
|
||||
from _xxsubinterpreters import (
|
||||
ChannelError, ChannelNotFoundError, ChannelEmptyError,
|
||||
is_shareable,
|
||||
)
|
||||
|
||||
|
||||
__all__ = [
|
||||
'Interpreter', 'get_current', 'get_main', 'create', 'list_all',
|
||||
'SendChannel', 'RecvChannel',
|
||||
'create_channel', 'list_all_channels', 'is_shareable',
|
||||
'ChannelError', 'ChannelNotFoundError',
|
||||
'ChannelEmptyError',
|
||||
]
|
||||
|
||||
|
||||
def create(*, isolated=True):
|
||||
"""
|
||||
Initialize a new (idle) Python interpreter.
|
||||
"""
|
||||
id = _interpreters.create(isolated=isolated)
|
||||
return Interpreter(id, isolated=isolated)
|
||||
|
||||
|
||||
def list_all():
|
||||
"""
|
||||
Get all existing interpreters.
|
||||
"""
|
||||
return [Interpreter(id) for id in
|
||||
_interpreters.list_all()]
|
||||
|
||||
|
||||
def get_current():
|
||||
"""
|
||||
Get the currently running interpreter.
|
||||
"""
|
||||
id = _interpreters.get_current()
|
||||
return Interpreter(id)
|
||||
|
||||
|
||||
def get_main():
|
||||
"""
|
||||
Get the main interpreter.
|
||||
"""
|
||||
id = _interpreters.get_main()
|
||||
return Interpreter(id)
|
||||
|
||||
|
||||
class Interpreter:
|
||||
"""
|
||||
The Interpreter object represents
|
||||
a single interpreter.
|
||||
"""
|
||||
|
||||
def __init__(self, id, *, isolated=None):
|
||||
self._id = id
|
||||
self._isolated = isolated
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def isolated(self):
|
||||
if self._isolated is None:
|
||||
self._isolated = _interpreters.is_isolated(self._id)
|
||||
return self._isolated
|
||||
|
||||
def is_running(self):
|
||||
"""
|
||||
Return whether or not the identified
|
||||
interpreter is running.
|
||||
"""
|
||||
return _interpreters.is_running(self._id)
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
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 the given source code in the interpreter.
|
||||
This blocks the current Python thread until done.
|
||||
"""
|
||||
_interpreters.run_string(self._id, src_str)
|
||||
|
||||
|
||||
def create_channel():
|
||||
"""
|
||||
Create a new channel for passing data between
|
||||
interpreters.
|
||||
"""
|
||||
|
||||
cid = _interpreters.channel_create()
|
||||
return (RecvChannel(cid), SendChannel(cid))
|
||||
|
||||
|
||||
def list_all_channels():
|
||||
"""
|
||||
Get all open channels.
|
||||
"""
|
||||
return [(RecvChannel(cid), SendChannel(cid))
|
||||
for cid in _interpreters.channel_list_all()]
|
||||
|
||||
|
||||
_NOT_SET = object()
|
||||
|
||||
|
||||
class RecvChannel:
|
||||
"""
|
||||
The RecvChannel object represents
|
||||
a recieving channel.
|
||||
"""
|
||||
|
||||
def __init__(self, id):
|
||||
self._id = id
|
||||
|
||||
def recv(self, *, _delay=10 / 1000): # 10 milliseconds
|
||||
"""
|
||||
Get the next object from the channel,
|
||||
and wait if none have been sent.
|
||||
Associate the interpreter with the channel.
|
||||
"""
|
||||
import time
|
||||
sentinel = object()
|
||||
obj = _interpreters.channel_recv(self._id, sentinel)
|
||||
while obj is sentinel:
|
||||
time.sleep(_delay)
|
||||
obj = _interpreters.channel_recv(self._id, sentinel)
|
||||
return obj
|
||||
|
||||
def recv_nowait(self, default=_NOT_SET):
|
||||
"""
|
||||
Like recv(), but return the default
|
||||
instead of waiting.
|
||||
|
||||
This function is blocked by a missing low-level
|
||||
implementation of channel_recv_wait().
|
||||
"""
|
||||
if default is _NOT_SET:
|
||||
return _interpreters.channel_recv(self._id)
|
||||
else:
|
||||
return _interpreters.channel_recv(self._id, default)
|
||||
|
||||
|
||||
class SendChannel:
|
||||
"""
|
||||
The SendChannel object represents
|
||||
a sending channel.
|
||||
"""
|
||||
|
||||
def __init__(self, id):
|
||||
self._id = id
|
||||
|
||||
def send(self, obj):
|
||||
"""
|
||||
Send the object (i.e. its data) to the receiving
|
||||
end of the channel and wait. Associate the interpreter
|
||||
with the channel.
|
||||
"""
|
||||
import time
|
||||
_interpreters.channel_send(self._id, obj)
|
||||
time.sleep(2)
|
||||
|
||||
def send_nowait(self, obj):
|
||||
"""
|
||||
Like send(), but return False if not received.
|
||||
|
||||
This function is blocked by a missing low-level
|
||||
implementation of channel_send_wait().
|
||||
"""
|
||||
|
||||
_interpreters.channel_send(self._id, obj)
|
||||
return False
|
145
Lib/test/support/interpreters.rst
Normal file
145
Lib/test/support/interpreters.rst
Normal file
|
@ -0,0 +1,145 @@
|
|||
High-level implementation of Subinterpreters
|
||||
============================================
|
||||
|
||||
**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.
|
Loading…
Add table
Add a link
Reference in a new issue