Skip to content

Commit 80d20c6

Browse files
Fix the test.
1 parent 08a0321 commit 80d20c6

File tree

3 files changed

+37
-40
lines changed

3 files changed

+37
-40
lines changed

Lib/test/test_capi/test_misc.py

+17-10
Original file line numberDiff line numberDiff line change
@@ -1629,27 +1629,34 @@ def test_tp_mro_is_set(self):
16291629

16301630
class TestStaticTypes(unittest.TestCase):
16311631

1632+
_has_run = False
1633+
1634+
@classmethod
1635+
def setUpClass(cls):
1636+
# The tests here don't play nice with our approach to refleak
1637+
# detection, so we bail out in that case.
1638+
if cls._has_run:
1639+
raise unittest.SkipTest('these tests do not support re-running')
1640+
cls._has_run = True
1641+
1642+
@contextlib.contextmanager
1643+
def basic_static_type(self, *args):
1644+
cls = _testcapi.get_basic_static_type(*args)
1645+
yield cls
1646+
16321647
def test_pytype_ready_always_sets_tp_type(self):
16331648
# The point of this test is to prevent something like
16341649
# https://github.com/python/cpython/issues/104614
16351650
# from happening again.
16361651

1637-
@contextlib.contextmanager
1638-
def basic_static_type(*args):
1639-
cls = _testcapi.get_basic_static_type(*args)
1640-
try:
1641-
yield cls
1642-
finally:
1643-
_testcapi.clear_basic_static_type(cls)
1644-
16451652
# First check when tp_base/tp_bases is *not* set before PyType_Ready().
1646-
with basic_static_type() as cls:
1653+
with self.basic_static_type() as cls:
16471654
self.assertIs(cls.__base__, object);
16481655
self.assertEqual(cls.__bases__, (object,));
16491656
self.assertIs(type(cls), type(object));
16501657

16511658
# Then check when we *do* set tp_base/tp_bases first.
1652-
with basic_static_type(object) as cls:
1659+
with self.basic_static_type(object) as cls:
16531660
self.assertIs(cls.__base__, object);
16541661
self.assertEqual(cls.__bases__, (object,));
16551662
self.assertIs(type(cls), type(object));

Modules/_testcapimodule.c

+18-29
Original file line numberDiff line numberDiff line change
@@ -2627,13 +2627,20 @@ type_get_tp_mro(PyObject *self, PyObject *type)
26272627
}
26282628

26292629

2630-
static PyTypeObject BasicStaticType = {
2631-
PyVarObject_HEAD_INIT(NULL, 0)
2632-
.tp_name = "BasicStaticType",
2633-
.tp_basicsize = sizeof(PyObject),
2630+
/* We only use 2 in test_capi/test_misc.py. */
2631+
#define NUM_BASIC_STATIC_TYPES 2
2632+
static PyTypeObject BasicStaticTypes[NUM_BASIC_STATIC_TYPES] = {
2633+
#define INIT_BASIC_STATIC_TYPE \
2634+
{ \
2635+
PyVarObject_HEAD_INIT(NULL, 0) \
2636+
.tp_name = "BasicStaticType", \
2637+
.tp_basicsize = sizeof(PyObject), \
2638+
}
2639+
INIT_BASIC_STATIC_TYPE,
2640+
INIT_BASIC_STATIC_TYPE,
2641+
#undef INIT_BASIC_STATIC_TYPE
26342642
};
2635-
2636-
static PyObject * clear_basic_static_type(PyObject *, PyObject *);
2643+
static int num_basic_static_types_used = 0;
26372644

26382645
static PyObject *
26392646
get_basic_static_type(PyObject *self, PyObject *args)
@@ -2644,42 +2651,25 @@ get_basic_static_type(PyObject *self, PyObject *args)
26442651
}
26452652
assert(base == NULL || PyType_Check(base));
26462653

2647-
PyTypeObject *cls = &BasicStaticType;
2648-
assert(!(cls->tp_flags & Py_TPFLAGS_READY));
2654+
if(num_basic_static_types_used >= NUM_BASIC_STATIC_TYPES) {
2655+
PyErr_SetString(PyExc_RuntimeError, "no more available basic static types");
2656+
return NULL;
2657+
}
2658+
PyTypeObject *cls = &BasicStaticTypes[num_basic_static_types_used++];
26492659

26502660
if (base != NULL) {
26512661
cls->tp_base = (PyTypeObject *)Py_NewRef(base);
26522662
cls->tp_bases = Py_BuildValue("(O)", base);
26532663
if (cls->tp_bases == NULL) {
2654-
clear_basic_static_type(self, (PyObject *)cls);
26552664
return NULL;
26562665
}
26572666
}
26582667
if (PyType_Ready(cls) < 0) {
2659-
clear_basic_static_type(self, (PyObject *)cls);
26602668
return NULL;
26612669
}
2662-
Py_INCREF(cls);
26632670
return (PyObject *)cls;
26642671
}
26652672

2666-
static PyObject *
2667-
clear_basic_static_type(PyObject *self, PyObject *clsobj)
2668-
{
2669-
// Reset it back to the statically initialized state.
2670-
PyTypeObject *cls = (PyTypeObject *)clsobj;
2671-
Py_CLEAR(cls->ob_base.ob_base.ob_type);
2672-
Py_CLEAR(cls->tp_base);
2673-
Py_CLEAR(cls->tp_bases);
2674-
Py_CLEAR(cls->tp_mro);
2675-
Py_CLEAR(cls->tp_subclasses);
2676-
Py_CLEAR(cls->tp_dict);
2677-
cls->tp_flags &= ~Py_TPFLAGS_READY;
2678-
cls->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
2679-
cls->tp_version_tag = 0;
2680-
Py_RETURN_NONE;
2681-
}
2682-
26832673

26842674
// Test PyThreadState C API
26852675
static PyObject *
@@ -3439,7 +3429,6 @@ static PyMethodDef TestMethods[] = {
34393429
{"type_get_tp_bases", type_get_tp_bases, METH_O},
34403430
{"type_get_tp_mro", type_get_tp_mro, METH_O},
34413431
{"get_basic_static_type", get_basic_static_type, METH_VARARGS, NULL},
3442-
{"clear_basic_static_type", clear_basic_static_type, METH_O, NULL},
34433432
{"test_tstate_capi", test_tstate_capi, METH_NOARGS, NULL},
34443433
{"frame_getlocals", frame_getlocals, METH_O, NULL},
34453434
{"frame_getglobals", frame_getglobals, METH_O, NULL},

Tools/c-analyzer/cpython/ignored.tsv

+2-1
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,8 @@ Modules/_testcapi/watchers.c - num_code_object_destroyed_events -
420420
Modules/_testcapi/watchers.c - pyfunc_watchers -
421421
Modules/_testcapi/watchers.c - func_watcher_ids -
422422
Modules/_testcapi/watchers.c - func_watcher_callbacks -
423-
Modules/_testcapimodule.c - BasicStaticType -
423+
Modules/_testcapimodule.c - BasicStaticTypes -
424+
Modules/_testcapimodule.c - num_basic_static_types_used -
424425
Modules/_testcapimodule.c - ContainerNoGC_members -
425426
Modules/_testcapimodule.c - ContainerNoGC_type -
426427
Modules/_testcapimodule.c - FmData -

0 commit comments

Comments
 (0)