gh-101524: Split Up the _xxsubinterpreters Module (gh-101526)

This is step 1 in potentially dropping all the "channel"-related code. Channels have already been removed from PEP 554.

https://github.com/python/cpython/issues/101524
This commit is contained in:
Eric Snow 2023-02-03 18:14:43 -07:00 committed by GitHub
parent d4c410f0f9
commit c67b00534a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 4007 additions and 3697 deletions

View file

@ -2,11 +2,12 @@
import time import time
import _xxsubinterpreters as _interpreters import _xxsubinterpreters as _interpreters
import _xxinterpchannels as _channels
# aliases: # aliases:
from _xxsubinterpreters import ( from _xxsubinterpreters import is_shareable
from _xxinterpchannels import (
ChannelError, ChannelNotFoundError, ChannelEmptyError, ChannelError, ChannelNotFoundError, ChannelEmptyError,
is_shareable,
) )
@ -102,7 +103,7 @@ def create_channel():
The channel may be used to pass data safely between interpreters. The channel may be used to pass data safely between interpreters.
""" """
cid = _interpreters.channel_create() cid = _channels.create()
recv, send = RecvChannel(cid), SendChannel(cid) recv, send = RecvChannel(cid), SendChannel(cid)
return recv, send return recv, send
@ -110,14 +111,14 @@ def create_channel():
def list_all_channels(): def list_all_channels():
"""Return a list of (recv, send) for all open channels.""" """Return a list of (recv, send) for all open channels."""
return [(RecvChannel(cid), SendChannel(cid)) return [(RecvChannel(cid), SendChannel(cid))
for cid in _interpreters.channel_list_all()] for cid in _channels.list_all()]
class _ChannelEnd: class _ChannelEnd:
"""The base class for RecvChannel and SendChannel.""" """The base class for RecvChannel and SendChannel."""
def __init__(self, id): def __init__(self, id):
if not isinstance(id, (int, _interpreters.ChannelID)): if not isinstance(id, (int, _channels.ChannelID)):
raise TypeError(f'id must be an int, got {id!r}') raise TypeError(f'id must be an int, got {id!r}')
self._id = id self._id = id
@ -152,10 +153,10 @@ class RecvChannel(_ChannelEnd):
This blocks until an object has been sent, if none have been This blocks until an object has been sent, if none have been
sent already. sent already.
""" """
obj = _interpreters.channel_recv(self._id, _sentinel) obj = _channels.recv(self._id, _sentinel)
while obj is _sentinel: while obj is _sentinel:
time.sleep(_delay) time.sleep(_delay)
obj = _interpreters.channel_recv(self._id, _sentinel) obj = _channels.recv(self._id, _sentinel)
return obj return obj
def recv_nowait(self, default=_NOT_SET): def recv_nowait(self, default=_NOT_SET):
@ -166,9 +167,9 @@ class RecvChannel(_ChannelEnd):
is the same as recv(). is the same as recv().
""" """
if default is _NOT_SET: if default is _NOT_SET:
return _interpreters.channel_recv(self._id) return _channels.recv(self._id)
else: else:
return _interpreters.channel_recv(self._id, default) return _channels.recv(self._id, default)
class SendChannel(_ChannelEnd): class SendChannel(_ChannelEnd):
@ -179,7 +180,7 @@ class SendChannel(_ChannelEnd):
This blocks until the object is received. This blocks until the object is received.
""" """
_interpreters.channel_send(self._id, obj) _channels.send(self._id, obj)
# XXX We are missing a low-level channel_send_wait(). # XXX We are missing a low-level channel_send_wait().
# See bpo-32604 and gh-19829. # See bpo-32604 and gh-19829.
# Until that shows up we fake it: # Until that shows up we fake it:
@ -194,4 +195,4 @@ class SendChannel(_ChannelEnd):
# XXX Note that at the moment channel_send() only ever returns # XXX Note that at the moment channel_send() only ever returns
# None. This should be fixed when channel_send_wait() is added. # None. This should be fixed when channel_send_wait() is added.
# See bpo-32604 and gh-19829. # See bpo-32604 and gh-19829.
return _interpreters.channel_send(self._id, obj) return _channels.send(self._id, obj)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -8,6 +8,7 @@ import time
from test import support from test import support
from test.support import import_helper from test.support import import_helper
_interpreters = import_helper.import_module('_xxsubinterpreters') _interpreters = import_helper.import_module('_xxsubinterpreters')
_channels = import_helper.import_module('_xxinterpchannels')
from test.support import interpreters from test.support import interpreters
@ -533,7 +534,7 @@ class TestRecvChannelAttrs(TestBase):
def test_id_type(self): def test_id_type(self):
rch, _ = interpreters.create_channel() rch, _ = interpreters.create_channel()
self.assertIsInstance(rch.id, _interpreters.ChannelID) self.assertIsInstance(rch.id, _channels.ChannelID)
def test_custom_id(self): def test_custom_id(self):
rch = interpreters.RecvChannel(1) rch = interpreters.RecvChannel(1)
@ -558,7 +559,7 @@ class TestSendChannelAttrs(TestBase):
def test_id_type(self): def test_id_type(self):
_, sch = interpreters.create_channel() _, sch = interpreters.create_channel()
self.assertIsInstance(sch.id, _interpreters.ChannelID) self.assertIsInstance(sch.id, _channels.ChannelID)
def test_custom_id(self): def test_custom_id(self):
sch = interpreters.SendChannel(1) sch = interpreters.SendChannel(1)

