[pypy-commit] pypy cpyext-gc-support-2: (ronan, arigo)
arigo
pypy.commits at gmail.com
Mon Feb 22 12:30:36 EST 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: cpyext-gc-support-2
Changeset: r82403:f2383d0be1ba
Date: 2016-02-22 18:29 +0100
http://bitbucket.org/pypy/pypy/changeset/f2383d0be1ba/
Log: (ronan, arigo)
Fix and test for inheriting at app-level from some PyTypeObject
diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c
--- a/pypy/module/cpyext/test/foo.c
+++ b/pypy/module/cpyext/test/foo.c
@@ -623,11 +623,17 @@
};
+static PyObject *size_of_instances(PyObject *self, PyObject *t)
+{
+ return PyInt_FromLong(((PyTypeObject *)t)->tp_basicsize);
+}
+
/* List of functions exported by this module */
static PyMethodDef foo_functions[] = {
{"new", (PyCFunction)foo_new, METH_NOARGS, NULL},
{"newCustom", (PyCFunction)newCustom, METH_NOARGS, NULL},
+ {"size_of_instances", (PyCFunction)size_of_instances, METH_O, NULL},
{NULL, NULL} /* Sentinel */
};
diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -744,3 +744,25 @@
module = self.import_module(name='foo3')
print('calling module.Type()...')
module.Type("X", (object,), {})
+
+ def test_app_subclass_of_c_type(self):
+ module = self.import_module(name='foo')
+ size = module.size_of_instances(module.fooType)
+ class f1(object):
+ pass
+ class f2(module.fooType):
+ pass
+ class bar(f1, f2):
+ pass
+ assert bar.__base__ is f2
+ assert module.size_of_instances(bar) == size
+
+ def test_app_cant_subclass_two_types(self):
+ module = self.import_module(name='foo')
+ try:
+ class bar(module.fooType, module.Property):
+ pass
+ except TypeError as e:
+ assert str(e) == 'instance layout conflicts in multiple inheritance'
+ else:
+ raise AssertionError("did not get TypeError!")
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -297,7 +297,7 @@
name = rffi.charp2str(pto.c_tp_name)
W_TypeObject.__init__(self, space, name,
- bases_w or [space.w_object], dict_w)
+ bases_w or [space.w_object], dict_w, force_new_layout=True)
if not space.is_true(space.issubtype(self, space.w_type)):
self.flag_cpytype = True
self.flag_heaptype = False
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -148,7 +148,7 @@
@dont_look_inside
def __init__(w_self, space, name, bases_w, dict_w,
- overridetypedef=None):
+ overridetypedef=None, force_new_layout=False):
w_self.space = space
w_self.name = name
w_self.bases_w = bases_w
@@ -164,9 +164,10 @@
w_self.flag_sequence_bug_compat = False
if overridetypedef is not None:
+ assert not force_new_layout
layout = setup_builtin_type(w_self, overridetypedef)
else:
- layout = setup_user_defined_type(w_self)
+ layout = setup_user_defined_type(w_self, force_new_layout)
w_self.layout = layout
if space.config.objspace.std.withtypeversion:
@@ -1000,7 +1001,7 @@
w_self.weakrefable = w_self.weakrefable or w_base.weakrefable
return hasoldstylebase
-def create_all_slots(w_self, hasoldstylebase, w_bestbase):
+def create_all_slots(w_self, hasoldstylebase, w_bestbase, force_new_layout):
base_layout = w_bestbase.layout
index_next_extra_slot = base_layout.nslots
space = w_self.space
@@ -1040,7 +1041,7 @@
if '__del__' in dict_w:
w_self.needsdel = True
#
- if index_next_extra_slot == base_layout.nslots:
+ if index_next_extra_slot == base_layout.nslots and not force_new_layout:
return base_layout
else:
return Layout(base_layout.typedef, index_next_extra_slot,
@@ -1081,7 +1082,7 @@
return False
return True
-def setup_user_defined_type(w_self):
+def setup_user_defined_type(w_self, force_new_layout):
if len(w_self.bases_w) == 0:
w_self.bases_w = [w_self.space.w_object]
w_bestbase = check_and_find_best_base(w_self.space, w_self.bases_w)
@@ -1093,7 +1094,8 @@
w_self.flag_abstract |= w_base.flag_abstract
hasoldstylebase = copy_flags_from_bases(w_self, w_bestbase)
- layout = create_all_slots(w_self, hasoldstylebase, w_bestbase)
+ layout = create_all_slots(w_self, hasoldstylebase, w_bestbase,
+ force_new_layout)
ensure_common_attributes(w_self)
return layout
More information about the pypy-commit
mailing list