@@ -7197,8 +7197,9 @@ resolve_slotdups(PyTypeObject *type, PyObject *name)
7197
7197
* pp = NULL ;
7198
7198
}
7199
7199
7200
- /* Look in all matching slots of the type; if exactly one of these has
7201
- a filled-in slot, return its value. Otherwise return NULL. */
7200
+ /* Look in all slots of the type matching the name. If exactly one of these
7201
+ has a filled-in slot, return a pointer to that slot.
7202
+ Otherwise, return NULL. */
7202
7203
res = NULL ;
7203
7204
for (pp = ptrs ; * pp ; pp ++ ) {
7204
7205
ptr = slotptr (type , (* pp )-> offset );
@@ -7211,12 +7212,61 @@ resolve_slotdups(PyTypeObject *type, PyObject *name)
7211
7212
return res ;
7212
7213
}
7213
7214
7214
- /* Common code for update_slots_callback() and fixup_slot_dispatchers(). This
7215
- does some incredibly complex thinking and then sticks something into the
7216
- slot. (It sees if the adjacent slotdefs for the same slot have conflicting
7217
- interests, and then stores a generic wrapper or a specific function into
7218
- the slot.) Return a pointer to the next slotdef with a different offset,
7219
- because that's convenient for fixup_slot_dispatchers(). */
7215
+
7216
+ /* Common code for update_slots_callback() and fixup_slot_dispatchers().
7217
+ *
7218
+ * This is meant to set a "slot" like type->tp_repr or
7219
+ * type->tp_as_sequence->sq_concat by looking up special methods like
7220
+ * __repr__ or __add__. The opposite (adding special methods from slots) is
7221
+ * done by add_operators(), called from PyType_Ready(). Since update_one_slot()
7222
+ * calls PyType_Ready() if needed, the special methods are already in place.
7223
+ *
7224
+ * The special methods corresponding to each slot are defined in the "slotdef"
7225
+ * array. Note that one slot may correspond to multiple special methods and vice
7226
+ * versa. For example, tp_richcompare uses 6 methods __lt__, ..., __ge__ and
7227
+ * tp_as_number->nb_add uses __add__ and __radd__. In the other direction,
7228
+ * __add__ is used by the number and sequence protocols and __getitem__ by the
7229
+ * sequence and mapping protocols. This causes a lot of complications.
7230
+ *
7231
+ * In detail, update_one_slot() does the following:
7232
+ *
7233
+ * First of all, if the slot in question does not exist, return immediately.
7234
+ * This can happen for example if it's tp_as_number->nb_add but tp_as_number
7235
+ * is NULL.
7236
+ *
7237
+ * For the given slot, we loop over all the special methods with a name
7238
+ * corresponding to that slot (for example, for tp_descr_set, this would be
7239
+ * __set__ and __delete__) and we look up these names in the MRO of the type.
7240
+ * If we don't find any special method, the slot is set to NULL (regardless of
7241
+ * what was in the slot before).
7242
+ *
7243
+ * Suppose that we find exactly one special method. If it's a wrapper_descriptor
7244
+ * (i.e. a special method calling a slot, for example str.__repr__ which calls
7245
+ * the tp_repr for the 'str' class) with the correct name ("__repr__" for
7246
+ * tp_repr), for the right class, calling the right wrapper C function (like
7247
+ * wrap_unaryfunc for tp_repr), then the slot is set to the slot that the
7248
+ * wrapper_descriptor originally wrapped. For example, a class inheriting
7249
+ * from 'str' and not redefining __repr__ will have tp_repr set to the tp_repr
7250
+ * of 'str'.
7251
+ * In all other cases where the special method exists, the slot is set to a
7252
+ * wrapper calling the special method. There is one exception: if the special
7253
+ * method is a wrapper_descriptor with the correct name but the type has
7254
+ * precisely one slot set for that name and that slot is not the one that we
7255
+ * are updating, then NULL is put in the slot (this exception is the only place
7256
+ * in update_one_slot() where the *existing* slots matter).
7257
+ *
7258
+ * When there are multiple special methods for the same slot, the above is
7259
+ * applied for each special method. As long as the results agree, the common
7260
+ * resulting slot is applied. If the results disagree, then a wrapper for
7261
+ * the special methods is installed. This is always safe, but less efficient
7262
+ * because it uses method lookup instead of direct C calls.
7263
+ *
7264
+ * There are some further special cases for specific slots, like supporting
7265
+ * __hash__ = None for tp_hash and special code for tp_new.
7266
+ *
7267
+ * When done, return a pointer to the next slotdef with a different offset,
7268
+ * because that's convenient for fixup_slot_dispatchers(). This function never
7269
+ * sets an exception: if an internal error happens (unlikely), it's ignored. */
7220
7270
static slotdef *
7221
7271
update_one_slot (PyTypeObject * type , slotdef * p )
7222
7272
{
@@ -7241,7 +7291,7 @@ update_one_slot(PyTypeObject *type, slotdef *p)
7241
7291
descr = find_name_in_mro (type , p -> name_strobj , & error );
7242
7292
if (descr == NULL ) {
7243
7293
if (error == -1 ) {
7244
- /* It is unlikely by not impossible that there has been an exception
7294
+ /* It is unlikely but not impossible that there has been an exception
7245
7295
during lookup. Since this function originally expected no errors,
7246
7296
we ignore them here in order to keep up the interface. */
7247
7297
PyErr_Clear ();
0 commit comments