@@ -5658,15 +5658,16 @@ slot_tp_del(PyObject *self)
56585658}
56595659
56605660
5661- /* Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper
5662- functions. The offsets here are relative to the 'PyHeapTypeObject'
5663- structure, which incorporates the additional structures used for numbers,
5664- sequences and mappings.
5665- Note that multiple names may map to the same slot (e.g. __eq__,
5666- __ne__ etc. all map to tp_richcompare) and one name may map to multiple
5667- slots (e.g. __str__ affects tp_str as well as tp_repr). The table is
5668- terminated with an all-zero entry. (This table is further initialized and
5669- sorted in init_slotdefs() below.) */
5661+ /*
5662+ Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper functions.
5663+
5664+ The table is ordered by offsets relative to the 'PyHeapTypeObject' structure,
5665+ which incorporates the additional structures used for numbers, sequences and
5666+ mappings. Note that multiple names may map to the same slot (e.g. __eq__,
5667+ __ne__ etc. all map to tp_richcompare) and one name may map to multiple slots
5668+ (e.g. __str__ affects tp_str as well as tp_repr). The table is terminated with
5669+ an all-zero entry. (This table is further initialized in init_slotdefs().)
5670+ */
56705671
56715672typedef struct wrapperbase slotdef ;
56725673
@@ -5716,43 +5717,53 @@ typedef struct wrapperbase slotdef;
57165717 "x." NAME "(y) <==> " DOC)
57175718
57185719static slotdef slotdefs [] = {
5719- SQSLOT ("__len__" , sq_length , slot_sq_length , wrap_lenfunc ,
5720- "x.__len__() <==> len(x)" ),
5721- /* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL.
5722- The logic in abstract.c always falls back to nb_add/nb_multiply in
5723- this case. Defining both the nb_* and the sq_* slots to call the
5724- user-defined methods has unexpected side-effects, as shown by
5725- test_descr.notimplemented() */
5726- SQSLOT ("__add__" , sq_concat , NULL , wrap_binaryfunc ,
5727- "x.__add__(y) <==> x+y" ),
5728- SQSLOT ("__mul__" , sq_repeat , NULL , wrap_indexargfunc ,
5729- "x.__mul__(n) <==> x*n" ),
5730- SQSLOT ("__rmul__" , sq_repeat , NULL , wrap_indexargfunc ,
5731- "x.__rmul__(n) <==> n*x" ),
5732- SQSLOT ("__getitem__" , sq_item , slot_sq_item , wrap_sq_item ,
5733- "x.__getitem__(y) <==> x[y]" ),
5734- SQSLOT ("__setitem__" , sq_ass_item , slot_sq_ass_item , wrap_sq_setitem ,
5735- "x.__setitem__(i, y) <==> x[i]=y" ),
5736- SQSLOT ("__delitem__" , sq_ass_item , slot_sq_ass_item , wrap_sq_delitem ,
5737- "x.__delitem__(y) <==> del x[y]" ),
5738- SQSLOT ("__contains__" , sq_contains , slot_sq_contains , wrap_objobjproc ,
5739- "x.__contains__(y) <==> y in x" ),
5740- SQSLOT ("__iadd__" , sq_inplace_concat , NULL ,
5741- wrap_binaryfunc , "x.__iadd__(y) <==> x+=y" ),
5742- SQSLOT ("__imul__" , sq_inplace_repeat , NULL ,
5743- wrap_indexargfunc , "x.__imul__(y) <==> x*=y" ),
5744-
5745- MPSLOT ("__len__" , mp_length , slot_mp_length , wrap_lenfunc ,
5746- "x.__len__() <==> len(x)" ),
5747- MPSLOT ("__getitem__" , mp_subscript , slot_mp_subscript ,
5748- wrap_binaryfunc ,
5749- "x.__getitem__(y) <==> x[y]" ),
5750- MPSLOT ("__setitem__" , mp_ass_subscript , slot_mp_ass_subscript ,
5751- wrap_objobjargproc ,
5752- "x.__setitem__(i, y) <==> x[i]=y" ),
5753- MPSLOT ("__delitem__" , mp_ass_subscript , slot_mp_ass_subscript ,
5754- wrap_delitem ,
5755- "x.__delitem__(y) <==> del x[y]" ),
5720+ TPSLOT ("__getattribute__" , tp_getattr , NULL , NULL , "" ),
5721+ TPSLOT ("__getattr__" , tp_getattr , NULL , NULL , "" ),
5722+ TPSLOT ("__setattr__" , tp_setattr , NULL , NULL , "" ),
5723+ TPSLOT ("__delattr__" , tp_setattr , NULL , NULL , "" ),
5724+ TPSLOT ("__repr__" , tp_repr , slot_tp_repr , wrap_unaryfunc ,
5725+ "x.__repr__() <==> repr(x)" ),
5726+ TPSLOT ("__hash__" , tp_hash , slot_tp_hash , wrap_hashfunc ,
5727+ "x.__hash__() <==> hash(x)" ),
5728+ FLSLOT ("__call__" , tp_call , slot_tp_call , (wrapperfunc )wrap_call ,
5729+ "x.__call__(...) <==> x(...)" , PyWrapperFlag_KEYWORDS ),
5730+ TPSLOT ("__str__" , tp_str , slot_tp_str , wrap_unaryfunc ,
5731+ "x.__str__() <==> str(x)" ),
5732+ TPSLOT ("__getattribute__" , tp_getattro , slot_tp_getattr_hook ,
5733+ wrap_binaryfunc , "x.__getattribute__('name') <==> x.name" ),
5734+ TPSLOT ("__getattr__" , tp_getattro , slot_tp_getattr_hook , NULL , "" ),
5735+ TPSLOT ("__setattr__" , tp_setattro , slot_tp_setattro , wrap_setattr ,
5736+ "x.__setattr__('name', value) <==> x.name = value" ),
5737+ TPSLOT ("__delattr__" , tp_setattro , slot_tp_setattro , wrap_delattr ,
5738+ "x.__delattr__('name') <==> del x.name" ),
5739+ TPSLOT ("__lt__" , tp_richcompare , slot_tp_richcompare , richcmp_lt ,
5740+ "x.__lt__(y) <==> x<y" ),
5741+ TPSLOT ("__le__" , tp_richcompare , slot_tp_richcompare , richcmp_le ,
5742+ "x.__le__(y) <==> x<=y" ),
5743+ TPSLOT ("__eq__" , tp_richcompare , slot_tp_richcompare , richcmp_eq ,
5744+ "x.__eq__(y) <==> x==y" ),
5745+ TPSLOT ("__ne__" , tp_richcompare , slot_tp_richcompare , richcmp_ne ,
5746+ "x.__ne__(y) <==> x!=y" ),
5747+ TPSLOT ("__gt__" , tp_richcompare , slot_tp_richcompare , richcmp_gt ,
5748+ "x.__gt__(y) <==> x>y" ),
5749+ TPSLOT ("__ge__" , tp_richcompare , slot_tp_richcompare , richcmp_ge ,
5750+ "x.__ge__(y) <==> x>=y" ),
5751+ TPSLOT ("__iter__" , tp_iter , slot_tp_iter , wrap_unaryfunc ,
5752+ "x.__iter__() <==> iter(x)" ),
5753+ TPSLOT ("__next__" , tp_iternext , slot_tp_iternext , wrap_next ,
5754+ "x.__next__() <==> next(x)" ),
5755+ TPSLOT ("__get__" , tp_descr_get , slot_tp_descr_get , wrap_descr_get ,
5756+ "descr.__get__(obj[, type]) -> value" ),
5757+ TPSLOT ("__set__" , tp_descr_set , slot_tp_descr_set , wrap_descr_set ,
5758+ "descr.__set__(obj, value)" ),
5759+ TPSLOT ("__delete__" , tp_descr_set , slot_tp_descr_set ,
5760+ wrap_descr_delete , "descr.__delete__(obj)" ),
5761+ FLSLOT ("__init__" , tp_init , slot_tp_init , (wrapperfunc )wrap_init ,
5762+ "x.__init__(...) initializes x; "
5763+ "see help(type(x)) for signature" ,
5764+ PyWrapperFlag_KEYWORDS ),
5765+ TPSLOT ("__new__" , tp_new , slot_tp_new , NULL , "" ),
5766+ TPSLOT ("__del__" , tp_del , slot_tp_del , NULL , "" ),
57565767
57575768 BINSLOT ("__add__" , nb_add , slot_nb_add ,
57585769 "+" ),
@@ -5799,8 +5810,6 @@ static slotdef slotdefs[] = {
57995810 "int(x)" ),
58005811 UNSLOT ("__float__" , nb_float , slot_nb_float , wrap_unaryfunc ,
58015812 "float(x)" ),
5802- NBSLOT ("__index__" , nb_index , slot_nb_index , wrap_unaryfunc ,
5803- "x[y:z] <==> x[y.__index__():z.__index__()]" ),
58045813 IBSLOT ("__iadd__" , nb_inplace_add , slot_nb_inplace_add ,
58055814 wrap_binaryfunc , "+=" ),
58065815 IBSLOT ("__isub__" , nb_inplace_subtract , slot_nb_inplace_subtract ,
@@ -5829,54 +5838,47 @@ static slotdef slotdefs[] = {
58295838 slot_nb_inplace_floor_divide , wrap_binaryfunc , "//" ),
58305839 IBSLOT ("__itruediv__" , nb_inplace_true_divide ,
58315840 slot_nb_inplace_true_divide , wrap_binaryfunc , "/" ),
5841+ NBSLOT ("__index__" , nb_index , slot_nb_index , wrap_unaryfunc ,
5842+ "x[y:z] <==> x[y.__index__():z.__index__()]" ),
5843+
5844+ MPSLOT ("__len__" , mp_length , slot_mp_length , wrap_lenfunc ,
5845+ "x.__len__() <==> len(x)" ),
5846+ MPSLOT ("__getitem__" , mp_subscript , slot_mp_subscript ,
5847+ wrap_binaryfunc ,
5848+ "x.__getitem__(y) <==> x[y]" ),
5849+ MPSLOT ("__setitem__" , mp_ass_subscript , slot_mp_ass_subscript ,
5850+ wrap_objobjargproc ,
5851+ "x.__setitem__(i, y) <==> x[i]=y" ),
5852+ MPSLOT ("__delitem__" , mp_ass_subscript , slot_mp_ass_subscript ,
5853+ wrap_delitem ,
5854+ "x.__delitem__(y) <==> del x[y]" ),
5855+
5856+ SQSLOT ("__len__" , sq_length , slot_sq_length , wrap_lenfunc ,
5857+ "x.__len__() <==> len(x)" ),
5858+ /* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL.
5859+ The logic in abstract.c always falls back to nb_add/nb_multiply in
5860+ this case. Defining both the nb_* and the sq_* slots to call the
5861+ user-defined methods has unexpected side-effects, as shown by
5862+ test_descr.notimplemented() */
5863+ SQSLOT ("__add__" , sq_concat , NULL , wrap_binaryfunc ,
5864+ "x.__add__(y) <==> x+y" ),
5865+ SQSLOT ("__mul__" , sq_repeat , NULL , wrap_indexargfunc ,
5866+ "x.__mul__(n) <==> x*n" ),
5867+ SQSLOT ("__rmul__" , sq_repeat , NULL , wrap_indexargfunc ,
5868+ "x.__rmul__(n) <==> n*x" ),
5869+ SQSLOT ("__getitem__" , sq_item , slot_sq_item , wrap_sq_item ,
5870+ "x.__getitem__(y) <==> x[y]" ),
5871+ SQSLOT ("__setitem__" , sq_ass_item , slot_sq_ass_item , wrap_sq_setitem ,
5872+ "x.__setitem__(i, y) <==> x[i]=y" ),
5873+ SQSLOT ("__delitem__" , sq_ass_item , slot_sq_ass_item , wrap_sq_delitem ,
5874+ "x.__delitem__(y) <==> del x[y]" ),
5875+ SQSLOT ("__contains__" , sq_contains , slot_sq_contains , wrap_objobjproc ,
5876+ "x.__contains__(y) <==> y in x" ),
5877+ SQSLOT ("__iadd__" , sq_inplace_concat , NULL ,
5878+ wrap_binaryfunc , "x.__iadd__(y) <==> x+=y" ),
5879+ SQSLOT ("__imul__" , sq_inplace_repeat , NULL ,
5880+ wrap_indexargfunc , "x.__imul__(y) <==> x*=y" ),
58325881
5833- TPSLOT ("__str__" , tp_str , slot_tp_str , wrap_unaryfunc ,
5834- "x.__str__() <==> str(x)" ),
5835- TPSLOT ("__repr__" , tp_repr , slot_tp_repr , wrap_unaryfunc ,
5836- "x.__repr__() <==> repr(x)" ),
5837- TPSLOT ("__hash__" , tp_hash , slot_tp_hash , wrap_hashfunc ,
5838- "x.__hash__() <==> hash(x)" ),
5839- FLSLOT ("__call__" , tp_call , slot_tp_call , (wrapperfunc )wrap_call ,
5840- "x.__call__(...) <==> x(...)" , PyWrapperFlag_KEYWORDS ),
5841- TPSLOT ("__getattribute__" , tp_getattro , slot_tp_getattr_hook ,
5842- wrap_binaryfunc , "x.__getattribute__('name') <==> x.name" ),
5843- TPSLOT ("__getattribute__" , tp_getattr , NULL , NULL , "" ),
5844- TPSLOT ("__getattr__" , tp_getattro , slot_tp_getattr_hook , NULL , "" ),
5845- TPSLOT ("__getattr__" , tp_getattr , NULL , NULL , "" ),
5846- TPSLOT ("__setattr__" , tp_setattro , slot_tp_setattro , wrap_setattr ,
5847- "x.__setattr__('name', value) <==> x.name = value" ),
5848- TPSLOT ("__setattr__" , tp_setattr , NULL , NULL , "" ),
5849- TPSLOT ("__delattr__" , tp_setattro , slot_tp_setattro , wrap_delattr ,
5850- "x.__delattr__('name') <==> del x.name" ),
5851- TPSLOT ("__delattr__" , tp_setattr , NULL , NULL , "" ),
5852- TPSLOT ("__lt__" , tp_richcompare , slot_tp_richcompare , richcmp_lt ,
5853- "x.__lt__(y) <==> x<y" ),
5854- TPSLOT ("__le__" , tp_richcompare , slot_tp_richcompare , richcmp_le ,
5855- "x.__le__(y) <==> x<=y" ),
5856- TPSLOT ("__eq__" , tp_richcompare , slot_tp_richcompare , richcmp_eq ,
5857- "x.__eq__(y) <==> x==y" ),
5858- TPSLOT ("__ne__" , tp_richcompare , slot_tp_richcompare , richcmp_ne ,
5859- "x.__ne__(y) <==> x!=y" ),
5860- TPSLOT ("__gt__" , tp_richcompare , slot_tp_richcompare , richcmp_gt ,
5861- "x.__gt__(y) <==> x>y" ),
5862- TPSLOT ("__ge__" , tp_richcompare , slot_tp_richcompare , richcmp_ge ,
5863- "x.__ge__(y) <==> x>=y" ),
5864- TPSLOT ("__iter__" , tp_iter , slot_tp_iter , wrap_unaryfunc ,
5865- "x.__iter__() <==> iter(x)" ),
5866- TPSLOT ("__next__" , tp_iternext , slot_tp_iternext , wrap_next ,
5867- "x.__next__() <==> next(x)" ),
5868- TPSLOT ("__get__" , tp_descr_get , slot_tp_descr_get , wrap_descr_get ,
5869- "descr.__get__(obj[, type]) -> value" ),
5870- TPSLOT ("__set__" , tp_descr_set , slot_tp_descr_set , wrap_descr_set ,
5871- "descr.__set__(obj, value)" ),
5872- TPSLOT ("__delete__" , tp_descr_set , slot_tp_descr_set ,
5873- wrap_descr_delete , "descr.__delete__(obj)" ),
5874- FLSLOT ("__init__" , tp_init , slot_tp_init , (wrapperfunc )wrap_init ,
5875- "x.__init__(...) initializes x; "
5876- "see help(type(x)) for signature" ,
5877- PyWrapperFlag_KEYWORDS ),
5878- TPSLOT ("__new__" , tp_new , slot_tp_new , NULL , "" ),
5879- TPSLOT ("__del__" , tp_del , slot_tp_del , NULL , "" ),
58805882 {NULL }
58815883};
58825884
@@ -6057,21 +6059,6 @@ update_slots_callback(PyTypeObject *type, void *data)
60576059 return 0 ;
60586060}
60596061
6060- /* Comparison function for qsort() to compare slotdefs by their offset, and
6061- for equal offset by their address (to force a stable sort). */
6062- static int
6063- slotdef_cmp (const void * aa , const void * bb )
6064- {
6065- const slotdef * a = (const slotdef * )aa , * b = (const slotdef * )bb ;
6066- int c = a -> offset - b -> offset ;
6067- if (c != 0 )
6068- return c ;
6069- else
6070- /* Cannot use a-b, as this gives off_t,
6071- which may lose precision when converted to int. */
6072- return (a > b ) ? 1 : (a < b ) ? -1 : 0 ;
6073- }
6074-
60756062/* Initialize the slotdefs table by adding interned string objects for the
60766063 names and sorting the entries. */
60776064static void
@@ -6083,12 +6070,12 @@ init_slotdefs(void)
60836070 if (initialized )
60846071 return ;
60856072 for (p = slotdefs ; p -> name ; p ++ ) {
6073+ /* Slots must be ordered by their offset in the PyHeapTypeObject. */
6074+ assert (!p [1 ].name || p -> offset <= p [1 ].offset );
60866075 p -> name_strobj = PyUnicode_InternFromString (p -> name );
60876076 if (!p -> name_strobj )
60886077 Py_FatalError ("Out of memory interning slotdef names" );
60896078 }
6090- qsort ((void * )slotdefs , (size_t )(p - slotdefs ), sizeof (slotdef ),
6091- slotdef_cmp );
60926079 initialized = 1 ;
60936080}
60946081
0 commit comments