Skip to content

Commit 2789986

Browse files
nanjekyejoannahnanjekyejoannahblurb-it[bot]
authored andcommitted
bpo-32604: PEP 554 for use in test suite (pythonGH-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>
1 parent b24beae commit 2789986

File tree

4 files changed

+865
-0
lines changed

4 files changed

+865
-0
lines changed

β€ŽLib/test/support/interpreters.py

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
"""Subinterpreters High Level Module."""
2+
3+
import _xxsubinterpreters as _interpreters
4+
5+
# aliases:
6+
from _xxsubinterpreters import (
7+
ChannelError, ChannelNotFoundError, ChannelEmptyError,
8+
is_shareable,
9+
)
10+
11+
12+
__all__ = [
13+
'Interpreter', 'get_current', 'get_main', 'create', 'list_all',
14+
'SendChannel', 'RecvChannel',
15+
'create_channel', 'list_all_channels', 'is_shareable',
16+
'ChannelError', 'ChannelNotFoundError',
17+
'ChannelEmptyError',
18+
]
19+
20+
21+
def create(*, isolated=True):
22+
"""
23+
Initialize a new (idle) Python interpreter.
24+
"""
25+
id = _interpreters.create(isolated=isolated)
26+
return Interpreter(id, isolated=isolated)
27+
28+
29+
def list_all():
30+
"""
31+
Get all existing interpreters.
32+
"""
33+
return [Interpreter(id) for id in
34+
_interpreters.list_all()]
35+
36+
37+
def get_current():
38+
"""
39+
Get the currently running interpreter.
40+
"""
41+
id = _interpreters.get_current()
42+
return Interpreter(id)
43+
44+
45+
def get_main():
46+
"""
47+
Get the main interpreter.
48+
"""
49+
id = _interpreters.get_main()
50+
return Interpreter(id)
51+
52+
53+
class Interpreter:
54+
"""
55+
The Interpreter object represents
56+
a single interpreter.
57+
"""
58+
59+
def __init__(self, id, *, isolated=None):
60+
self._id = id
61+
self._isolated = isolated
62+
63+
@property
64+
def id(self):
65+
return self._id
66+
67+
@property
68+
def isolated(self):
69+
if self._isolated is None:
70+
self._isolated = _interpreters.is_isolated(self._id)
71+
return self._isolated
72+
73+
def is_running(self):
74+
"""
75+
Return whether or not the identified
76+
interpreter is running.
77+
"""
78+
return _interpreters.is_running(self._id)
79+
80+
def close(self):
81+
"""
82+
Finalize and destroy the interpreter.
83+
84+
Attempting to destroy the current
85+
interpreter results in a RuntimeError.
86+
"""
87+
return _interpreters.destroy(self._id)
88+
89+
def run(self, src_str, /, *, channels=None):
90+
"""
91+
Run the given source code in the interpreter.
92+
This blocks the current Python thread until done.
93+
"""
94+
_interpreters.run_string(self._id, src_str)
95+
96+
97+
def create_channel():
98+
"""
99+
Create a new channel for passing data between
100+
interpreters.
101+
"""
102+
103+
cid = _interpreters.channel_create()
104+
return (RecvChannel(cid), SendChannel(cid))
105+
106+
107+
def list_all_channels():
108+
"""
109+
Get all open channels.
110+
"""
111+
return [(RecvChannel(cid), SendChannel(cid))
112+
for cid in _interpreters.channel_list_all()]
113+
114+
115+
_NOT_SET = object()
116+
117+
118+
class RecvChannel:
119+
"""
120+
The RecvChannel object represents
121+
a recieving channel.
122+
"""
123+
124+
def __init__(self, id):
125+
self._id = id
126+
127+
def recv(self, *, _delay=10 / 1000): # 10 milliseconds
128+
"""
129+
Get the next object from the channel,
130+
and wait if none have been sent.
131+
Associate the interpreter with the channel.
132+
"""
133+
import time
134+
sentinel = object()
135+
obj = _interpreters.channel_recv(self._id, sentinel)
136+
while obj is sentinel:
137+
time.sleep(_delay)
138+
obj = _interpreters.channel_recv(self._id, sentinel)
139+
return obj
140+
141+
def recv_nowait(self, default=_NOT_SET):
142+
"""
143+
Like recv(), but return the default
144+
instead of waiting.
145+
146+
This function is blocked by a missing low-level
147+
implementation of channel_recv_wait().
148+
"""
149+
if default is _NOT_SET:
150+
return _interpreters.channel_recv(self._id)
151+
else:
152+
return _interpreters.channel_recv(self._id, default)
153+
154+
155+
class SendChannel:
156+
"""
157+
The SendChannel object represents
158+
a sending channel.
159+
"""
160+
161+
def __init__(self, id):
162+
self._id = id
163+
164+
def send(self, obj):
165+
"""
166+
Send the object (i.e. its data) to the receiving
167+
end of the channel and wait. Associate the interpreter
168+
with the channel.
169+
"""
170+
import time
171+
_interpreters.channel_send(self._id, obj)
172+
time.sleep(2)
173+
174+
def send_nowait(self, obj):
175+
"""
176+
Like send(), but return False if not received.
177+
178+
This function is blocked by a missing low-level
179+
implementation of channel_send_wait().
180+
"""
181+
182+
_interpreters.channel_send(self._id, obj)
183+
return False

β€ŽLib/test/support/interpreters.rst

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
High-level implementation of Subinterpreters
2+
============================================
3+
4+
**Source code:** :source:`Lib/test/support/_interpreters.py`
5+
6+
--------------
7+
8+
This module provides high-level tools for working with sub-interpreters,
9+
such as creating them, running code in them, or sending data between them.
10+
It is a wrapper around the low-level ``__xxsubinterpreters`` module.
11+
12+
.. versionchanged:: added in 3.9
13+
14+
Interpreter Objects
15+
-------------------
16+
17+
The ``Interpreter`` object represents a single interpreter.
18+
19+
.. class:: Interpreter(id)
20+
21+
The class implementing a subinterpreter object.
22+
23+
.. method:: is_running()
24+
25+
Return ``True`` if the identified interpreter is running.
26+
27+
.. method:: close()
28+
29+
Destroy the interpreter. Attempting to destroy the current
30+
interpreter results in a `RuntimeError`.
31+
32+
.. method:: run(self, src_str, /, *, channels=None):
33+
34+
Run the given source code in the interpreter. This blocks
35+
the current thread until done. ``channels`` should be in
36+
the form : `(RecvChannel, SendChannel)`.
37+
38+
RecvChannel Objects
39+
-------------------
40+
41+
The ``RecvChannel`` object represents a recieving channel.
42+
43+
.. class:: RecvChannel(id)
44+
45+
This class represents the receiving end of a channel.
46+
47+
.. method:: recv()
48+
49+
Get the next object from the channel, and wait if
50+
none have been sent. Associate the interpreter
51+
with the channel.
52+
53+
.. method:: recv_nowait(default=None)
54+
55+
Like ``recv()``, but return the default result
56+
instead of waiting.
57+
58+
59+
SendChannel Objects
60+
--------------------
61+
62+
The ``SendChannel`` object represents a sending channel.
63+
64+
.. class:: SendChannel(id)
65+
66+
This class represents the sending end of a channel.
67+
68+
.. method:: send(obj)
69+
70+
Send the object ``obj`` to the receiving end of the channel
71+
and wait. Associate the interpreter with the channel.
72+
73+
.. method:: send_nowait(obj)
74+
75+
Similar to ``send()``, but returns ``False`` if
76+
*obj* is not immediately received instead of blocking.
77+
78+
79+
This module defines the following global functions:
80+
81+
82+
.. function:: is_shareable(obj)
83+
84+
Return ``True`` if the object's data can be shared between
85+
interpreters.
86+
87+
.. function:: create_channel()
88+
89+
Create a new channel for passing data between interpreters.
90+
91+
.. function:: list_all_channels()
92+
93+
Return all open channels.
94+
95+
.. function:: create(*, isolated=True)
96+
97+
Initialize a new (idle) Python interpreter. Get the currently
98+
running interpreter. This method returns an ``Interpreter`` object.
99+
100+
.. function:: get_current()
101+
102+
Get the currently running interpreter. This method returns
103+
an ``Interpreter`` object.
104+
105+
.. function:: get_main()
106+
107+
Get the main interpreter. This method returns
108+
an ``Interpreter`` object.
109+
110+
.. function:: list_all()
111+
112+
Get all existing interpreters. Returns a list
113+
of ``Interpreter`` objects.
114+
115+
This module also defines the following exceptions.
116+
117+
.. exception:: RunFailedError
118+
119+
This exception, a subclass of :exc:`RuntimeError`, is raised when the
120+
``Interpreter.run()`` results in an uncaught exception.
121+
122+
.. exception:: ChannelError
123+
124+
This exception is a subclass of :exc:`Exception`, and is the base
125+
class for all channel-related exceptions.
126+
127+
.. exception:: ChannelNotFoundError
128+
129+
This exception is a subclass of :exc:`ChannelError`, and is raised
130+
when the the identified channel is not found.
131+
132+
.. exception:: ChannelEmptyError
133+
134+
This exception is a subclass of :exc:`ChannelError`, and is raised when
135+
the channel is unexpectedly empty.
136+
137+
.. exception:: ChannelNotEmptyError
138+
139+
This exception is a subclass of :exc:`ChannelError`, and is raised when
140+
the channel is unexpectedly not empty.
141+
142+
.. exception:: NotReceivedError
143+
144+
This exception is a subclass of :exc:`ChannelError`, and is raised when
145+
nothing was waiting to receive a sent object.

0 commit comments

Comments
Β (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy