8000 gh-134939: Add the interpreters Module by ericsnowcurrently · Pull Request #133958 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-134939: Add the interpreters Module #133958

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 17 commits into from
Jun 11, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

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
Move the interpreters module to the official stdlib.
  • Loading branch information
ericsnowcurrently committed May 30, 2025
commit e3aa50bb8c5336b0246b69c17431b141da06e2d7
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ Doc/howto/clinic.rst @erlend-aasland
# Subinterpreters
**/*interpreteridobject.* @ericsnowcurrently
**/*crossinterp* @ericsnowcurrently
Lib/test/support/interpreters/ @ericsnowcurrently
Lib/interpreters/ @ericsnowcurrently
Modules/_interp*module.c @ericsnowcurrently
Lib/test/test_interpreters/ @ericsnowcurrently

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion Lib/test/test__interpchannels.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from test.support import import_helper, skip_if_sanitizer

_channels = import_helper.import_module('_interpchannels')
from test.support.interpreters import _crossinterp
from interpreters import _crossinterp
from test.test__interpreters import (
_interpreters,
_run_output,
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_concurrent_futures/test_interpreter_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
from concurrent.futures.interpreter import (
ExecutionFailed, BrokenInterpreterPool,
)
from interpreters import queues
import _interpreters
from test import support
import test.test_asyncio.utils as testasyncio_utils
from test.support.interpreters import queues

from .executor import ExecutorTest, mul
from .util import BaseTestCase, InterpreterPoolMixin, setup_module
Expand Down
26 changes: 13 additions & 13 deletions Lib/test/test_interpreters/test_api.py
6D40
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
from test.support import import_helper
# Raise SkipTest if subinterpreters not supported.
_interpreters = import_helper.import_module('_interpreters')
import interpreters
from test.support import Py_GIL_DISABLED
from test.support import interpreters
from test.support import force_not_colorized
import test._crossinterp_definitions as defs
from test.support.interpreters import (
from interpreters import (
InterpreterError, InterpreterNotFoundError, ExecutionFailed,
)
from .utils import (
Expand Down Expand Up @@ -133,7 +133,7 @@ def test_in_subinterpreter(self):
main, = interpreters.list_all()
interp = interpreters.create()
out = _run_output(interp, dedent("""
from test.support import interpreters
import interpreters
interp = interpreters.create()
print(interp.id)
"""))
Expand Down Expand Up @@ -196,7 +196,7 @@ def test_subinterpreter(self):
main = interpreters.get_main()
interp = interpreters.create()
out = _run_output(interp, dedent("""
from test.support import interpreters
import interpreters
cur = interpreters.get_current()
print(cur.id)
"""))
Expand All @@ -213,7 +213,7 @@ def test_idempotent(self):
with self.subTest('subinterpreter'):
interp = interpreters.create()
out = _run_output(interp, dedent("""
from test.support import interpreters
import interpreters
cur = interpreters.get_current()
print(id(cur))
cur = interpreters.get_current()
Expand All @@ -225,7 +225,7 @@ def test_idempotent(self):
with self.subTest('per-interpreter'):
interp = interpreters.create()
out = _run_output(interp, dedent("""
from test.support import interpreters
import interpreters
cur = interpreters.get_current()
print(id(cur))
"""))
Expand Down Expand Up @@ -582,7 +582,7 @@ def test_from_current(self):
main, = interpreters.list_all()
interp = interpreters.create()
out = _run_output(interp, dedent(f"""
from test.support import interpreters
import interpreters
interp = interpreters.Interpreter({interp.id})
try:
interp.close()
Expand All @@ -599,7 +599,7 @@ def test_from_sibling(self):
self.assertEqual(set(interpreters.list_all()),
{main, interp1, interp2})
interp1.exec(dedent(f"""
from test.support import interpreters
import interpreters
interp2 = interpreters.Interpreter({interp2.id})
interp2.close()
interp3 = interpreters.create()
Expand Down Expand Up @@ -806,7 +806,7 @@ def eggs():
ham()
""")
scriptfile = self.make_script('script.py', tempdir, text="""
from test.support import interpreters
import interpreters

def script():
import spam
Expand All @@ -827,7 +827,7 @@ def script():
~~~~~~~~~~~^^^^^^^^
{interpmod_line.strip()}
raise ExecutionFailed(excinfo)
test.support.interpreters.ExecutionFailed: RuntimeError: uh-oh!
interpreters.ExecutionFailed: RuntimeError: uh-oh!

Uncaught in the interpreter:

Expand Down Expand Up @@ -1281,7 +1281,7 @@ def run(text):
# no module indirection
with self.subTest('no indirection'):
text = run(f"""
from test.support import interpreters
import interpreters

def spam():
# This a global var...
Expand All @@ -1301,7 +1301,7 @@ def run(interp, func):
""")
with self.subTest('indirect as func, direct interp'):
text = run(f"""
from test.support import interpreters
import interpreters
import mymod

def spam():
Expand All @@ -1317,7 +1317,7 @@ def spam():

# indirect as func, indirect interp
new_mod('mymod', f"""
from test.support import interpreters
import interpreters
def run(func):
interp = interpreters.create()
return interp.call(func)
Expand Down
16 changes: 8 additions & 8 deletions Lib/test/test_interpreters/test_channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
from test.support import import_helper
# Raise SkipTest if subinterpreters not supported.
_channels = import_helper.import_module('_interpchannels')
from test.support import interpreters
from test.support.interpreters import channels
import interpreters
from interpreters import channels
from .utils import _run_output, TestBase


Expand Down Expand Up @@ -171,7 +171,7 @@ def test_send_recv_main(self):
def test_send_recv_same_interpreter(self):
interp = interpreters.create()
interp.exec(dedent("""
from test.support.interpreters import channels
from interpreters import channels
r, s = 10000 channels.create()
orig = b'spam'
s.send_nowait(orig)
Expand Down Expand Up @@ -244,7 +244,7 @@ def test_send_recv_nowait_main_with_default(self):
def test_send_recv_nowait_same_interpreter(self):
interp = interpreters.create()
interp.exec(dedent("""
from test.support.interpreters import channels
from interpreters import channels
r, s = channels.create()
orig = b'spam'
s.send_nowait(orig)
Expand Down Expand Up @@ -387,7 +387,7 @@ def common(rch, sch, unbound=None, presize=0):
interp = interpreters.create()

_run_output(interp, dedent(f"""
from test.support.interpreters import channels
from interpreters import channels
sch = channels.SendChannel({sch.id})
obj1 = b'spam'
obj2 = b'eggs'
Expand Down Expand Up @@ -482,7 +482,7 @@ def test_send_cleared_with_subinterpreter_mixed(self):
self.assertEqual(_channels.get_count(rch.id), 0)

_run_output(interp, dedent(f"""
from test.support.interpreters import channels
from interpreters import channels
sch = channels.SendChannel({sch.id})
sch.send_nowait(1, unbounditems=channels.UNBOUND)
sch.send_nowait(2, unbounditems=channels.UNBOUND_ERROR)
Expand Down Expand Up @@ -518,15 +518,15 @@ def test_send_cleared_with_subinterpreter_multiple(self):

sch.send_nowait(1)
_run_output(interp1, dedent(f"""
from test.support.interpreters import channels
from interpreters import channels
rch = channels.RecvChannel({rch.id})
sch = channels.SendChannel({sch.id})
obj1 = rch.recv()
sch.send_nowait(2, unbounditems=channels.UNBOUND)
sch.send_nowait(obj1, unbounditems=channels.UNBOUND_REMOVE)
"""))
_run_output(interp2, dedent(f"""
from test.support.interpreters import channels
from interpreters import channels
rch = channels.RecvChannel({rch.id})
sch = channels.SendChannel({sch.id})
obj2 = rch.recv()
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_interpreters/test_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def test_sys_path_0(self):
# The main interpreter's sys.path[0] should be used by subinterpreters.
script = '''
import sys
from test.support import interpreters
import interpreters

orig = sys.path[0]

Expand Down Expand Up @@ -170,7 +170,7 @@ def test_gh_109793(self):
# is reported, even when subinterpreters get cleaned up at the end.
import subprocess
argv = [sys.executable, '-c', '''if True:
from test.support import interpreters
import interpreters
interp = interpreters.create()
raise Exception
''']
Expand Down
18 changes: 9 additions & 9 deletions Lib/test/test_interpreters/test_queues.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from test.support import import_helper, Py_DEBUG
# Raise SkipTest if subinterpreters not supported.
_queues = import_helper.import_module('_interpqueues')
from test.support import interpreters
from test.support.interpreters import queues, _crossinterp
import interpreters
from interpreters import queues, _crossinterp
from .utils import _run_output, TestBase as _TestBase


Expand Down Expand Up @@ -126,7 +126,7 @@ def test_shareable(self):

interp = interpreters.create()
interp.exec(dedent(f"""
from test.support.interpreters import queues
from interpreters import queues
queue1 = queues.Queue({queue1.id})
"""));

Expand Down Expand Up @@ -324,7 +324,7 @@ def test_put_get_full_fallback(self):
def test_put_get_same_interpreter(self):
interp = interpreters.create()
interp.exec(dedent("""
from test.support.interpreters import queues
from interpreters import queues
queue = queues.create()
"""))
for methname in ('get', 'get_nowait'):
Expand All @@ -351,7 +351,7 @@ def test_put_get_different_interpreters(self):
out = _run_output(
interp,
dedent(f"""
from test.support.interpreters import queues
from interpreters import queues
queue1 = queues.Queue({queue1.id})
queue2 = queues.Queue({queue2.id})
assert queue1.qsize() == 1, 'expected: queue1.qsize() == 1'
Expand Down Expand Up @@ -390,7 +390,7 @@ def common(queue, unbound=None, presize=0):
interp = interpreters.create()

_run_output(interp, dedent(f"""
from test.support.interpreters import queues
from interpreters import queues
queue = queues.Queue({queue.id})
obj1 = b'spam'
obj2 = b'eggs'
Expand Down Expand Up @@ -468,7 +468,7 @@ def test_put_cleared_with_subinterpreter_mixed(self):
queue = queues.create()
interp = interpreters.create()
_run_output(interp, dedent(f"""
from test.support.interpreters import queues
from interpreters import queues
queue = queues.Queue({queue.id})
queue.put(1, unbounditems=queues.UNBOUND)
queue.put(2, unbounditems=queues.UNBOUND_ERROR)
Expand Down Expand Up @@ -504,14 +504,14 @@ def test_put_cleared_with_subinterpreter_multiple(self):

queue.put(1)
_run_output(interp1, dedent(f"""
from test.support.interpreters import queues
from interpreters import queues
queue = queues.Queue({queue.id})
obj1 = queue.get()
queue.put(2, unbounditems=queues.UNBOUND)
queue.put(obj1, unbounditems=queues.UNBOUND_REMOVE)
"""))
_run_output(interp2, dedent(f"""
from test.support.interpreters import queues
from interpreters import queues
queue = queues.Queue({queue.id})
obj2 = queue.get()
obj1 = queue.get()
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_interpreters/test_stress.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from test.support import threading_helper
# Raise SkipTest if subinterpreters not supported.
import_helper.import_module('_interpreters')
from test.support import interpreters
import interpreters
from .utils import TestBase


Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_interpreters/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import _interpreters
except ImportError as exc:
raise unittest.SkipTest(str(exc))
from test.support import interpreters
import interpreters


try:
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from test.support import force_not_colorized
from test.support import SHORT_TIMEOUT
try:
from test.support import interpreters
import interpreters
except ImportError:
interpreters = None
import textwrap
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from test import support

try:
from test.support import interpreters
import interpreters
except ImportError:
interpreters = None

Expand Down
6 changes: 3 additions & 3 deletions Lib/test/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2513,10 +2513,10 @@ class SubinterpreterTests(unittest.TestCase):
def setUpClass(cls):
global interpreters
try:
from test.support import interpreters
import interpreters
except ModuleNotFoundError:
raise unittest.SkipTest('subinterpreters required')
import test.support.interpreters.channels # noqa: F401
import interpreters.channels # noqa: F401

@cpython_only
@no_rerun('channels (and queues) might have a refleak; see gh-122199')
Expand Down Expand Up @@ -2547,7 +2547,7 @@ def collate_results(raw):
main_results = collate_results(raw)

interp = interpreters.create()
interp.exec('from test.support import interpreters')
interp.exec('import interpreters')
interp.prepare_main(sch=sch)
interp.exec(script)
raw = rch.recv_nowait()
Expand Down
2 changes: 1 addition & 1 deletion Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -2526,6 +2526,7 @@ LIBSUBDIRS= asyncio \
http \
idlelib idlelib/Icons \
importlib importlib/resources importlib/metadata \
interpreters \
json \
logging \
multiprocessing multiprocessing/dummy \
Expand Down Expand Up @@ -2573,7 +2574,6 @@ TESTSUBDIRS= idlelib/idle_test \
test/subprocessdata \
test/support \
test/support/_hypothesis_stubs \
test/support/interpreters \
test/test_asyncio \
test/test_capi \
test/test_cext \
Expand Down
6 changes: 1 addition & 5 deletions Modules/_interpchannelsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2744,11 +2744,7 @@ _get_current_channelend_type(int end)
// Force the module to be loaded, to register the type.
PyObject *highlevel = PyImport_ImportModule("interpreters.channels");
if (highlevel == NULL) {
PyErr_Clear();
highlevel = PyImport_ImportModule("test.support.interpreters.channels");
if (highlevel == NULL) {
return NULL;
}
return NULL;
}
Py_DECREF(highlevel);
if (end == CHANNEL_SEND) {
Expand Down
Loading
0