Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8d24ee9

Browse files
committed
Refactoring: rename update_these_slots() into update_subclasses() and
generalize to take a callback function and a void * data argument. This might come in handy later... :-)
1 parent b39903b commit 8d24ee9

1 file changed

Lines changed: 68 additions & 47 deletions

File tree

Objects/typeobject.c

Lines changed: 68 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ static int add_subclass(PyTypeObject*, PyTypeObject*);
130130
static void remove_subclass(PyTypeObject *, PyTypeObject *);
131131
static void update_all_slots(PyTypeObject *);
132132

133+
typedef int (*update_callback)(PyTypeObject *, void *);
134+
static int update_subclasses(PyTypeObject *type, PyObject *name,
135+
update_callback callback, void *data);
136+
static int recurse_down_subclasses(PyTypeObject *type, PyObject *name,
137+
update_callback callback, void *data);
138+
133139
static int
134140
mro_subclasses(PyTypeObject *type, PyObject* temp)
135141
{
@@ -2031,6 +2037,10 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
20312037
type->tp_name);
20322038
return -1;
20332039
}
2040+
/* XXX Example of how I expect this to be used...
2041+
if (update_subclasses(type, name, invalidate_cache, NULL) < 0)
2042+
return -1;
2043+
*/
20342044
if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0)
20352045
return -1;
20362046
return update_slot(type, name);
@@ -4993,7 +5003,7 @@ resolve_slotdups(PyTypeObject *type, PyObject *name)
49935003
return res;
49945004
}
49955005

4996-
/* Common code for update_these_slots() and fixup_slot_dispatchers(). This
5006+
/* Common code for update_slots_callback() and fixup_slot_dispatchers(). This
49975007
does some incredibly complex thinking and then sticks something into the
49985008
slot. (It sees if the adjacent slotdefs for the same slot have conflicting
49995009
interests, and then stores a generic wrapper or a specific function into
@@ -5068,51 +5078,15 @@ update_one_slot(PyTypeObject *type, slotdef *p)
50685078
return p;
50695079
}
50705080

5071-
static int recurse_down_subclasses(PyTypeObject *type, slotdef **pp,
5072-
PyObject *name);
5073-
5074-
/* In the type, update the slots whose slotdefs are gathered in the pp0 array,
5075-
and then do the same for all this type's subtypes. */
5081+
/* In the type, update the slots whose slotdefs are gathered in the pp array.
5082+
This is a callback for update_subclasses(). */
50765083
static int
5077-
update_these_slots(PyTypeObject *type, slotdef **pp0, PyObject *name)
5084+
update_slots_callback(PyTypeObject *type, void *data)
50785085
{
5079-
slotdef **pp;
5086+
slotdef **pp = (slotdef **)data;
50805087

5081-
for (pp = pp0; *pp; pp++)
5088+
for (; *pp; pp++)
50825089
update_one_slot(type, *pp);
5083-
return recurse_down_subclasses(type, pp0, name);
5084-
}
5085-
5086-
/* Update the slots whose slotdefs are gathered in the pp array in all (direct
5087-
or indirect) subclasses of type. */
5088-
static int
5089-
recurse_down_subclasses(PyTypeObject *type, slotdef **pp, PyObject *name)
5090-
{
5091-
PyTypeObject *subclass;
5092-
PyObject *ref, *subclasses, *dict;
5093-
int i, n;
5094-
5095-
subclasses = type->tp_subclasses;
5096-
if (subclasses == NULL)
5097-
return 0;
5098-
assert(PyList_Check(subclasses));
5099-
n = PyList_GET_SIZE(subclasses);
5100-
for (i = 0; i < n; i++) {
5101-
ref = PyList_GET_ITEM(subclasses, i);
5102-
assert(PyWeakref_CheckRef(ref));
5103-
subclass = (PyTypeObject *)PyWeakref_GET_OBJECT(ref);
5104-
assert(subclass != NULL);
5105-
if ((PyObject *)subclass == Py_None)
5106-
continue;
5107-
assert(PyType_Check(subclass));
5108-
/* Avoid recursing down into unaffected classes */
5109-
dict = subclass->tp_dict;
5110-
if (dict != NULL && PyDict_Check(dict) &&
5111-
PyDict_GetItem(dict, name) != NULL)
5112-
continue;
5113-
if (update_these_slots(subclass, pp, name) < 0)
5114-
return -1;
5115-
}
51165090
return 0;
51175091
}
51185092

