- 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

`