bpo-46417: Add _PyType_GetSubclasses() function (GH-30761) · python/cpython@8ee07dd · GitHub
Skip to content

Commit 8ee07dd

Browse files
authored
bpo-46417: Add _PyType_GetSubclasses() function (GH-30761)
Add a new _PyType_GetSubclasses() function to get type's subclasses. _PyType_GetSubclasses(type) returns a list which holds strong refererences to subclasses. It is safer than iterating on type->tp_subclasses which yields weak references and can be modified in the loop. _PyType_GetSubclasses(type) now holds a reference to the tp_subclasses dict while creating the list of subclasses. set_collection_flag_recursive() of _abc.c now uses _PyType_GetSubclasses().
1 parent 57d1855 commit 8ee07dd

3 files changed

Lines changed: 75 additions & 54 deletions

File tree

Include/internal/pycore_object.h

Lines changed: 6 additions & 5 deletions

Modules/_abc.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#endif
55

66
#include "Python.h"
7+
#include "pycore_object.h" // _PyType_GetSubclasses()
78
#include "pycore_moduleobject.h" // _PyModule_GetState()
89
#include "clinic/_abc.c.h"
910

@@ -493,21 +494,20 @@ set_collection_flag_recursive(PyTypeObject *child, unsigned long flag)
493494
{
494495
return;
495496
}
497+
496498
child->tp_flags &= ~COLLECTION_FLAGS;
497499
child->tp_flags |= flag;
498-
PyObject *grandchildren = child->tp_subclasses;
500+
501+
PyObject *grandchildren = _PyType_GetSubclasses(child);
499502
if (grandchildren == NULL) {
500503
return;
501504
}
502-
assert(PyDict_CheckExact(grandchildren));
503-
Py_ssize_t i = 0;
504-
while (PyDict_Next(grandchildren, &i, NULL, &grandchildren)) {
505-
assert(PyWeakref_CheckRef(grandchildren));
506-
PyObject *grandchild = PyWeakref_GET_OBJECT(grandchildren);
507-
if (PyType_Check(grandchild)) {
508-
set_collection_flag_recursive((PyTypeObject *)grandchild, flag);
509-
}
505+
506+
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(grandchildren); i++) {
507+
PyObject *grandchild = PyList_GET_ITEM(grandchildren, i);
508+
set_collection_flag_recursive((PyTypeObject *)grandchild, flag);
510509
}
510+
Py_DECREF(grandchildren);
511511
}
512512

513513
/*[clinic input]

Objects/typeobject.c

Lines changed: 60 additions & 40 deletions

0 commit comments

Comments
 (0)