View file

@ -280,6 +280,7 @@ PYTHONPATH=$(COREPYTHONPATH)
# Testing # Testing
#_xxsubinterpreters _xxsubinterpretersmodule.c #_xxsubinterpreters _xxsubinterpretersmodule.c
#_xxinterpchannels _xxinterpchannelsmodule.c
#_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c #_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
#_testbuffer _testbuffer.c #_testbuffer _testbuffer.c
#_testinternalcapi _testinternalcapi.c #_testinternalcapi _testinternalcapi.c

View file

@ -43,6 +43,7 @@
@MODULE__STRUCT_TRUE@_struct _struct.c @MODULE__STRUCT_TRUE@_struct _struct.c
@MODULE__TYPING_TRUE@_typing _typingmodule.c @MODULE__TYPING_TRUE@_typing _typingmodule.c
@MODULE__XXSUBINTERPRETERS_TRUE@_xxsubinterpreters _xxsubinterpretersmodule.c @MODULE__XXSUBINTERPRETERS_TRUE@_xxsubinterpreters _xxsubinterpretersmodule.c
@MODULE__XXINTERPCHANNELS_TRUE@_xxinterpchannels _xxinterpchannelsmodule.c
@MODULE__ZONEINFO_TRUE@_zoneinfo _zoneinfo.c @MODULE__ZONEINFO_TRUE@_zoneinfo _zoneinfo.c
# needs libm # needs libm

View file