@@ -5175,7 +5149,8 @@ update_slot(PyTypeObject *type, PyObject *name)
51755149
}
51765150
if (ptrs[0] == NULL)
51775151
return 0; /* Not an attribute that affects any slots */
5178-
return update_these_slots(type, ptrs, name);
5152+
return update_subclasses(type, name,
5153+
update_slots_callback, (void *)ptrs);
51795154
}
51805155

51815156
/* Store the proper functions in the slot dispatches at class (type)
@@ -5203,6 +5178,51 @@ update_all_slots(PyTypeObject* type)
52035178
}
52045179
}
52055180

5181+
/* recurse_down_subclasses() and update_subclasses() are mutually
5182+
recursive functions to call a callback for all subclasses,
5183+
but refraining from recursing into subclasses that define 'name'. */
5184+
5185+
static int
5186+
update_subclasses(PyTypeObject *type, PyObject *name,
5187+
update_callback callback, void *data)
5188+
{
5189+
if (callback(type, data) < 0)
5190+
return -1;
5191+
return recurse_down_subclasses(type, name, callback, data);
5192+
}
5193+
5194+
static int
5195+
recurse_down_subclasses(PyTypeObject *type, PyObject *name,
5196+
update_callback callback, void *data)
5197+
{
5198+
PyTypeObject *subclass;
5199+
PyObject *ref, *subclasses, *dict;
5200+
int i, n;
5201+
5202+
subclasses = type->tp_subclasses;
5203+
if (subclasses == NULL)
5204+
return 0;
5205+
assert(PyList_Check(subclasses));
5206+
n = PyList_GET_SIZE(subclasses);
5207+
for (i = 0; i < n; i++) {
5208+
ref = PyList_GET_ITEM(subclasses, i);
5209+
assert(PyWeakref_CheckRef(ref));
5210+
subclass = (PyTypeObject *)PyWeakref_GET_OBJECT(ref);
5211+
assert(subclass != NULL);
5212+
if ((PyObject *)subclass == Py_None)
5213+
continue;
5214+
assert(PyType_Check(subclass));
5215+
/* Avoid recursing down into unaffected classes */
5216+
dict = subclass->tp_dict;
5217+
if (dict != NULL && PyDict_Check(dict) &&
5218+
PyDict_GetItem(dict, name) != NULL)
5219+
continue;
5220+
if (update_subclasses(subclass, name, callback, data) < 0)
5221+
return -1;
5222+
}
5223+
return 0;
5224+
}
5225+
52065226
/* This function is called by PyType_Ready() to populate the type's
52075227
dictionary with method descriptors for function slots. For each
52085228
function slot (like tp_repr) that's defined in the type, one or more
@@ -5216,10 +5236,11 @@ update_all_slots(PyTypeObject* type)
52165236
In the latter case, the first slotdef entry encoutered wins. Since
52175237
slotdef entries are sorted by the offset of the slot in the
52185238
PyHeapTypeObject, this gives us some control over disambiguating
5219-
between competing slots: the members of PyHeapTypeObject are listed from most
5220-
general to least general, so the most general slot is preferred. In
5221-
particular, because as_mapping comes before as_sequence, for a type
5222-
that defines both mp_subscript and sq_item, mp_subscript wins.
5239+
between competing slots: the members of PyHeapTypeObject are listed
5240+
from most general to least general, so the most general slot is
5241+
preferred. In particular, because as_mapping comes before as_sequence,
5242+
for a type that defines both mp_subscript and sq_item, mp_subscript
5243+
wins.
52235244
52245245
This only adds new descriptors and doesn't overwrite entries in
52255246
tp_dict that were previously defined. The descriptors contain a

0 commit comments

Comments
 (0)