@@ -5667,15 +5667,16 @@ slot_tp_del(PyObject *self)
56675667}
56685668
56695669
5670- /* Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper
5671- functions. The offsets here are relative to the 'PyHeapTypeObject'
5672- structure, which incorporates the additional structures used for numbers,
5673- sequences and mappings.
5674- Note that multiple names may map to the same slot (e.g. __eq__,
5675- __ne__ etc. all map to tp_richcompare) and one name may map to multiple
5676- slots (e.g. __str__ affects tp_str as well as tp_repr). The table is
5677- terminated with an all-zero entry. (This table is further initialized and
5678- sorted in init_slotdefs() below.) */
5670+ /*
5671+ Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper functions.
5672+
5673+ The table is ordered by offsets relative to the 'PyHeapTypeObject' structure,
5674+ which incorporates the additional structures used for numbers, sequences and
5675+ mappings. Note that multiple names may map to the same slot (e.g. __eq__,
5676+ __ne__ etc. all map to tp_richcompare) and one name may map to multiple slots
5677+ (e.g. __str__ affects tp_str as well as tp_repr). The table is terminated with
5678+ an all-zero entry. (This table is further initialized in init_slotdefs().)
5679+ */
56795680
56805681typedef struct wrapperbase slotdef ;
56815682
@@ -5725,43 +5726,53 @@ typedef struct wrapperbase slotdef;
57255726 "x." NAME "(y) <==> " DOC)
57265727
57275728static slotdef slotdefs [] = {
5728- SQSLOT ("__len__" , sq_length , slot_sq_length , wrap_lenfunc ,
5729- "x.__len__() <==> len(x)" ),
5730- /* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL.
5731- The logic in abstract.c always falls back to nb_add/nb_multiply in
5732- this case. Defining both the nb_* and the sq_* slots to call the
5733- user-defined methods has unexpected side-effects, as shown by
5734- test_descr.notimplemented() */
5735- SQSLOT ("__add__" , sq_concat , NULL , wrap_binaryfunc ,
5736- "x.__add__(y) <==> x+y" ),
5737- SQSLOT ("__mul__" , sq_repeat , NULL , wrap_indexargfunc ,
5738- "x.__mul__(n) <==> x*n" ),
5739- SQSLOT ("__rmul__" , sq_repeat , NULL , wrap_indexargfunc ,
5740- "x.__rmul__(n) <==> n*x" ),
5741- SQSLOT ("__getitem__" , sq_item , slot_sq_item , wrap_sq_item ,
5742- "x.__getitem__(y) <==> x[y]" ),
5743- SQSLOT ("__setitem__" , sq_ass_item , slot_sq_ass_item , wrap_sq_setitem ,
5744- "x.__setitem__(i, y) <==> x[i]=y" ),
5745- SQSLOT ("__delitem__" , sq_ass_item , slot_sq_ass_item , wrap_sq_delitem ,
5746- "x.__delitem__(y) <==> del x[y]" ),
5747- SQSLOT ("__contains__" , sq_contains , slot_sq_contains , wrap_objobjproc ,
5748- "x.__contains__(y) <==> y in x" ),
5749- SQSLOT ("__iadd__" , sq_inplace_concat , NULL ,
5750- wrap_binaryfunc , "x.__iadd__(y) <==> x+=y" ),
5751- SQSLOT ("__imul__" , sq_inplace_repeat , NULL ,
5752- wrap_indexargfunc , "x.__imul__(y) <==> x*=y" ),
5753-
5754- MPSLOT ("__len__" , mp_length , slot_mp_length , wrap_lenfunc ,
5755- "x.__len__() <==> len(x)" ),
5756- MPSLOT ("__getitem__" , mp_subscript , slot_mp_subscript ,
5757- wrap_binaryfunc ,
5758- "x.__getitem__(y) <==> x[y]" ),
5759- MPSLOT ("__setitem__" , mp_ass_subscript , slot_mp_ass_subscript ,
5760- wrap_objobjargproc ,
5761- "x.__setitem__(i, y) <==> x[i]=y" ),
5762- MPSLOT ("__delitem__" , mp_ass_subscript , slot_mp_ass_subscript ,
5763- wrap_delitem ,
5764- "x.__delitem__(y) <==> del x[y]" ),
5729+ TPSLOT ("__getattribute__" , tp_getattr , NULL , NULL , "" ),
5730+ TPSLOT ("__getattr__" , tp_getattr , NULL , NULL , "" ),
5731+ TPSLOT ("__setattr__" , tp_setattr , NULL , NULL , "" ),
5732+ TPSLOT ("__delattr__" , tp_setattr , NULL , NULL , "" ),
5733+ TPSLOT ("__repr__" , tp_repr , slot_tp_repr , wrap_unaryfunc ,
5734+ "x.__repr__() <==> repr(x)" ),
5735+ TPSLOT ("__hash__" , tp_hash , slot_tp_hash , wrap_hashfunc ,
5736+ "x.__hash__() <==> hash(x)" ),
5737+ FLSLOT ("__call__" , tp_call , slot_tp_call , (wrapperfunc )wrap_call ,
5738+ "x.__call__(...) <==> x(...)" , PyWrapperFlag_KEYWORDS ),
5739+ TPSLOT ("__str__" , tp_str , slot_tp_str , wrap_unaryfunc ,
5740+ "x.__str__() <==> str(x)" ),
5741+ TPSLOT ("__getattribute__" , tp_getattro , slot_tp_getattr_hook ,
5742+ wrap_binaryfunc , "x.__getattribute__('name') <==> x.name" ),
5743+ TPSLOT ("__getattr__" , tp_getattro , slot_tp_getattr_hook , NULL , "" ),
5744+ TPSLOT ("__setattr__" , tp_setattro , slot_tp_setattro , wrap_setattr ,
5745+ "x.__setattr__('name', value) <==> x.name = value" ),
5746+ TPSLOT ("__delattr__" , tp_setattro , slot_tp_setattro , wrap_delattr ,
5747+ "x.__delattr__('name') <==> del x.name" ),
5748+ TPSLOT ("__lt__" , tp_richcompare , slot_tp_richcompare , richcmp_lt ,
5749+ "x.__lt__(y) <==> x<y" ),
5750+ TPSLOT ("__le__" , tp_richcompare , slot_tp_richcompare , richcmp_le ,
5751+ "x.__le__(y) <==> x<=y" ),
5752+ TPSLOT ("__eq__" , tp_richcompare , slot_tp_richcompare , richcmp_eq ,
5753+ "x.__eq__(y) <==> x==y" ),
5754+ TPSLOT ("__ne__" , tp_richcompare , slot_tp_richcompare , richcmp_ne ,
5755+ "x.__ne__(y) <==> x!=y" ),
5756+ TPSLOT ("__gt__" , tp_richcompare , slot_tp_richcompare , richcmp_gt ,
5757+ "x.__gt__(y) <==> x>y" ),
5758+ TPSLOT ("__ge__" , tp_richcompare , slot_tp_richcompare , richcmp_ge ,
5759+ "x.__ge__(y) <==> x>=y" ),
5760+ TPSLOT ("__iter__" , tp_iter , slot_tp_iter , wrap_unaryfunc ,
5761+ "x.__iter__() <==> iter(x)" ),
5762+ TPSLOT ("__next__" , tp_iternext , slot_tp_iternext , wrap_next ,
5763+ "x.__next__() <==> next(x)" ),
5764+ TPSLOT ("__get__" , tp_descr_get , slot_tp_descr_get , wrap_descr_get ,
5765+ "descr.__get__(obj[, type]) -> value" ),
5766+ TPSLOT ("__set__" , tp_descr_set , slot_tp_descr_set , wrap_descr_set ,
5767+ "descr.__set__(obj, value)" ),
5768+ TPSLOT ("__delete__" , tp_descr_set , slot_tp_descr_set ,
5769+ wrap_descr_delete , "descr.__delete__(obj)" ),
5770+ FLSLOT ("__init__" , tp_init , slot_tp_init , (wrapperfunc )wrap_init ,
5771+ "x.__init__(...) initializes x; "
5772+ "see help(type(x)) for signature" ,
5773+ PyWrapperFlag_KEYWORDS ),
5774+ TPSLOT ("__new__" , tp_new , slot_tp_new , NULL , "" ),
5775+ TPSLOT ("__del__" , tp_del , slot_tp_del , NULL , "" ),
57655776
57665777 BINSLOT ("__add__" , nb_add , slot_nb_add ,
57675778 "+" ),
@@ -5808,8 +5819,6 @@ static slotdef slotdefs[] = {
58085819 "int(x)" ),
58095820 UNSLOT ("__float__" , nb_float , slot_nb_float , wrap_unaryfunc ,
58105821 "float(x)" ),
5811- NBSLOT ("__index__" , nb_index , slot_nb_index , wrap_unaryfunc ,
5812- "x[y:z] <==> x[y.__index__():z.__index__()]" ),
58135822 IBSLOT ("__iadd__" , nb_inplace_add , slot_nb_inplace_add ,
58145823 wrap_binaryfunc , "+=" ),
58155824 IBSLOT ("__isub__" , nb_inplace_subtract , slot_nb_inplace_subtract ,
@@ -5838,54 +5847,47 @@ static slotdef slotdefs[] = {
58385847 slot_nb_inplace_floor_divide , wrap_binaryfunc , "//" ),
58395848 IBSLOT ("__itruediv__" , nb_inplace_true_divide ,
58405849 slot_nb_inplace_true_divide , wrap_binaryfunc , "/" ),
5850+ NBSLOT ("__index__" , nb_index , slot_nb_index , wrap_unaryfunc ,
5851+ "x[y:z] <==> x[y.__index__():z.__index__()]" ),
5852+
5853+ MPSLOT ("__len__" , mp_length , slot_mp_length , wrap_lenfunc ,
5854+ "x.__len__() <==> len(x)" ),
5855+ MPSLOT ("__getitem__" , mp_subscript , slot_mp_subscript ,
5856+ wrap_binaryfunc ,
5857+ "x.__getitem__(y) <==> x[y]" ),
5858+ MPSLOT ("__setitem__" , mp_ass_subscript , slot_mp_ass_subscript ,
5859+ wrap_objobjargproc ,
5860+ "x.__setitem__(i, y) <==> x[i]=y" ),
5861+ MPSLOT ("__delitem__" , mp_ass_subscript , slot_mp_ass_subscript ,
5862+ wrap_delitem ,
5863+ "x.__delitem__(y) <==> del x[y]" ),
5864+
5865+ SQSLOT ("__len__" , sq_length , slot_sq_length , wrap_lenfunc ,
5866+ "x.__len__() <==> len(x)" ),
5867+ /* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL.
5868+ The logic in abstract.c always falls back to nb_add/nb_multiply in
5869+ this case. Defining both the nb_* and the sq_* slots to call the
5870+ user-defined methods has unexpected side-effects, as shown by
5871+ test_descr.notimplemented() */
5872+ SQSLOT ("__add__" , sq_concat , NULL , wrap_binaryfunc ,
5873+ "x.__add__(y) <==> x+y" ),
5874+ SQSLOT ("__mul__" , sq_repeat , NULL , wrap_indexargfunc ,
5875+ "x.__mul__(n) <==> x*n" ),
5876+ SQSLOT ("__rmul__" , sq_repeat , NULL , wrap_indexargfunc ,
5877+ "x.__rmul__(n) <==> n*x" ),
5878+ SQSLOT ("__getitem__" , sq_item , slot_sq_item , wrap_sq_item ,
5879+ "x.__getitem__(y) <==> x[y]" ),
5880+ SQSLOT ("__setitem__" , sq_ass_item , slot_sq_ass_item , wrap_sq_setitem ,
5881+ "x.__setitem__(i, y) <==> x[i]=y" ),
5882+ SQSLOT ("__delitem__" , sq_ass_item , slot_sq_ass_item , wrap_sq_delitem ,
5883+ "x.__delitem__(y) <==> del x[y]" ),
5884+ SQSLOT ("__contains__" , sq_contains , slot_sq_contains , wrap_objobjproc ,
5885+ "x.__contains__(y) <==> y in x" ),
5886+ SQSLOT ("__iadd__" , sq_inplace_concat , NULL ,
5887+ wrap_binaryfunc , "x.__iadd__(y) <==> x+=y" ),
5888+ SQSLOT ("__imul__" , sq_inplace_repeat , NULL ,
5889+ wrap_indexargfunc , "x.__imul__(y) <==> x*=y" ),
58415890
5842- TPSLOT ("__str__" , tp_str , slot_tp_str , wrap_unaryfunc ,
5843- "x.__str__() <==> str(x)" ),
5844- TPSLOT ("__repr__" , tp_repr , slot_tp_repr , wrap_unaryfunc ,
5845- "x.__repr__() <==> repr(x)" ),
5846- TPSLOT ("__hash__" , tp_hash , slot_tp_hash , wrap_hashfunc ,
5847- "x.__hash__() <==> hash(x)" ),
5848- FLSLOT ("__call__" , tp_call , slot_tp_call , (wrapperfunc )wrap_call ,
5849- "x.__call__(...) <==> x(...)" , PyWrapperFlag_KEYWORDS ),
5850- TPSLOT ("__getattribute__" , tp_getattro , slot_tp_getattr_hook ,
5851- wrap_binaryfunc , "x.__getattribute__('name') <==> x.name" ),
5852- TPSLOT ("__getattribute__" , tp_getattr , NULL , NULL , "" ),
5853- TPSLOT ("__getattr__" , tp_getattro , slot_tp_getattr_hook , NULL , "" ),
5854- TPSLOT ("__getattr__" , tp_getattr , NULL , NULL , "" ),
5855- TPSLOT ("__setattr__" , tp_setattro , slot_tp_setattro , wrap_setattr ,
5856- "x.__setattr__('name', value) <==> x.name = value" ),
5857- TPSLOT ("__setattr__" , tp_setattr , NULL , NULL , "" ),
5858- TPSLOT ("__delattr__" , tp_setattro , slot_tp_setattro , wrap_delattr ,
5859- "x.__delattr__('name') <==> del x.name" ),
5860- TPSLOT ("__delattr__" , tp_setattr , NULL , NULL , "" ),
5861- TPSLOT ("__lt__" , tp_richcompare , slot_tp_richcompare , richcmp_lt ,
5862- "x.__lt__(y) <==> x<y" ),
5863- TPSLOT ("__le__" , tp_richcompare , slot_tp_richcompare , richcmp_le ,
5864- "x.__le__(y) <==> x<=y" ),
5865- TPSLOT ("__eq__" , tp_richcompare , slot_tp_richcompare , richcmp_eq ,
5866- "x.__eq__(y) <==> x==y" ),
5867- TPSLOT ("__ne__" , tp_richcompare , slot_tp_richcompare , richcmp_ne ,
5868- "x.__ne__(y) <==> x!=y" ),
5869- TPSLOT ("__gt__" , tp_richcompare , slot_tp_richcompare , richcmp_gt ,
5870- "x.__gt__(y) <==> x>y" ),
5871- TPSLOT ("__ge__" , tp_richcompare , slot_tp_richcompare , richcmp_ge ,
5872- "x.__ge__(y) <==> x>=y" ),
5873- TPSLOT ("__iter__" , tp_iter , slot_tp_iter , wrap_unaryfunc ,
5874- "x.__iter__() <==> iter(x)" ),
5875- TPSLOT ("__next__" , tp_iternext , slot_tp_iternext , wrap_next ,
5876- "x.__next__() <==> next(x)" ),
5877- TPSLOT ("__get__" , tp_descr_get , slot_tp_descr_get , wrap_descr_get ,
5878- "descr.__get__(obj[, type]) -> value" ),
5879- TPSLOT ("__set__" , tp_descr_set , slot_tp_descr_set , wrap_descr_set ,
5880- "descr.__set__(obj, value)" ),
5881- TPSLOT ("__delete__" , tp_descr_set , slot_tp_descr_set ,
5882- wrap_descr_delete , "descr.__delete__(obj)" ),
5883- FLSLOT ("__init__" , tp_init , slot_tp_init , (wrapperfunc )wrap_init ,
5884- "x.__init__(...) initializes x; "
5885- "see help(type(x)) for signature" ,
5886- PyWrapperFlag_KEYWORDS ),
5887- TPSLOT ("__new__" , tp_new , slot_tp_new , NULL , "" ),
5888- TPSLOT ("__del__" , tp_del , slot_tp_del , NULL , "" ),
58895891 {NULL }
58905892};
58915893
@@ -6066,21 +6068,6 @@ update_slots_callback(PyTypeObject *type, void *data)
60666068 return 0 ;
60676069}
60686070
6069- /* Comparison function for qsort() to compare slotdefs by their offset, and
6070- for equal offset by their address (to force a stable sort). */
6071- static int
6072- slotdef_cmp (const void * aa , const void * bb )
6073- {
6074- const slotdef * a = (const slotdef * )aa , * b = (const slotdef * )bb ;
6075- int c = a -> offset - b -> offset ;
6076- if (c != 0 )
6077- return c ;
6078- else
6079- /* Cannot use a-b, as this gives off_t,
6080- which may lose precision when converted to int. */
6081- return (a > b ) ? 1 : (a < b ) ? -1 : 0 ;
6082- }
6083-
60846071/* Initialize the slotdefs table by adding interned string objects for the
60856072 names and sorting the entries. */
60866073static void
@@ -6092,12 +6079,12 @@ init_slotdefs(void)
60926079 if (initialized )
60936080 return ;
60946081 for (p = slotdefs ; p -> name ; p ++ ) {
6082+ /* Slots must be ordered by their offset in the PyHeapTypeObject. */
6083+ assert (!p [1 ].name || p -> offset <= p [1 ].offset );
60956084 p -> name_strobj = PyUnicode_InternFromString (p -> name );
60966085 if (!p -> name_strobj )
60976086 Py_FatalError ("Out of memory interning slotdef names" );
60986087 }
6099- qsort ((void * )slotdefs , (size_t )(p - slotdefs ), sizeof (slotdef ),
6100- slotdef_cmp );
61016088 initialized = 1 ;
61026089}
61036090
0 commit comments