[pypy-commit] pypy default: Allow very basic multiple inheritance of app-level types in RPython. Thanks to amaury for the review/suggestions.
alex_gaynor
noreply at buildbot.pypy.org
Wed Nov 9 22:44:51 CET 2011
Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch:
Changeset: r49066:90b293e995c7
Date: 2011-11-09 16:44 -0500
http://bitbucket.org/pypy/pypy/changeset/90b293e995c7/
Log: Allow very basic multiple inheritance of app-level types in RPython.
Thanks to amaury for the review/suggestions.
diff --git a/pypy/interpreter/test/test_typedef.py b/pypy/interpreter/test/test_typedef.py
--- a/pypy/interpreter/test/test_typedef.py
+++ b/pypy/interpreter/test/test_typedef.py
@@ -2,7 +2,7 @@
from pypy.interpreter import typedef
from pypy.tool.udir import udir
from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.gateway import ObjSpace
+from pypy.interpreter.gateway import ObjSpace, interp2app
# this test isn't so much to test that the objspace interface *works*
# -- it's more to test that it's *there*
@@ -260,6 +260,50 @@
gc.collect(); gc.collect()
assert space.unwrap(w_seen) == [6, 2]
+ def test_multiple_inheritance(self):
+ class W_A(Wrappable):
+ a = 1
+ b = 2
+ class W_C(W_A):
+ b = 3
+ W_A.typedef = typedef.TypeDef("A",
+ a = typedef.interp_attrproperty("a", cls=W_A),
+ b = typedef.interp_attrproperty("b", cls=W_A),
+ )
+ class W_B(Wrappable):
+ pass
+ def standalone_method(space, w_obj):
+ if isinstance(w_obj, W_A):
+ return space.w_True
+ else:
+ return space.w_False
+ W_B.typedef = typedef.TypeDef("B",
+ c = interp2app(standalone_method)
+ )
+ W_C.typedef = typedef.TypeDef("C", (W_A.typedef, W_B.typedef,))
+
+ w_o1 = self.space.wrap(W_C())
+ w_o2 = self.space.wrap(W_B())
+ w_c = self.space.gettypefor(W_C)
+ w_b = self.space.gettypefor(W_B)
+ w_a = self.space.gettypefor(W_A)
+ assert w_c.mro_w == [
+ w_c,
+ w_a,
+ w_b,
+ self.space.w_object,
+ ]
+ for w_tp in w_c.mro_w:
+ assert self.space.isinstance_w(w_o1, w_tp)
+ def assert_attr(w_obj, name, value):
+ assert self.space.unwrap(self.space.getattr(w_obj, self.space.wrap(name))) == value
+ def assert_method(w_obj, name, value):
+ assert self.space.unwrap(self.space.call_method(w_obj, name)) == value
+ assert_attr(w_o1, "a", 1)
+ assert_attr(w_o1, "b", 3)
+ assert_method(w_o1, "c", True)
+ assert_method(w_o2, "c", False)
+
class AppTestTypeDef:
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -15,13 +15,19 @@
def __init__(self, __name, __base=None, **rawdict):
"NOT_RPYTHON: initialization-time only"
self.name = __name
- self.base = __base
+ if __base is None:
+ bases = ()
+ elif isinstance(__base, tuple):
+ bases = __base
+ else:
+ bases = (__base,)
+ self.bases = bases
self.hasdict = '__dict__' in rawdict
self.weakrefable = '__weakref__' in rawdict
self.doc = rawdict.pop('__doc__', None)
- if __base is not None:
- self.hasdict |= __base.hasdict
- self.weakrefable |= __base.weakrefable
+ for base in bases:
+ self.hasdict |= base.hasdict
+ self.weakrefable |= base.weakrefable
self.rawdict = {}
self.acceptable_as_base_class = '__new__' in rawdict
self.applevel_subclasses_base = None
diff --git a/pypy/objspace/std/stdtypedef.py b/pypy/objspace/std/stdtypedef.py
--- a/pypy/objspace/std/stdtypedef.py
+++ b/pypy/objspace/std/stdtypedef.py
@@ -32,11 +32,15 @@
from pypy.objspace.std.objecttype import object_typedef
if b is object_typedef:
return True
- while a is not b:
- if a is None:
- return False
- a = a.base
- return True
+ if a is None:
+ return False
+ if a is b:
+ return True
+ for a1 in a.bases:
+ for b1 in b.bases:
+ if issubtypedef(a1, b1):
+ return True
+ return False
std_dict_descr = GetSetProperty(descr_get_dict, descr_set_dict, descr_del_dict,
doc="dictionary for instance variables (if defined)")
@@ -75,8 +79,8 @@
if typedef is object_typedef:
bases_w = []
else:
- base = typedef.base or object_typedef
- bases_w = [space.gettypeobject(base)]
+ bases = typedef.bases or [object_typedef]
+ bases_w = [space.gettypeobject(base) for base in bases]
# wrap everything
dict_w = {}
More information about the pypy-commit
mailing list