From 7b9144b2ee0b34a0f4569b0e6277b12d1066c6be Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 9 Oct 2001 19:39:46 +0000 Subject: Halfway checkin. This is still messy, but it's beginning to address the problem that slots weren't inherited properly. override_slots() no longer exists; in its place comes fixup_slot_dispatchers() which does more and different work and is table-based. (Eventually I want this table also to replace all the little tab_foo tables.) Also add a wrapper for __delslice__; this required a change in test_descrtut.py. --- Lib/test/test_descrtut.py | 1 + Objects/typeobject.c | 441 +++++++++++++++++++++++++++++++--------------- 2 files changed, 302 insertions(+), 140 deletions(-) diff --git a/Lib/test/test_descrtut.py b/Lib/test/test_descrtut.py index 80e7f05..2e019aa 100644 --- a/Lib/test/test_descrtut.py +++ b/Lib/test/test_descrtut.py @@ -190,6 +190,7 @@ Instead, you can get the same information from the list type: '__contains__', '__delattr__', '__delitem__', + '__delslice__', '__eq__', '__ge__', '__getattribute__', diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 65267d3..63843c5 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -299,7 +299,6 @@ subtype_dealloc(PyObject *self) } } -staticforward void override_slots(PyTypeObject *type, PyObject *dict); staticforward PyTypeObject *solid_base(PyTypeObject *type); typedef struct { @@ -677,6 +676,8 @@ solid_base(PyTypeObject *type) staticforward void object_dealloc(PyObject *); staticforward int object_init(PyObject *, PyObject *, PyObject *); +staticforward int update_slot(PyTypeObject *, PyObject *, PyObject *); +staticforward void fixup_slot_dispatchers(PyTypeObject *); static PyObject * subtype_dict(PyObject *obj, void *context) @@ -1011,9 +1012,8 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) return NULL; } - /* Override slots that deserve it */ - if (!PyType_HasFeature(type, Py_TPFLAGS_DYNAMICTYPE)) - override_slots(type, type->tp_defined); + /* Put the proper slots in place */ + fixup_slot_dispatchers(type); return (PyObject *)type; } @@ -1104,9 +1104,12 @@ type_getattro(PyTypeObject *type, PyObject *name) static int type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) { - if (type->tp_flags & Py_TPFLAGS_DYNAMICTYPE) - return PyObject_GenericSetAttr((PyObject *)type, name, value); - PyErr_SetString(PyExc_TypeError, "can't set type attributes"); + if (type->tp_flags & Py_TPFLAGS_DYNAMICTYPE) { + if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0) + return -1; + return update_slot(type, name, value); + } + PyErr_SetString(PyExc_TypeError, "can't set static type attributes"); return -1; } @@ -1857,11 +1860,7 @@ PyType_Ready(PyTypeObject *type) inherit_special(type, type->tp_base); /* Initialize tp_dict properly */ - if (PyType_HasFeature(type, Py_TPFLAGS_DYNAMICTYPE)) { - /* For a dynamic type, all slots are overridden */ - override_slots(type, NULL); - } - else { + if (!PyType_HasFeature(type, Py_TPFLAGS_DYNAMICTYPE)) { /* For a static type, tp_dict is the consolidation of the tp_defined of its bases in MRO. */ Py_DECREF(type->tp_dict); @@ -1881,6 +1880,18 @@ PyType_Ready(PyTypeObject *type) inherit_slots(type, base); } } + else { + /* For a dynamic type, we simply inherit the base slots. */ + bases = type->tp_mro; + assert(bases != NULL); + assert(PyTuple_Check(bases)); + n = PyTuple_GET_SIZE(bases); + for (i = 1; i < n; i++) { + base = (PyTypeObject *)PyTuple_GET_ITEM(bases, i); + assert(PyType_Check(base)); + inherit_slots(type, base); + } + } /* Some more special stuff */ base = type->tp_base; @@ -1987,7 +1998,7 @@ wrap_binaryfunc_l(PyObject *self, PyObject *args, void *wrapped) if (!PyArg_ParseTuple(args, "O", &other)) return NULL; if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) && - self->ob_type != other->ob_type) { + !PyType_IsSubtype(other->ob_type, self->ob_type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -2003,7 +2014,7 @@ wrap_binaryfunc_r(PyObject *self, PyObject *args, void *wrapped) if (!PyArg_ParseTuple(args, "O", &other)) return NULL; if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) && - self->ob_type != other->ob_type) { + !PyType_IsSubtype(other->ob_type, self->ob_type)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -2332,9 +2343,26 @@ wrap_intintobjargproc(PyObject *self, PyObject *args, void *wrapped) return Py_None; } +static PyObject * +wrap_delslice(PyObject *self, PyObject *args, void *wrapped) +{ + intintobjargproc func = (intintobjargproc)wrapped; + int i, j, res; + + if (!PyArg_ParseTuple(args, "ii", &i, &j)) + return NULL; + res = (*func)(self, i, j, NULL); + if (res == -1 && PyErr_Occurred()) + return NULL; + Py_INCREF(Py_None); + return Py_None; +} + static struct wrapperbase tab_setslice[] = { {"__setslice__", (wrapperfunc)wrap_intintobjargproc, "x.__setslice__(i, j, y) <==> x[i:j]=y"}, + {"__delslice__", (wrapperfunc)wrap_delslice, + "x.__delslice__(i, j) <==> del x[i:j]"}, {0} }; @@ -2609,7 +2637,7 @@ static struct wrapperbase tab_descr_get[] = { }; static PyObject * -wrap_descrsetfunc(PyObject *self, PyObject *args, void *wrapped) +wrap_descr_set(PyObject *self, PyObject *args, void *wrapped) { descrsetfunc func = (descrsetfunc)wrapped; PyObject *obj, *value; @@ -2625,7 +2653,7 @@ wrap_descrsetfunc(PyObject *self, PyObject *args, void *wrapped) } static struct wrapperbase tab_descr_set[] = { - {"__set__", (wrapperfunc)wrap_descrsetfunc, + {"__set__", (wrapperfunc)wrap_descr_set, "descr.__set__(obj, value)"}, {0} }; @@ -3638,133 +3666,266 @@ slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return x; } -/* This is called at the very end of type_new() (even after - PyType_Ready()) to complete the initialization of dynamic types. - The dict argument is the dictionary argument passed to type_new(), - which is the local namespace of the class statement, in other - words, it contains the methods. For each special method (like - __repr__) defined in the dictionary, the corresponding function - slot in the type object (like tp_repr) is set to a special function - whose name is 'slot_' followed by the slot name and whose signature - is whatever is required for that slot. These slot functions look - up the corresponding method in the type's dictionary and call it. - The slot functions have to take care of the various peculiarities - of the mapping between slots and special methods, such as mapping - one slot to multiple methods (tp_richcompare <--> __le__, __lt__ - etc.) or mapping multiple slots to a single method (sq_item, - mp_subscript <--> __getitem__). */ -static void -override_slots(PyTypeObject *type, PyObject *dict) -{ - PySequenceMethods *sq = type->tp_as_sequence; - PyMappingMethods *mp = type->tp_as_mapping; - PyNumberMethods *nb = type->tp_as_number; - -#define SQSLOT(OPNAME, SLOTNAME, FUNCNAME) \ - if (dict == NULL || PyDict_GetItemString(dict, OPNAME)) { \ - sq->SLOTNAME = FUNCNAME; \ - } - -#define MPSLOT(OPNAME, SLOTNAME, FUNCNAME) \ - if (dict == NULL || PyDict_GetItemString(dict, OPNAME)) { \ - mp->SLOTNAME = FUNCNAME; \ - } - -#define NBSLOT(OPNAME, SLOTNAME, FUNCNAME) \ - if (dict == NULL || PyDict_GetItemString(dict, OPNAME)) { \ - nb->SLOTNAME = FUNCNAME; \ - } - -#define TPSLOT(OPNAME, SLOTNAME, FUNCNAME) \ - if (dict == NULL || PyDict_GetItemString(dict, OPNAME)) { \ - type->SLOTNAME = FUNCNAME; \ - } - - SQSLOT("__len__", sq_length, slot_sq_length); - SQSLOT("__add__", sq_concat, slot_sq_concat); - SQSLOT("__mul__", sq_repeat, slot_sq_repeat); - SQSLOT("__getitem__", sq_item, slot_sq_item); - SQSLOT("__getslice__", sq_slice, slot_sq_slice); - SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item); - SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item); - SQSLOT("__setslice__", sq_ass_slice, slot_sq_ass_slice); - SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice); - SQSLOT("__contains__", sq_contains, slot_sq_contains); - SQSLOT("__iadd__", sq_inplace_concat, slot_sq_inplace_concat); - SQSLOT("__imul__", sq_inplace_repeat, slot_sq_inplace_repeat); - - MPSLOT("__len__", mp_length, slot_mp_length); - MPSLOT("__getitem__", mp_subscript, slot_mp_subscript); - MPSLOT("__setitem__", mp_ass_subscript, slot_mp_ass_subscript); - MPSLOT("__delitem__", mp_ass_subscript, slot_mp_ass_subscript); - - NBSLOT("__add__", nb_add, slot_nb_add); - NBSLOT("__sub__", nb_subtract, slot_nb_subtract); - NBSLOT("__mul__", nb_multiply, slot_nb_multiply); - NBSLOT("__div__", nb_divide, slot_nb_divide); - NBSLOT("__mod__", nb_remainder, slot_nb_remainder); - NBSLOT("__divmod__", nb_divmod, slot_nb_divmod); - NBSLOT("__pow__", nb_power, slot_nb_power); - NBSLOT("__neg__", nb_negative, slot_nb_negative); - NBSLOT("__pos__", nb_positive, slot_nb_positive); - NBSLOT("__abs__", nb_absolute, slot_nb_absolute); - NBSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero); - NBSLOT("__invert__", nb_invert, slot_nb_invert); - NBSLOT("__lshift__", nb_lshift, slot_nb_lshift); - NBSLOT("__rshift__", nb_rshift, slot_nb_rshift); - NBSLOT("__and__", nb_and, slot_nb_and); - NBSLOT("__xor__", nb_xor, slot_nb_xor); - NBSLOT("__or__", nb_or, slot_nb_or); - NBSLOT("__coerce__", nb_coerce, slot_nb_coerce); - NBSLOT("__int__", nb_int, slot_nb_int); - NBSLOT("__long__", nb_long, slot_nb_long); - NBSLOT("__float__", nb_float, slot_nb_float); - NBSLOT("__oct__", nb_oct, slot_nb_oct); - NBSLOT("__hex__", nb_hex, slot_nb_hex); - NBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add); - NBSLOT("__isub__", nb_inplace_subtract, slot_nb_inplace_subtract); - NBSLOT("__imul__", nb_inplace_multiply, slot_nb_inplace_multiply); - NBSLOT("__idiv__", nb_inplace_divide, slot_nb_inplace_divide); - NBSLOT("__imod__", nb_inplace_remainder, slot_nb_inplace_remainder); - NBSLOT("__ipow__", nb_inplace_power, slot_nb_inplace_power); - NBSLOT("__ilshift__", nb_inplace_lshift, slot_nb_inplace_lshift); - NBSLOT("__irshift__", nb_inplace_rshift, slot_nb_inplace_rshift); - NBSLOT("__iand__", nb_inplace_and, slot_nb_inplace_and); - NBSLOT("__ixor__", nb_inplace_xor, slot_nb_inplace_xor); - NBSLOT("__ior__", nb_inplace_or, slot_nb_inplace_or); - NBSLOT("__floordiv__", nb_floor_divide, slot_nb_floor_divide); - NBSLOT("__truediv__", nb_true_divide, slot_nb_true_divide); +/* Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper + functions. The offsets here are relative to the 'etype' structure, which + incorporates the additional structures used for numbers, sequences and + mappings. Note that multiple names may map to the same slot (e.g. __eq__, + __ne__ etc. all map to tp_richcompare) and one name may map to multiple + slots (e.g. __str__ affects tp_str as well as tp_repr). */ + +typedef struct { + char *name; + int offset; + void *function; + wrapperfunc wrapper; +} slotdef; + +#undef TPSLOT +#undef ETSLOT +#undef SQSLOT +#undef MPSLOT +#undef NBSLOT +#undef BINSLOT +#undef RBINSLOT + +#define TPSLOT(NAME, SLOT, FUNCTION, WRAPPER) \ + {NAME, offsetof(PyTypeObject, SLOT), FUNCTION, WRAPPER} +#define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER) \ + {NAME, offsetof(etype, SLOT), FUNCTION, WRAPPER} +#define SQSLOT(NAME, SLOT, FUNCTION, WRAPPER) \ + ETSLOT(NAME, as_sequence.SLOT, FUNCTION, WRAPPER) +#define MPSLOT(NAME, SLOT, FUNCTION, WRAPPER) \ + ETSLOT(NAME, as_mapping.SLOT, FUNCTION, WRAPPER) +#define NBSLOT(NAME, SLOT, FUNCTION, WRAPPER) \ + ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER) +#define BINSLOT(NAME, SLOT, FUNCTION) \ + ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l) +#define RBINSLOT(NAME, SLOT, FUNCTION) \ + ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r) + +static slotdef slotdefs[] = { + SQSLOT("__len__", sq_length, slot_sq_length, wrap_inquiry), + SQSLOT("__add__", sq_concat, slot_sq_concat, wrap_binaryfunc), + SQSLOT("__mul__", sq_repeat, slot_sq_repeat, wrap_intargfunc), + SQSLOT("__rmul__", sq_repeat, slot_sq_repeat, wrap_intargfunc), + SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item), + SQSLOT("__getslice__", sq_slice, slot_sq_slice, wrap_intintargfunc), + SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem), + SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_delitem), + SQSLOT("__setslice__", sq_ass_slice, slot_sq_ass_slice, + wrap_intintobjargproc), + SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice, wrap_delslice), + SQSLOT("__contains__", sq_contains, slot_sq_contains, wrap_objobjproc), + SQSLOT("__iadd__", sq_inplace_concat, slot_sq_inplace_concat, + wrap_binaryfunc), + SQSLOT("__imul__", sq_inplace_repeat, slot_sq_inplace_repeat, + wrap_intargfunc), + + MPSLOT("__len__", mp_length, slot_mp_length, wrap_inquiry), + MPSLOT("__getitem__", mp_subscript, slot_mp_subscript, wrap_sq_item), + MPSLOT("__setitem__", mp_ass_subscript, slot_mp_ass_subscript, + wrap_objobjargproc), + MPSLOT("__delitem__", mp_ass_subscript, slot_mp_ass_subscript, + wrap_delitem), + + BINSLOT("__add__", nb_add, slot_nb_add), + RBINSLOT("__radd__", nb_add, slot_nb_add), + BINSLOT("__sub__", nb_subtract, slot_nb_subtract), + RBINSLOT("__rsub__", nb_subtract, slot_nb_subtract), + BINSLOT("__mul__", nb_multiply, slot_nb_multiply), + RBINSLOT("__rmul__", nb_multiply, slot_nb_multiply), + BINSLOT("__div__", nb_divide, slot_nb_divide), + RBINSLOT("__rdiv__", nb_divide, slot_nb_divide), + BINSLOT("__mod__", nb_remainder, slot_nb_remainder), + RBINSLOT("__rmod__", nb_remainder, slot_nb_remainder), + BINSLOT("__divmod__", nb_divmod, slot_nb_divmod), + RBINSLOT("__rdivmod__", nb_divmod, slot_nb_divmod), + NBSLOT("__pow__", nb_power, slot_nb_power, wrap_ternaryfunc), + NBSLOT("__rpow__", nb_power, slot_nb_power, wrap_ternaryfunc_r), + NBSLOT("__neg__", nb_negative, slot_nb_negative, wrap_unaryfunc), + NBSLOT("__pos__", nb_positive, slot_nb_positive, wrap_unaryfunc), + NBSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc), + NBSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero, wrap_unaryfunc), + NBSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc), + BINSLOT("__lshift__", nb_lshift, slot_nb_lshift), + RBINSLOT("__rlshift__", nb_lshift, slot_nb_lshift), + BINSLOT("__rshift__", nb_rshift, slot_nb_rshift), + RBINSLOT("__rrshift__", nb_rshift, slot_nb_rshift), + BINSLOT("__and__", nb_and, slot_nb_and), + RBINSLOT("__rand__", nb_and, slot_nb_and), + BINSLOT("__xor__", nb_xor, slot_nb_xor), + RBINSLOT("__rxor__", nb_xor, slot_nb_xor), + BINSLOT("__or__", nb_or, slot_nb_or), + RBINSLOT("__ror__", nb_or, slot_nb_or), + NBSLOT("__coerce__", nb_coerce, slot_nb_coerce, wrap_coercefunc), + NBSLOT("__int__", nb_int, slot_nb_int, wrap_unaryfunc), + NBSLOT("__long__", nb_long, slot_nb_long, wrap_unaryfunc), + NBSLOT("__float__", nb_float, slot_nb_float, wrap_unaryfunc), + NBSLOT("__oct__", nb_oct, slot_nb_oct, wrap_unaryfunc), + NBSLOT("__hex__", nb_hex, slot_nb_hex, wrap_unaryfunc), + NBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add, + wrap_binaryfunc), + NBSLOT("__isub__", nb_inplace_subtract, slot_nb_inplace_subtract, + wrap_binaryfunc), + NBSLOT("__imul__", nb_inplace_multiply, slot_nb_inplace_multiply, + wrap_binaryfunc), + NBSLOT("__idiv__", nb_inplace_divide, slot_nb_inplace_divide, + wrap_binaryfunc), + NBSLOT("__imod__", nb_inplace_remainder, slot_nb_inplace_remainder, + wrap_binaryfunc), + NBSLOT("__ipow__", nb_inplace_power, slot_nb_inplace_power, + wrap_ternaryfunc), + NBSLOT("__ilshift__", nb_inplace_lshift, slot_nb_inplace_lshift, + wrap_binaryfunc), + NBSLOT("__irshift__", nb_inplace_rshift, slot_nb_inplace_rshift, + wrap_binaryfunc), + NBSLOT("__iand__", nb_inplace_and, slot_nb_inplace_and, + wrap_binaryfunc), + NBSLOT("__ixor__", nb_inplace_xor, slot_nb_inplace_xor, + wrap_binaryfunc), + NBSLOT("__ior__", nb_inplace_or, slot_nb_inplace_or, + wrap_binaryfunc), + BINSLOT("__floordiv__", nb_floor_divide, slot_nb_floor_divide), + RBINSLOT("__rfloordiv__", nb_floor_divide, slot_nb_floor_divide), + BINSLOT("__truediv__", nb_true_divide, slot_nb_true_divide), + RBINSLOT("__rtruediv__", nb_true_divide, slot_nb_true_divide), NBSLOT("__ifloordiv__", nb_inplace_floor_divide, - slot_nb_inplace_floor_divide); + slot_nb_inplace_floor_divide, wrap_binaryfunc), NBSLOT("__itruediv__", nb_inplace_true_divide, - slot_nb_inplace_true_divide); - - if (dict == NULL || - PyDict_GetItemString(dict, "__str__") || - PyDict_GetItemString(dict, "__repr__")) - type->tp_print = NULL; - - TPSLOT("__cmp__", tp_compare, _PyObject_SlotCompare); - TPSLOT("__repr__", tp_repr, slot_tp_repr); - TPSLOT("__hash__", tp_hash, slot_tp_hash); - TPSLOT("__call__", tp_call, slot_tp_call); - TPSLOT("__str__", tp_str, slot_tp_str); - TPSLOT("__getattribute__", tp_getattro, slot_tp_getattro); - TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook); - TPSLOT("__setattr__", tp_setattro, slot_tp_setattro); - TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare); - TPSLOT("__le__", tp_richcompare, slot_tp_richcompare); - TPSLOT("__eq__", tp_richcompare, slot_tp_richcompare); - TPSLOT("__ne__", tp_richcompare, slot_tp_richcompare); - TPSLOT("__gt__", tp_richcompare, slot_tp_richcompare); - TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare); - TPSLOT("__iter__", tp_iter, slot_tp_iter); - TPSLOT("next", tp_iternext, slot_tp_iternext); - TPSLOT("__get__", tp_descr_get, slot_tp_descr_get); - TPSLOT("__set__", tp_descr_set, slot_tp_descr_set); - TPSLOT("__init__", tp_init, slot_tp_init); - TPSLOT("__new__", tp_new, slot_tp_new); + slot_nb_inplace_true_divide, wrap_binaryfunc), + + TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc), + TPSLOT("__str__", tp_print, NULL, NULL), + TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc), + TPSLOT("__repr__", tp_print, NULL, NULL), + TPSLOT("__cmp__", tp_compare, _PyObject_SlotCompare, wrap_cmpfunc), + TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc), + TPSLOT("__call__", tp_call, slot_tp_call, wrap_call), + TPSLOT("__getattribute__", tp_getattro, slot_tp_getattro, + wrap_binaryfunc), + TPSLOT("__getattribute__", tp_getattr, NULL, NULL), + TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL), + TPSLOT("__getattr__", tp_getattr, NULL, NULL), + TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr), + TPSLOT("__setattr__", tp_setattr, NULL, NULL), + TPSLOT("__delattr__", tp_setattro, slot_tp_setattro, wrap_delattr), + TPSLOT("__delattr__", tp_setattr, NULL, NULL), + TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare, richcmp_lt), + TPSLOT("__le__", tp_richcompare, slot_tp_richcompare, richcmp_le), + TPSLOT("__eq__", tp_richcompare, slot_tp_richcompare, richcmp_eq), + TPSLOT("__ne__", tp_richcompare, slot_tp_richcompare, richcmp_ne), + TPSLOT("__gt__", tp_richcompare, slot_tp_richcompare, richcmp_gt), + TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare, richcmp_ge), + TPSLOT("__iter__", tp_iter, slot_tp_iter, wrap_unaryfunc), + TPSLOT("next", tp_iternext, slot_tp_iternext, wrap_next), + TPSLOT("__get__", tp_descr_get, slot_tp_descr_get, wrap_descr_get), + TPSLOT("__set__", tp_descr_set, slot_tp_descr_set, wrap_descr_set), + TPSLOT("__init__", tp_init, slot_tp_init, wrap_init), + TPSLOT("__new__", tp_new, slot_tp_new, NULL), + {NULL} +}; + +static int +update_slot(PyTypeObject *type, PyObject *name, PyObject *value) +{ + char *s; + int n; + slotdef *p; + void **ptr; + + assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE); + if (value == NULL) + return 0; /* Can't unset a slot */ + s = PyString_AsString(name); + n = PyString_Size(name); + if (s == NULL || n < 0) { + /* Shouldn't happen, but can't be bothered */ + PyErr_Clear(); + return 0; + } + if (!(s[0] == '_' && s[1] == '_' && s[n-1] == '_' && s[n-2] == '_')) + return 0; + for (p = slotdefs; p->name; p++) { + if (!strcmp(p->name, s)) { + ptr = (void **) ((char *)type + p->offset); + *ptr = p->function; + } + } + return 0; +} + +static void ** +slotptr(PyTypeObject *type, int offset) +{ + char *ptr; + + assert(offset >= 0); + assert(offset < offsetof(etype, as_buffer)); + if (offset >= offsetof(etype, as_mapping)) { + ptr = (void *)type->tp_as_mapping; + offset -= offsetof(etype, as_mapping); + } + else if (offset >= offsetof(etype, as_sequence)) { + ptr = (void *)type->tp_as_sequence; + offset -= offsetof(etype, as_sequence); + } + else if (offset >= offsetof(etype, as_number)) { + ptr = (void *)type->tp_as_number; + offset -= offsetof(etype, as_number); + } + else { + ptr = (void *)type; + } + if (ptr != NULL) + ptr += offset; + return (void **)ptr; +} + +static void +fixup_slot_dispatchers(PyTypeObject *type) +{ + slotdef *p; + PyObject *mro, *descr; + PyTypeObject *base; + PyWrapperDescrObject *d; + int i, n; + void **ptr; + + for (p = slotdefs; p->name; p++) { + ptr = slotptr(type, p->offset); + if (ptr) + *ptr = NULL; + } + mro = type->tp_mro; + assert(PyTuple_Check(mro)); + n = PyTuple_GET_SIZE(mro); + for (p = slotdefs; p->name; p++) { + for (i = 0; i < n; i++) { + base = (PyTypeObject *)PyTuple_GET_ITEM(mro, i); + assert(PyType_Check(base)); + descr = PyDict_GetItemString( + base->tp_defined, p->name); + if (descr == NULL) + continue; + ptr = slotptr(type, p->offset); + if (ptr == NULL) + continue; + if (descr->ob_type == &PyWrapperDescr_Type) { + d = (PyWrapperDescrObject *)descr; + if (d->d_base->wrapper == p->wrapper) { + if (*ptr == NULL) { + *ptr = d->d_wrapped; + continue; + } + if (p->wrapper == wrap_binaryfunc_r) + continue; + } + } + *ptr = p->function; + break; + } + } } -- cgit v0.12