44#include "Python.h"
55#include "structmember.h"
66
7- staticforward int add_members (PyTypeObject * , struct memberlist * );
8-
97static struct memberlist type_members [] = {
108 {"__name__" , T_STRING , offsetof(PyTypeObject , tp_name ), READONLY },
119 {"__basicsize__" , T_INT , offsetof(PyTypeObject ,tp_basicsize ),READONLY },
@@ -647,7 +645,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
647645 slotoffset += sizeof (PyObject * );
648646 }
649647 type -> tp_basicsize = slotoffset ;
650- add_members ( type , et -> members ) ;
648+ type -> tp_members = et -> members ;
651649
652650 /* Special case some slots */
653651 if (type -> tp_dictoffset != 0 || nslots > 0 ) {
@@ -882,7 +880,7 @@ PyTypeObject PyBaseObject_Type = {
882880 0 , /* tp_call */
883881 0 , /* tp_str */
884882 PyObject_GenericGetAttr , /* tp_getattro */
885- 0 , /* tp_setattro */
883+ PyObject_GenericSetAttr , /* tp_setattro */
886884 0 , /* tp_as_buffer */
887885 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
888886 "The most base type" , /* tp_doc */
@@ -928,25 +926,6 @@ add_methods(PyTypeObject *type, PyMethodDef *meth)
928926 return 0 ;
929927}
930928
931- static int
932- add_wrappers (PyTypeObject * type , struct wrapperbase * wraps , void * wrapped )
933- {
934- PyObject * dict = type -> tp_defined ;
935-
936- for (; wraps -> name != NULL ; wraps ++ ) {
937- PyObject * descr ;
938- if (PyDict_GetItemString (dict , wraps -> name ))
939- continue ;
940- descr = PyDescr_NewWrapper (type , wraps , wrapped );
941- if (descr == NULL )
942- return -1 ;
943- if (PyDict_SetItemString (dict , wraps -> name , descr ) < 0 )
944- return -1 ;
945- Py_DECREF (descr );
946- }
947- return 0 ;
948- }
949-
950929static int
951930add_members (PyTypeObject * type , struct memberlist * memb )
952931{
@@ -986,27 +965,90 @@ add_getset(PyTypeObject *type, struct getsetlist *gsp)
986965 return 0 ;
987966}
988967
989- staticforward int add_operators (PyTypeObject * );
968+ static void
969+ inherit_special (PyTypeObject * type , PyTypeObject * base )
970+ {
971+ int oldsize , newsize ;
990972
991- static int
973+ /* Special flag magic */
974+ if (!type -> tp_as_buffer && base -> tp_as_buffer ) {
975+ type -> tp_flags &= ~Py_TPFLAGS_HAVE_GETCHARBUFFER ;
976+ type -> tp_flags |=
977+ base -> tp_flags & Py_TPFLAGS_HAVE_GETCHARBUFFER ;
978+ }
979+ if (!type -> tp_as_sequence && base -> tp_as_sequence ) {
980+ type -> tp_flags &= ~Py_TPFLAGS_HAVE_SEQUENCE_IN ;
981+ type -> tp_flags |= base -> tp_flags & Py_TPFLAGS_HAVE_SEQUENCE_IN ;
982+ }
983+ if ((type -> tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS ) !=
984+ (base -> tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS )) {
985+ if ((!type -> tp_as_number && base -> tp_as_number ) ||
986+ (!type -> tp_as_sequence && base -> tp_as_sequence )) {
987+ type -> tp_flags &= ~Py_TPFLAGS_HAVE_INPLACEOPS ;
988+ if (!type -> tp_as_number && !type -> tp_as_sequence ) {
989+ type -> tp_flags |= base -> tp_flags &
990+ Py_TPFLAGS_HAVE_INPLACEOPS ;
991+ }
992+ }
993+ /* Wow */
994+ }
995+ if (!type -> tp_as_number && base -> tp_as_number ) {
996+ type -> tp_flags &= ~Py_TPFLAGS_CHECKTYPES ;
997+ type -> tp_flags |= base -> tp_flags & Py_TPFLAGS_CHECKTYPES ;
998+ }
999+
1000+ /* Copying basicsize is connected to the GC flags */
1001+ oldsize = PyType_BASICSIZE (base );
1002+ newsize = type -> tp_basicsize ? PyType_BASICSIZE (type ) : oldsize ;
1003+ if (!(type -> tp_flags & Py_TPFLAGS_GC ) &&
1004+ (base -> tp_flags & Py_TPFLAGS_GC ) &&
1005+ (type -> tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE /*GC slots exist*/ ) &&
1006+ (!type -> tp_traverse && !type -> tp_clear )) {
1007+ type -> tp_flags |= Py_TPFLAGS_GC ;
1008+ if (type -> tp_traverse == NULL )
1009+ type -> tp_traverse = base -> tp_traverse ;
1010+ if (type -> tp_clear == NULL )
1011+ type -> tp_clear = base -> tp_clear ;
1012+ }
1013+ if (type -> tp_flags & base -> tp_flags & Py_TPFLAGS_HAVE_CLASS ) {
1014+ if (base != & PyBaseObject_Type ||
1015+ (type -> tp_flags & Py_TPFLAGS_HEAPTYPE )) {
1016+ if (type -> tp_new == NULL )
1017+ type -> tp_new = base -> tp_new ;
1018+ }
1019+ }
1020+ PyType_SET_BASICSIZE (type , newsize );
1021+ }
1022+
1023+ static void
9921024inherit_slots (PyTypeObject * type , PyTypeObject * base )
9931025{
994- int oldsize , newsize ;
1026+ PyTypeObject * basebase ;
9951027
1028+ #undef SLOTDEFINED
9961029#undef COPYSLOT
9971030#undef COPYNUM
9981031#undef COPYSEQ
9991032#undef COPYMAP
1033+
1034+ #define SLOTDEFINED (SLOT ) \
1035+ (base->SLOT != 0 && \
1036+ (basebase == NULL || base->SLOT != basebase->SLOT))
1037+
10001038#define COPYSLOT (SLOT ) \
1001- if (!type->SLOT) type->SLOT = base->SLOT
1039+ if (!type->SLOT && SLOTDEFINED(SLOT) ) type->SLOT = base->SLOT
10021040
10031041#define COPYNUM (SLOT ) COPYSLOT(tp_as_number->SLOT)
10041042#define COPYSEQ (SLOT ) COPYSLOT(tp_as_sequence->SLOT)
10051043#define COPYMAP (SLOT ) COPYSLOT(tp_as_mapping->SLOT)
10061044
1007- if (type -> tp_as_number == NULL )
1008- type -> tp_as_number = base -> tp_as_number ;
1009- else if (base -> tp_as_number ) {
1045+ /* This won't inherit indirect slots (from tp_as_number etc.)
1046+ if type doesn't provide the space. */
1047+
1048+ if (type -> tp_as_number != NULL && base -> tp_as_number != NULL ) {
1049+ basebase = base -> tp_base ;
1050+ if (basebase -> tp_as_number == NULL )
1051+ basebase = NULL ;
10101052 COPYNUM (nb_add );
10111053 COPYNUM (nb_subtract );
10121054 COPYNUM (nb_multiply );
@@ -1049,9 +1091,10 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
10491091 }
10501092 }
10511093
1052- if (type -> tp_as_sequence == NULL )
1053- type -> tp_as_sequence = base -> tp_as_sequence ;
1054- else if (base -> tp_as_sequence ) {
1094+ if (type -> tp_as_sequence != NULL && base -> tp_as_sequence != NULL ) {
1095+ basebase = base -> tp_base ;
1096+ if (basebase -> tp_as_sequence == NULL )
1097+ basebase = NULL ;
10551098 COPYSEQ (sq_length );
10561099 COPYSEQ (sq_concat );
10571100 COPYSEQ (sq_repeat );
@@ -1064,53 +1107,16 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
10641107 COPYSEQ (sq_inplace_repeat );
10651108 }
10661109
1067- if (type -> tp_as_mapping == NULL )
1068- type -> tp_as_mapping = base -> tp_as_mapping ;
1069- else if (base -> tp_as_mapping ) {
1110+ if (type -> tp_as_mapping != NULL && base -> tp_as_mapping != NULL ) {
1111+ basebase = base -> tp_base ;
1112+ if (basebase -> tp_as_mapping == NULL )
1113+ basebase = NULL ;
10701114 COPYMAP (mp_length );
10711115 COPYMAP (mp_subscript );
10721116 COPYMAP (mp_ass_subscript );
10731117 }
10741118
1075- /* Special flag magic */
1076- if (!type -> tp_as_buffer && base -> tp_as_buffer ) {
1077- type -> tp_flags &= ~Py_TPFLAGS_HAVE_GETCHARBUFFER ;
1078- type -> tp_flags |=
1079- base -> tp_flags & Py_TPFLAGS_HAVE_GETCHARBUFFER ;
1080- }
1081- if (!type -> tp_as_sequence && base -> tp_as_sequence ) {
1082- type -> tp_flags &= ~Py_TPFLAGS_HAVE_SEQUENCE_IN ;
1083- type -> tp_flags |= base -> tp_flags & Py_TPFLAGS_HAVE_SEQUENCE_IN ;
1084- }
1085- if ((type -> tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS ) !=
1086- (base -> tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS )) {
1087- if ((!type -> tp_as_number && base -> tp_as_number ) ||
1088- (!type -> tp_as_sequence && base -> tp_as_sequence )) {
1089- type -> tp_flags &= ~Py_TPFLAGS_HAVE_INPLACEOPS ;
1090- if (!type -> tp_as_number && !type -> tp_as_sequence ) {
1091- type -> tp_flags |= base -> tp_flags &
1092- Py_TPFLAGS_HAVE_INPLACEOPS ;
1093- }
1094- }
1095- /* Wow */
1096- }
1097- if (!type -> tp_as_number && base -> tp_as_number ) {
1098- type -> tp_flags &= ~Py_TPFLAGS_CHECKTYPES ;
1099- type -> tp_flags |= base -> tp_flags & Py_TPFLAGS_CHECKTYPES ;
1100- }
1101-
1102- /* Copying basicsize is connected to the GC flags */
1103- oldsize = PyType_BASICSIZE (base );
1104- newsize = type -> tp_basicsize ? PyType_BASICSIZE (type ) : oldsize ;
1105- if (!(type -> tp_flags & Py_TPFLAGS_GC ) &&
1106- (base -> tp_flags & Py_TPFLAGS_GC ) &&
1107- (type -> tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE /*GC slots exist*/ ) &&
1108- (!type -> tp_traverse && !type -> tp_clear )) {
1109- type -> tp_flags |= Py_TPFLAGS_GC ;
1110- COPYSLOT (tp_traverse );
1111- COPYSLOT (tp_clear );
1112- }
1113- PyType_SET_BASICSIZE (type , newsize );
1119+ basebase = base -> tp_base ;
11141120
11151121 COPYSLOT (tp_itemsize );
11161122 COPYSLOT (tp_dealloc );
@@ -1152,16 +1158,12 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
11521158 COPYSLOT (tp_dictoffset );
11531159 COPYSLOT (tp_init );
11541160 COPYSLOT (tp_alloc );
1155- if (base != & PyBaseObject_Type ||
1156- (type -> tp_flags & Py_TPFLAGS_HEAPTYPE )) {
1157- COPYSLOT (tp_new );
1158- }
11591161 COPYSLOT (tp_free );
11601162 }
1161-
1162- return 0 ;
11631163}
11641164
1165+ staticforward int add_operators (PyTypeObject * );
1166+
11651167int
11661168PyType_Ready (PyTypeObject * type )
11671169{
@@ -1237,34 +1239,44 @@ PyType_Ready(PyTypeObject *type)
12371239 goto error ;
12381240 }
12391241
1242+ /* Inherit special flags from dominant base */
1243+ if (type -> tp_base != NULL )
1244+ inherit_special (type , type -> tp_base );
1245+
12401246 /* Initialize tp_dict properly */
12411247 if (!PyType_HasFeature (type , Py_TPFLAGS_DYNAMICTYPE )) {
12421248 /* For a static type, tp_dict is the consolidation
1243- of the tp_defined of its bases in MRO. Earlier
1244- bases override later bases; since d.update() works
1245- the other way, we walk the MRO sequence backwards. */
1249+ of the tp_defined of its bases in MRO. */
12461250 Py_DECREF (type -> tp_dict );
1247- type -> tp_dict = PyDict_New ( );
1251+ type -> tp_dict = PyDict_Copy ( type -> tp_defined );
12481252 if (type -> tp_dict == NULL )
12491253 goto error ;
12501254 bases = type -> tp_mro ;
12511255 assert (bases != NULL );
12521256 assert (PyTuple_Check (bases ));
12531257 n = PyTuple_GET_SIZE (bases );
1254- for (i = n ; -- i >= 0 ; ) {
1258+ for (i = 1 ; i < n ; i ++ ) {
12551259 base = (PyTypeObject * )PyTuple_GET_ITEM (bases , i );
12561260 assert (PyType_Check (base ));
12571261 x = base -> tp_defined ;
1258- if (x != NULL && PyDict_Update (type -> tp_dict , x ) < 0 )
1262+ if (x != NULL && PyDict_Merge (type -> tp_dict , x , 0 ) < 0 )
12591263 goto error ;
1264+ inherit_slots (type , base );
12601265 }
12611266 }
12621267
1263- /* Inherit slots from direct base */
1264- if (type -> tp_base != NULL )
1265- if (inherit_slots (type , type -> tp_base ) < 0 )
1266- goto error ;
1268+ /* Some more special stuff */
1269+ base = type -> tp_base ;
1270+ if (base != NULL ) {
1271+ if (type -> tp_as_number == NULL )
1272+ type -> tp_as_number = base -> tp_as_number ;
1273+ if (type -> tp_as_sequence == NULL )
1274+ type -> tp_as_sequence = base -> tp_as_sequence ;
1275+ if (type -> tp_as_mapping == NULL )
1276+ type -> tp_as_mapping = base -> tp_as_mapping ;
1277+ }
12671278
1279+ /* All done -- set the ready flag */
12681280 assert (type -> tp_dict != NULL );
12691281 type -> tp_flags =
12701282 (type -> tp_flags & ~Py_TPFLAGS_READYING ) | Py_TPFLAGS_READY ;
@@ -1911,6 +1923,25 @@ add_tp_new_wrapper(PyTypeObject *type)
19111923 return PyDict_SetItemString (type -> tp_defined , "__new__" , func );
19121924}
19131925
1926+ static int
1927+ add_wrappers (PyTypeObject * type , struct wrapperbase * wraps , void * wrapped )
1928+ {
1929+ PyObject * dict = type -> tp_defined ;
1930+
1931+ for (; wraps -> name != NULL ; wraps ++ ) {
1932+ PyObject * descr ;
1933+ if (PyDict_GetItemString (dict , wraps -> name ))
1934+ continue ;
1935+ descr = PyDescr_NewWrapper (type , wraps , wrapped );
1936+ if (descr == NULL )
1937+ return -1 ;
1938+ if (PyDict_SetItemString (dict , wraps -> name , descr ) < 0 )
1939+ return -1 ;
1940+ Py_DECREF (descr );
1941+ }
1942+ return 0 ;
1943+ }
1944+
19141945/* This function is called by PyType_Ready() to populate the type's
19151946 dictionary with method descriptors for function slots. For each
19161947 function slot (like tp_repr) that's defined in the type, one or
0 commit comments