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 _xxsubinterpreters as _interpreters
import _xxinterpchannels as _channels
# aliases:
from _xxsubinterpreters import (
from _xxsubinterpreters import is_shareable
from _xxinterpchannels import (
ChannelError, ChannelNotFoundError, ChannelEmptyError,
is_shareable,
)
@ -102,7 +103,7 @@ def create_channel():
The channel may be used to pass data safely between interpreters.
"""
cid = _interpreters.channel_create()
cid = _channels.create()
recv, send = RecvChannel(cid), SendChannel(cid)
return recv, send
@ -110,14 +111,14 @@ def create_channel():
def list_all_channels():
"""Return a list of (recv, send) for all open channels."""
return [(RecvChannel(cid), SendChannel(cid))
for cid in _interpreters.channel_list_all()]
for cid in _channels.list_all()]
class _ChannelEnd:
"""The base class for RecvChannel and SendChannel."""
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}')
self._id = id
@ -152,10 +153,10 @@ def recv(self, *, _sentinel=object(), _delay=10 / 1000): # 10 milliseconds
This blocks until an object has been sent, if none have been
sent already.
"""
obj = _interpreters.channel_recv(self._id, _sentinel)
obj = _channels.recv(self._id, _sentinel)
while obj is _sentinel:
time.sleep(_delay)
obj = _interpreters.channel_recv(self._id, _sentinel)
obj = _channels.recv(self._id, _sentinel)
return obj
def recv_nowait(self, default=_NOT_SET):
@ -166,9 +167,9 @@ def recv_nowait(self, default=_NOT_SET):
is the same as recv().
"""
if default is _NOT_SET:
return _interpreters.channel_recv(self._id)
return _channels.recv(self._id)
else:
return _interpreters.channel_recv(self._id, default)
return _channels.recv(self._id, default)
class SendChannel(_ChannelEnd):
@ -179,7 +180,7 @@ def send(self, obj):
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().
# See bpo-32604 and gh-19829.
# Until that shows up we fake it:
@ -194,4 +195,4 @@ def send_nowait(self, obj):
# XXX Note that at the moment channel_send() only ever returns
# None. This should be fixed when channel_send_wait() is added.
# 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 @@
from test import support
from test.support import import_helper
_interpreters = import_helper.import_module('_xxsubinterpreters')
_channels = import_helper.import_module('_xxinterpchannels')
from test.support import interpreters
@ -533,7 +534,7 @@ class TestRecvChannelAttrs(TestBase):
def test_id_type(self):
rch, _ = interpreters.create_channel()
self.assertIsInstance(rch.id, _interpreters.ChannelID)
self.assertIsInstance(rch.id, _channels.ChannelID)
def test_custom_id(self):
rch = interpreters.RecvChannel(1)
@ -558,7 +559,7 @@ class TestSendChannelAttrs(TestBase):
def test_id_type(self):
_, sch = interpreters.create_channel()
self.assertIsInstance(sch.id, _interpreters.ChannelID)
self.assertIsInstance(sch.id, _channels.ChannelID)
def test_custom_id(self):
sch = interpreters.SendChannel(1)

View file

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

View file

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

View file

@ -1639,6 +1639,58 @@ run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs)
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
slot_tp_del(PyObject *self)
{
@ -3306,6 +3358,8 @@ static PyMethodDef TestMethods[] = {
{"run_in_subinterp_with_config",
_PyCFunction_CAST(run_in_subinterp_with_config),
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},
{"create_cfunction", create_cfunction, METH_NOARGS},
{"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. */
extern PyObject* PyInit_xxsubtype(void);
extern PyObject* PyInit__xxsubinterpreters(void);
extern PyObject* PyInit__xxinterpchannels(void);
extern PyObject* PyInit__random(void);
extern PyObject* PyInit_itertools(void);
extern PyObject* PyInit__collections(void);
@ -134,6 +135,7 @@ struct _inittab _PyImport_Inittab[] = {
{"xxsubtype", PyInit_xxsubtype},
{"_xxsubinterpreters", PyInit__xxsubinterpreters},
{"_xxinterpchannels", PyInit__xxinterpchannels},
#ifdef _Py_HAVE_ZLIB
{"zlib", PyInit_zlib},
#endif

View file

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

View file

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

View file

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

27
configure generated vendored
View file

@ -752,6 +752,8 @@ MODULE__MULTIPROCESSING_FALSE
MODULE__MULTIPROCESSING_TRUE
MODULE__ZONEINFO_FALSE
MODULE__ZONEINFO_TRUE
MODULE__XXINTERPCHANNELS_FALSE
MODULE__XXINTERPCHANNELS_TRUE
MODULE__XXSUBINTERPRETERS_FALSE
MODULE__XXSUBINTERPRETERS_TRUE
MODULE__TYPING_FALSE
@ -25615,6 +25617,7 @@ case $ac_sys_system in #(
py_cv_module__scproxy=n/a
py_cv_module__tkinter=n/a
py_cv_module__xxsubinterpreters=n/a
py_cv_module__xxinterpchannels=n/a
py_cv_module_grp=n/a
py_cv_module_nis=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
@ -28236,6 +28259,10 @@ if test -z "${MODULE__XXSUBINTERPRETERS_TRUE}" && test -z "${MODULE__XXSUBINTERP
as_fn_error $? "conditional \"MODULE__XXSUBINTERPRETERS\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
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
as_fn_error $? "conditional \"MODULE__ZONEINFO\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5

View file

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