Skip to content

Commit bae872f

Browse files
nanjekyejoannahnanjekyejoannahblurb-it[bot]
authored
bpo-32604: Recommit "bpo-32604: PEP 554 for use in test suite (GH-19985)" (GH-20611)
* 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() * Update Lib/test/support/interpreters.py Co-authored-by: Pablo Galindo <[email protected]> * Remove documentation (module is for internal use) Co-authored-by: nanjekyejoannah <[email protected]> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
1 parent 7aed052 commit bae872f

File tree

3 files changed

+720
-0
lines changed

3 files changed

+720
-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 receiving 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

0 commit comments

Comments
 (0)