- Big changes to fix SF bug #442833 (a nasty multiple inheritance · python/cpython@13d52f0 (original) (raw)
`@@ -4,8 +4,6 @@
`
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
`