4
4
#include "Python.h"
5
5
#include "structmember.h"
6
6
7
- staticforward int add_members (PyTypeObject * , struct memberlist * );
8
-
9
7
static struct memberlist type_members [] = {
10
8
{"__name__" , T_STRING , offsetof(PyTypeObject , tp_name ), READONLY },
11
9
{"__basicsize__" , T_INT , offsetof(PyTypeObject ,tp_basicsize ),READONLY },
@@ -647,7 +645,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
647
645
slotoffset += sizeof (PyObject * );
648
646
}
649
647
type -> tp_basicsize = slotoffset ;
650
- add_members ( type , et -> members ) ;
648
+ type -> tp_members = et -> members ;
651
649
652
650
/* Special case some slots */
653
651
if (type -> tp_dictoffset != 0 || nslots > 0 ) {
@@ -882,7 +880,7 @@ PyTypeObject PyBaseObject_Type = {
882
880
0 , /* tp_call */
883
881
0 , /* tp_str */
884
882
PyObject_GenericGetAttr , /* tp_getattro */
885
- 0 , /* tp_setattro */
883
+ PyObject_GenericSetAttr , /* tp_setattro */
886
884
0 , /* tp_as_buffer */
887
885
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
888
886
"The most base type" , /* tp_doc */
@@ -928,25 +926,6 @@ add_methods(PyTypeObject *type, PyMethodDef *meth)
928
926
return 0 ;
929
927
}
930
928
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
-
950
929
static int
951
930
add_members (PyTypeObject * type , struct memberlist * memb )
952
931
{
@@ -986,27 +965,90 @@ add_getset(PyTypeObject *type, struct getsetlist *gsp)
986
965
return 0 ;
987
966
}
988
967
989
- staticforward int add_operators (PyTypeObject * );
968
+ static void
969
+ inherit_special (PyTypeObject * type , PyTypeObject * base )
970
+ {
971
+ int oldsize , newsize ;
990
972
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
992
1024
inherit_slots (PyTypeObject * type , PyTypeObject * base )
993
1025
{
994
- int oldsize , newsize ;
1026
+ PyTypeObject * basebase ;
995
1027
1028
+ #undef SLOTDEFINED
996
1029
#undef COPYSLOT
997
1030
#undef COPYNUM
998
1031
#undef COPYSEQ
999
1032
#undef COPYMAP
1033
+
1034
+ #define SLOTDEFINED (SLOT ) \
1035
+ (base->SLOT != 0 && \
1036
+ (basebase == NULL || base->SLOT != basebase->SLOT))
1037
+
1000
1038
#define COPYSLOT (SLOT ) \
1001
- if (!type->SLOT) type->SLOT = base->SLOT
1039
+ if (!type->SLOT && SLOTDEFINED(SLOT) ) type->SLOT = base->SLOT
1002
1040
1003
1041
#define COPYNUM (SLOT ) COPYSLOT(tp_as_number->SLOT)
1004
1042
#define COPYSEQ (SLOT ) COPYSLOT(tp_as_sequence->SLOT)
1005
1043
#define COPYMAP (SLOT ) COPYSLOT(tp_as_mapping->SLOT)
1006
1044
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 ;
1010
1052
COPYNUM (nb_add );
1011
1053
COPYNUM (nb_subtract );
1012
1054
COPYNUM (nb_multiply );
@@ -1049,9 +1091,10 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
1049
1091
}
1050
1092
}
1051
1093
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 ;
1055
1098
COPYSEQ (sq_length );
1056
1099
COPYSEQ (sq_concat );
1057
1100
COPYSEQ (sq_repeat );
@@ -1064,53 +1107,16 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
1064
1107
COPYSEQ (sq_inplace_repeat );
1065
1108
}
1066
1109
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 ;
1070
1114
COPYMAP (mp_length );
1071
1115
COPYMAP (mp_subscript );
1072
1116
COPYMAP (mp_ass_subscript );
1073
1117
}
1074
1118
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 ;
1114
1120
1115
1121
COPYSLOT (tp_itemsize );
1116
1122
COPYSLOT (tp_dealloc );
@@ -1152,16 +1158,12 @@ inherit_slots(PyTypeObject *type, PyTypeObject *base)
1152
1158
COPYSLOT (tp_dictoffset );
1153
1159
COPYSLOT (tp_init );
1154
1160
COPYSLOT (tp_alloc );
1155
- if (base != & PyBaseObject_Type ||
1156
- (type -> tp_flags & Py_TPFLAGS_HEAPTYPE )) {
1157
- COPYSLOT (tp_new );
1158
- }
1159
1161
COPYSLOT (tp_free );
1160
1162
}
1161
-
1162
- return 0 ;
1163
1163
}
1164
1164
1165
+ staticforward int add_operators (PyTypeObject * );
1166
+
1165
1167
int
1166
1168
PyType_Ready (PyTypeObject * type )
1167
1169
{
@@ -1237,34 +1239,44 @@ PyType_Ready(PyTypeObject *type)
1237
1239
goto error ;
1238
1240
}
1239
1241
1242
+ /* Inherit special flags from dominant base */
1243
+ if (type -> tp_base != NULL )
1244
+ inherit_special (type , type -> tp_base );
1245
+
1240
1246
/* Initialize tp_dict properly */
1241
1247
if (!PyType_HasFeature (type , Py_TPFLAGS_DYNAMICTYPE )) {
1242
1248
/* 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. */
1246
1250
Py_DECREF (type -> tp_dict );
1247
- type -> tp_dict = PyDict_New ( );
1251
+ type -> tp_dict = PyDict_Copy ( type -> tp_defined );
1248
1252
if (type -> tp_dict == NULL )
1249
1253
goto error ;
1250
1254
bases = type -> tp_mro ;
1251
1255
assert (bases != NULL );
1252
1256
assert (PyTuple_Check (bases ));
1253
1257
n = PyTuple_GET_SIZE (bases );
1254
- for (i = n ; -- i >= 0 ; ) {
1258
+ for (i = 1 ; i < n ; i ++ ) {
1255
1259
base = (PyTypeObject * )PyTuple_GET_ITEM (bases , i );
1256
1260
assert (PyType_Check (base ));
1257
1261
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 )
1259
1263
goto error ;
1264
+ inherit_slots (type , base );
1260
1265
}
1261
1266
}
1262
1267
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
+ }
1267
1278
1279
+ /* All done -- set the ready flag */
1268
1280
assert (type -> tp_dict != NULL );
1269
1281
type -> tp_flags =
1270
1282
(type -> tp_flags & ~Py_TPFLAGS_READYING ) | Py_TPFLAGS_READY ;
@@ -1911,6 +1923,25 @@ add_tp_new_wrapper(PyTypeObject *type)
1911
1923
return PyDict_SetItemString (type -> tp_defined , "__new__" , func );
1912
1924
}
1913
1925
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
+
1914
1945
/* This function is called by PyType_Ready() to populate the type's
1915
1946
dictionary with method descriptors for function slots. For each
1916
1947
function slot (like tp_repr) that's defined in the type, one or
0 commit comments