@ -1639,6 +1639,58 @@ run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs)
return PyLong_FromLong(r); return PyLong_FromLong(r);
} }
static void
_xid_capsule_destructor(PyObject *capsule)
{
_PyCrossInterpreterData *data = \
(_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL);
if (data != NULL) {
assert(_PyCrossInterpreterData_Release(data) == 0);
PyMem_Free(data);
}
}
static PyObject *
get_crossinterp_data(PyObject *self, PyObject *args)
{
PyObject *obj = NULL;
if (!PyArg_ParseTuple(args, "O:get_crossinterp_data", &obj)) {
return NULL;
}
_PyCrossInterpreterData *data = PyMem_NEW(_PyCrossInterpreterData, 1);
if (data == NULL) {
PyErr_NoMemory();
return NULL;
}
if (_PyObject_GetCrossInterpreterData(obj, data) != 0) {
PyMem_Free(data);
return NULL;
}
PyObject *capsule = PyCapsule_New(data, NULL, _xid_capsule_destructor);
if (capsule == NULL) {
assert(_PyCrossInterpreterData_Release(data) == 0);
PyMem_Free(data);
}
return capsule;
}
static PyObject *
restore_crossinterp_data(PyObject *self, PyObject *args)
{
PyObject *capsule = NULL;
if (!PyArg_ParseTuple(args, "O:restore_crossinterp_data", &capsule)) {
return NULL;
}
_PyCrossInterpreterData *data = \
(_PyCrossInterpreterData *)PyCapsule_GetPointer(capsule, NULL);
if (data == NULL) {
return NULL;
}
return _PyCrossInterpreterData_NewObject(data);
}
static void static void
slot_tp_del(PyObject *self) slot_tp_del(PyObject *self)
{ {
@ -3306,6 +3358,8 @@ static PyMethodDef TestMethods[] = {
{"run_in_subinterp_with_config", {"run_in_subinterp_with_config",
_PyCFunction_CAST(run_in_subinterp_with_config), _PyCFunction_CAST(run_in_subinterp_with_config),
METH_VARARGS | METH_KEYWORDS}, METH_VARARGS | METH_KEYWORDS},
{"get_crossinterp_data", get_crossinterp_data, METH_VARARGS},
{"restore_crossinterp_data", restore_crossinterp_data, METH_VARARGS},
{"with_tp_del", with_tp_del, METH_VARARGS}, {"with_tp_del", with_tp_del, METH_VARARGS},
{"create_cfunction", create_cfunction, METH_NOARGS}, {"create_cfunction", create_cfunction, METH_NOARGS},
{"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_VARARGS, {"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_VARARGS,

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -37,6 +37,7 @@ extern PyObject* PyInit__weakref(void);
/* XXX: These two should really be extracted to standalone extensions. */ /* XXX: These two should really be extracted to standalone extensions. */
extern PyObject* PyInit_xxsubtype(void); extern PyObject* PyInit_xxsubtype(void);
extern PyObject* PyInit__xxsubinterpreters(void); extern PyObject* PyInit__xxsubinterpreters(void);
extern PyObject* PyInit__xxinterpchannels(void);
extern PyObject* PyInit__random(void); extern PyObject* PyInit__random(void);
extern PyObject* PyInit_itertools(void); extern PyObject* PyInit_itertools(void);
extern PyObject* PyInit__collections(void); extern PyObject* PyInit__collections(void);
@ -134,6 +135,7 @@ struct _inittab _PyImport_Inittab[] = {
{"xxsubtype", PyInit_xxsubtype}, {"xxsubtype", PyInit_xxsubtype},
{"_xxsubinterpreters", PyInit__xxsubinterpreters}, {"_xxsubinterpreters", PyInit__xxsubinterpreters},
{"_xxinterpchannels", PyInit__xxinterpchannels},
#ifdef _Py_HAVE_ZLIB #ifdef _Py_HAVE_ZLIB
{"zlib", PyInit_zlib}, {"zlib", PyInit_zlib},
#endif #endif

View file

@ -418,6 +418,7 @@
<ClCompile Include="..\Modules\timemodule.c" /> <ClCompile Include="..\Modules\timemodule.c" />
<ClCompile Include="..\Modules\xxsubtype.c" /> <ClCompile Include="..\Modules\xxsubtype.c" />
<ClCompile Include="..\Modules\_xxsubinterpretersmodule.c" /> <ClCompile Include="..\Modules\_xxsubinterpretersmodule.c" />
<ClCompile Include="..\Modules\_xxinterpchannelsmodule.c" />
<ClCompile Include="..\Modules\_io\fileio.c" /> <ClCompile Include="..\Modules\_io\fileio.c" />
<ClCompile Include="..\Modules\_io\bytesio.c" /> <ClCompile Include="..\Modules\_io\bytesio.c" />
<ClCompile Include="..\Modules\_io\stringio.c" /> <ClCompile Include="..\Modules\_io\stringio.c" />

View file

@ -1322,6 +1322,9 @@
<ClCompile Include="..\Modules\_xxsubinterpretersmodule.c"> <ClCompile Include="..\Modules\_xxsubinterpretersmodule.c">
<Filter>Modules</Filter> <Filter>Modules</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Modules\_xxinterpchannelsmodule.c">
<Filter>Modules</Filter>
</ClCompile>
<ClCompile Include="..\Parser\string_parser.c"> <ClCompile Include="..\Parser\string_parser.c">
<Filter>Parser</Filter> <Filter>Parser</Filter>
</ClCompile> </ClCompile>

View file

@ -36,6 +36,7 @@ IGNORE = {
'_testmultiphase', '_testmultiphase',
'_testsinglephase', '_testsinglephase',
'_xxsubinterpreters', '_xxsubinterpreters',
'_xxinterpchannels',
'_xxtestfuzz', '_xxtestfuzz',
'idlelib.idle_test', 'idlelib.idle_test',
'test', 'test',

27
configure generated vendored
View file

@ -752,6 +752,8 @@ MODULE__MULTIPROCESSING_FALSE
MODULE__MULTIPROCESSING_TRUE MODULE__MULTIPROCESSING_TRUE
MODULE__ZONEINFO_FALSE MODULE__ZONEINFO_FALSE
MODULE__ZONEINFO_TRUE MODULE__ZONEINFO_TRUE
MODULE__XXINTERPCHANNELS_FALSE
MODULE__XXINTERPCHANNELS_TRUE
MODULE__XXSUBINTERPRETERS_FALSE MODULE__XXSUBINTERPRETERS_FALSE
MODULE__XXSUBINTERPRETERS_TRUE MODULE__XXSUBINTERPRETERS_TRUE
MODULE__TYPING_FALSE MODULE__TYPING_FALSE
@ -25615,6 +25617,7 @@ case $ac_sys_system in #(
py_cv_module__scproxy=n/a py_cv_module__scproxy=n/a
py_cv_module__tkinter=n/a py_cv_module__tkinter=n/a
py_cv_module__xxsubinterpreters=n/a py_cv_module__xxsubinterpreters=n/a
py_cv_module__xxinterpchannels=n/a
py_cv_module_grp=n/a py_cv_module_grp=n/a
py_cv_module_nis=n/a py_cv_module_nis=n/a
py_cv_module_ossaudiodev=n/a py_cv_module_ossaudiodev=n/a
@ -26057,6 +26060,26 @@ fi
fi
if test "$py_cv_module__xxinterpchannels" != "n/a"; then :
py_cv_module__xxinterpchannels=yes
fi
if test "$py_cv_module__xxinterpchannels" = yes; then
MODULE__XXINTERPCHANNELS_TRUE=
MODULE__XXINTERPCHANNELS_FALSE='#'
else
MODULE__XXINTERPCHANNELS_TRUE='#'
MODULE__XXINTERPCHANNELS_FALSE=
fi
as_fn_append MODULE_BLOCK "MODULE__XXINTERPCHANNELS_STATE=$py_cv_module__xxinterpchannels$as_nl"
if test "x$py_cv_module__xxinterpchannels" = xyes; then :
fi fi
@ -28236,6 +28259,10 @@ if test -z "${MODULE__XXSUBINTERPRETERS_TRUE}" && test -z "${MODULE__XXSUBINTERP
as_fn_error $? "conditional \"MODULE__XXSUBINTERPRETERS\" was never defined. as_fn_error $? "conditional \"MODULE__XXSUBINTERPRETERS\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5 Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi fi
if test -z "${MODULE__XXINTERPCHANNELS_TRUE}" && test -z "${MODULE__XXINTERPCHANNELS_FALSE}"; then
as_fn_error $? "conditional \"MODULE__XXINTERPCHANNELS\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${MODULE__ZONEINFO_TRUE}" && test -z "${MODULE__ZONEINFO_FALSE}"; then if test -z "${MODULE__ZONEINFO_TRUE}" && test -z "${MODULE__ZONEINFO_FALSE}"; then
as_fn_error $? "conditional \"MODULE__ZONEINFO\" was never defined. as_fn_error $? "conditional \"MODULE__ZONEINFO\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5 Usually this means the macro was only invoked conditionally." "$LINENO" 5

View file

@ -7017,6 +7017,7 @@ AS_CASE([$ac_sys_system],
[_scproxy], [_scproxy],
[_tkinter], [_tkinter],
[_xxsubinterpreters], [_xxsubinterpreters],
[_xxinterpchannels],
[grp], [grp],
[nis], [nis],
[ossaudiodev], [ossaudiodev],
@ -7135,6 +7136,7 @@ PY_STDLIB_MOD_SIMPLE([select])
PY_STDLIB_MOD_SIMPLE([_struct]) PY_STDLIB_MOD_SIMPLE([_struct])
PY_STDLIB_MOD_SIMPLE([_typing]) PY_STDLIB_MOD_SIMPLE([_typing])
PY_STDLIB_MOD_SIMPLE([_xxsubinterpreters]) PY_STDLIB_MOD_SIMPLE([_xxsubinterpreters])
PY_STDLIB_MOD_SIMPLE([_xxinterpchannels])
PY_STDLIB_MOD_SIMPLE([_zoneinfo]) PY_STDLIB_MOD_SIMPLE([_zoneinfo])
dnl multiprocessing modules dnl multiprocessing modules