[pypy-svn] r48858 - in pypy/dist/pypy: module/__builtin__ module/__builtin__/test objspace/std
fijal at codespeak.net
fijal at codespeak.net
Tue Nov 20 18:47:30 CET 2007
Author: fijal
Date: Tue Nov 20 18:47:29 2007
New Revision: 48858
Added:
pypy/dist/pypy/module/__builtin__/descriptor.py (contents, props changed)
Modified:
pypy/dist/pypy/module/__builtin__/__init__.py
pypy/dist/pypy/module/__builtin__/app_descriptor.py
pypy/dist/pypy/module/__builtin__/test/test_descriptor.py
pypy/dist/pypy/objspace/std/objspace.py
pypy/dist/pypy/objspace/std/typeobject.py
Log:
(anto, fijal) Move super() from app-level to interp-level
Modified: pypy/dist/pypy/module/__builtin__/__init__.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/__init__.py (original)
+++ pypy/dist/pypy/module/__builtin__/__init__.py Tue Nov 20 18:47:29 2007
@@ -58,7 +58,6 @@
'property' : 'app_descriptor.property',
'staticmethod' : 'app_descriptor.staticmethod',
'classmethod' : 'app_descriptor.classmethod',
- 'super' : 'app_descriptor.super',
'complex' : 'app_complex.complex',
@@ -127,6 +126,7 @@
'xrange' : 'functional.W_XRange',
'all' : 'functional.all',
'any' : 'functional.any',
+ 'super' : 'descriptor.W_Super',
}
def pick_builtin(self, w_globals):
Modified: pypy/dist/pypy/module/__builtin__/app_descriptor.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/app_descriptor.py (original)
+++ pypy/dist/pypy/module/__builtin__/app_descriptor.py Tue Nov 20 18:47:29 2007
@@ -142,62 +142,3 @@
self.fdel(obj)
docstring.capture(property, 'slot__doc__')
-
-
-# super is a modified version from Guido's tutorial
-# http://www.python.org/2.2.3/descrintro.html
-# it exposes the same special attributes as CPython's.
-class super(object):
- """super(type) -> unbound super object
-super(type, obj) -> bound super object; requires isinstance(obj, type)
-super(type, type2) -> bound super object; requires issubclass(type2, type)
-
-Typical use to call a cooperative superclass method:
-
-class C(B):
- def meth(self, arg):
- super(C, self).meth(arg)"""
- __slots__ = ['__thisclass__', '__self__', '__self_class__']
- def __init__(self, typ, obj=None):
- if obj is None:
- objcls = None # unbound super object
- elif _issubtype(type(obj), type) and _issubtype(obj, typ):
- objcls = obj # special case for class methods
- elif _issubtype(type(obj), typ):
- objcls = type(obj) # normal case
- else:
- objcls = getattr(obj, '__class__', type(obj))
- if not _issubtype(objcls, typ):
- raise TypeError, ("super(type, obj): "
- "obj must be an instance or subtype of type")
- self.__thisclass__ = typ
- self.__self__ = obj
- self.__self_class__ = objcls
- def __get__(self, obj, type=None):
- if obj is None or super.__self__.__get__(self) is not None:
- return self
- else:
- return self.__class__(super.__thisclass__.__get__(self), obj)
- def __getattribute__(self, attr):
- _self_class_ = super.__self_class__.__get__(self)
- if (attr != '__class__' # we want super().__class__ to be the real class
- and _self_class_ is not None): # no magic for unbound type objects
- _thisclass_ = super.__thisclass__.__get__(self)
- mro = iter(_self_class_.__mro__)
- for cls in mro:
- if cls is _thisclass_:
- break
- # Note: mro is an iterator, so the second loop
- # picks up where the first one left off!
- for cls in mro:
- try:
- x = cls.__dict__[attr]
- except KeyError:
- continue
- if hasattr(x, '__get__'):
- _self_ = super.__self__.__get__(self)
- if _self_ is _self_class_:
- _self_ = None # performs an unbound __get__
- x = x.__get__(_self_, _self_class_)
- return x
- return object.__getattribute__(self, attr) # fall-back
Added: pypy/dist/pypy/module/__builtin__/descriptor.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/__builtin__/descriptor.py Tue Nov 20 18:47:29 2007
@@ -0,0 +1,91 @@
+
+from pypy.interpreter.typedef import TypeDef, GetSetProperty
+from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable, \
+ Arguments
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.error import OperationError
+# XXX
+from pypy.interpreter.callmethod import object_getattribute
+
+class W_Super(Wrappable):
+ def __init__(self, space, w_selftype, w_starttype, w_type, w_self):
+ self.w_selftype = w_selftype
+ self.w_starttype = w_starttype
+ self.w_type = w_type
+ self.w_self = w_self
+
+ def get(self, space, w_obj, w_type=None):
+ w = space.wrap
+ if self.w_self is None or space.is_w(w_obj, space.w_None):
+ return w(self)
+ else:
+ return space.call(self.w_selftype, space.newlist([
+ self.w_starttype, w_obj]))
+ get.unwrap_spec = ['self', ObjSpace, W_Root, W_Root]
+
+ def getattribute(self, space, name):
+ w = space.wrap
+ if name == '__class__':
+ return self.w_selftype
+ if self.w_type is None:
+ return space.call(object_getattribute(space),
+ space.newlist([w(self), w(name)]))
+
+ w_value = space.lookup_in_type_starting_at(self.w_type,
+ self.w_starttype,
+ name)
+ if w_value is None:
+ return space.getattr(w(self), w(name))
+
+ try:
+ w_get = space.getattr(w_value, space.wrap('__get__'))
+ if space.is_w(self.w_self, self.w_type):
+ w_self = None
+ else:
+ w_self = self.w_self
+ except OperationError, o:
+ if not o.match(space, space.w_AttributeError):
+ raise
+ return w_value
+ return space.call(w_get, space.newlist([w_self, self.w_type]))
+ getattribute.unwrap_spec = ['self', ObjSpace, str]
+
+def descr_new_super(space, w_self, w_starttype, w_obj_or_type=None):
+ if space.is_w(w_obj_or_type, space.w_None):
+ w_type = None # unbound super object
+ else:
+ w_objtype = space.type(w_obj_or_type)
+ if space.is_true(space.issubtype(w_objtype, space.w_type)) and \
+ space.is_true(space.issubtype(w_obj_or_type, w_starttype)):
+ w_type = w_obj_or_type # special case for class methods
+ elif space.is_true(space.issubtype(w_objtype, w_starttype)):
+ w_type = w_objtype # normal case
+ else:
+ try:
+ w_type = space.getattr(w_obj_or_type, space.wrap('__class__'))
+ except OperationError, o:
+ if not o.match(space, space.w_AttributeError):
+ raise
+ w_type = w_objtype
+ if not space.is_true(space.issubtype(w_type, w_starttype)):
+ raise OperationError(space.w_TypeError,
+ space.wrap("super(type, obj): "
+ "obj must be an instance or subtype of type"))
+ return space.wrap(W_Super(space, w_self, w_starttype, w_type, w_obj_or_type))
+descr_new_super.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root]
+
+W_Super.typedef = TypeDef(
+ 'super',
+ __new__ = interp2app(descr_new_super),
+ __getattribute__ = interp2app(W_Super.getattribute),
+ __get__ = interp2app(W_Super.get),
+ __doc__ = """super(type) -> unbound super object
+super(type, obj) -> bound super object; requires isinstance(obj, type)
+super(type, type2) -> bound super object; requires issubclass(type2, type)
+
+Typical use to call a cooperative superclass method:
+
+class C(B):
+ def meth(self, arg):
+ super(C, self).meth(arg)"""
+)
Modified: pypy/dist/pypy/module/__builtin__/test/test_descriptor.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/test/test_descriptor.py (original)
+++ pypy/dist/pypy/module/__builtin__/test/test_descriptor.py Tue Nov 20 18:47:29 2007
@@ -87,3 +87,109 @@
except TypeError, e:
message = e.args[0]
assert message.startswith('super(type, obj): obj must be an instance or subtype of type')
+
+ def test_super_various(self):
+
+ class A(object):
+ def meth(self, a):
+ return "A(%r)" % a
+
+ class B(A):
+ def __init__(self):
+ self.__super = super(B, self)
+ def meth(self, a):
+ return "B(%r)" % a + self.__super.meth(a)
+
+ assert B().meth(2) == "B(2)A(2)"
+
+ class C(A):
+ def meth(self, a):
+ return "C(%r)" % a + self.__super.meth(a)
+ C._C__super = super(C)
+
+ assert C().meth(3) == "C(3)A(3)"
+
+ class D(C, B):
+ def meth(self, a):
+ return "D(%r)" % a + super(D, self).meth(a)
+
+ assert D().meth(4) == "D(4)C(4)B(4)A(4)"
+
+ # subclasses
+ class mysuper(super):
+ def __init__(self, *args):
+ return super(mysuper, self).__init__(*args)
+
+ class E(D):
+ def meth(self, a):
+ return "E(%r)" % a + mysuper(E, self).meth(a)
+
+ assert E().meth(5) == "E(5)D(5)C(5)B(5)A(5)"
+
+ class F(E):
+ def meth(self, a):
+ s = self.__super # == mysuper(F, self)
+ return "F(%r)[%s]" % (a, s.__class__.__name__) + s.meth(a)
+ F._F__super = mysuper(F)
+
+ assert F().meth(6) == "F(6)[mysuper]E(6)D(6)C(6)B(6)A(6)"
+
+
+ def test_super_lookup(self):
+ class DDbase(object):
+ def getx(self):
+ return 42
+ x = property(getx)
+
+ class DDsub(DDbase):
+ def getx(self):
+ return "hello"
+ x = property(getx)
+
+ dd = DDsub()
+ assert dd.x == "hello"
+ assert super(DDsub, dd).x == 42
+
+ def test_super_lookup2(self):
+
+ class Base(object):
+ aProp = property(lambda self: "foo")
+
+ class Sub(Base):
+ def test(klass):
+ return super(Sub,klass).aProp
+ test = classmethod(test)
+
+ assert Sub.test() is Base.aProp
+
+ def test_proxy_super(self):
+ class Proxy(object):
+ def __init__(self, obj):
+ self.__obj = obj
+ def __getattribute__(self, name):
+ if name.startswith("_Proxy__"):
+ return object.__getattribute__(self, name)
+ else:
+ return getattr(self.__obj, name)
+
+ class B(object):
+ def f(self):
+ return "B.f"
+
+ class C(B):
+ def f(self):
+ return super(C, self).f() + "->C.f"
+
+ obj = C()
+ p = Proxy(obj)
+ assert C.__dict__["f"](p) == "B.f->C.f"
+
+ def test_super_errors(self):
+ class C:
+ pass
+ class D(C):
+ pass
+ raises(TypeError, "super(D, 42)")
+ raises(TypeError, "super(D, C())")
+ raises(TypeError, "super(D).__get__(12)")
+ raises(TypeError, "super(D).__get__(C())")
Modified: pypy/dist/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/std/objspace.py (original)
+++ pypy/dist/pypy/objspace/std/objspace.py Tue Nov 20 18:47:29 2007
@@ -541,6 +541,14 @@
return w_type.lookup_where(name)
lookup_in_type_where._annspecialcase_ = 'specialize:lookup_in_type_where'
+ def lookup_in_type_starting_at(self, w_type, w_starttype, name):
+ """ Only supposed to be used to implement super, w_starttype
+ and w_type are the same as for super(starttype, type)
+ """
+ assert isinstance(w_type, W_TypeObject)
+ assert isinstance(w_starttype, W_TypeObject)
+ return w_type.lookup_starting_at(w_starttype, name)
+
def allocate_instance(self, cls, w_subtype):
"""Allocate the memory needed for an instance of an internal or
user-defined type, without actually __init__ializing the instance."""
Modified: pypy/dist/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/typeobject.py (original)
+++ pypy/dist/pypy/objspace/std/typeobject.py Tue Nov 20 18:47:29 2007
@@ -294,6 +294,20 @@
return w_self._lookup_where(name)
+ def lookup_starting_at(w_self, w_starttype, name):
+ space = w_self.space
+ # XXX Optimize this with method cache
+ look = False
+ for w_class in w_self.mro_w:
+ if w_class is w_starttype:
+ look = True
+ elif look:
+ w_value = w_class.getdictvalue_w(space, name)
+ if w_value is not None:
+ return w_value
+ return None
+
+
def _lookup(w_self, key):
space = w_self.space
for w_class in w_self.mro_w:
More information about the Pypy-commit
mailing list