import pickle
import locale
import sys
+import textwrap
import types
import unittest.mock
import weakref
'close', 'throw'}))
+class SubinterpreterTests(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ global interpreters
+ try:
+ from test.support import interpreters
+ except ModuleNotFoundError:
+ raise unittest.SkipTest('subinterpreters required')
+
+ @cpython_only
+ def test_slot_wrappers(self):
+ rch, sch = interpreters.create_channel()
+
+ # For now it's sufficient to check int.__str__.
+ # See https://github.com/python/cpython/issues/117482
+ # and https://github.com/python/cpython/pull/117660.
+ script = textwrap.dedent(f'''
+ text = repr(int.__str__)
+ sch = interpreters.SendChannel({sch.id})
+ sch.send_nowait(text)
+ ''')
+
+ exec(script)
+ expected = rch.recv()
+
+ interp = interpreters.create()
+ interp.run('from test.support import interpreters')
+ interp.run(script)
+ results = rch.recv()
+
+ self.assertEqual(results, expected)
+
+
if __name__ == '__main__':
unittest.main()
self->tp_subclasses = NULL;
}
+
+/* In 3.13+ this is stored in _PyRuntimeState. */
+static PyTypeObject static_type_defs[_Py_MAX_STATIC_BUILTIN_TYPES];
+
+static inline PyTypeObject *
+static_builtin_get_def(PyTypeObject *type)
+{
+ size_t index = static_builtin_index_get(type);
+ return &static_type_defs[index];
+}
+
+
static inline static_builtin_state *
static_builtin_state_get(PyInterpreterState *interp, PyTypeObject *self)
{
return 0;
}
-static int add_operators(PyTypeObject *);
+static int add_operators(PyTypeObject *, PyTypeObject *);
static int add_tp_new_wrapper(PyTypeObject *type);
#define COLLECTION_FLAGS (Py_TPFLAGS_SEQUENCE | Py_TPFLAGS_MAPPING)
static int
-type_ready_fill_dict(PyTypeObject *type)
+type_ready_fill_dict(PyTypeObject *type, PyTypeObject *def)
{
/* Add type-specific descriptors to tp_dict */
- if (add_operators(type) < 0) {
+ if (add_operators(type, def) < 0) {
return -1;
}
if (type_add_methods(type) < 0) {
static int
-type_ready(PyTypeObject *type, int rerunbuiltin)
+type_ready(PyTypeObject *type, PyTypeObject *def, int rerunbuiltin)
{
_PyObject_ASSERT((PyObject *)type, !is_readying(type));
start_readying(type);
if (type_ready_set_new(type, rerunbuiltin) < 0) {
goto error;
}
- if (type_ready_fill_dict(type) < 0) {
+ if (type_ready_fill_dict(type, def) < 0) {
goto error;
}
if (!rerunbuiltin) {
type->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
}
- return type_ready(type, 0);
+ return type_ready(type, NULL, 0);
}
int
static_builtin_state_init(interp, self);
- int res = type_ready(self, !ismain);
+ PyTypeObject *def = static_builtin_get_def(self);
+ if (ismain) {
+ memcpy(def, self, sizeof(PyTypeObject));
+ }
+
+ int res = type_ready(self, def, !ismain);
if (res < 0) {
static_builtin_state_clear(interp, self);
}
+
return res;
}
infinite recursion here.) */
static int
-add_operators(PyTypeObject *type)
+add_operators(PyTypeObject *type, PyTypeObject *def)
{
PyObject *dict = lookup_tp_dict(type);
pytype_slotdef *p;
PyObject *descr;
void **ptr;
+ assert(def == NULL || (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN));
+ if (def == NULL) {
+ def = type;
+ }
+
for (p = slotdefs; p->name; p++) {
if (p->wrapper == NULL)
continue;
- ptr = slotptr(type, p->offset);
+ ptr = slotptr(def, p->offset);
if (!ptr || !*ptr)
continue;
int r = PyDict_Contains(dict, p->name_strobj);