[pypy-svn] r56022 - in pypy/dist/pypy/module/__builtin__: . test

arigo at codespeak.net arigo at codespeak.net
Sun Jun 22 13:20:40 CEST 2008


Author: arigo
Date: Sun Jun 22 13:20:40 2008
New Revision: 56022

Modified:
   pypy/dist/pypy/module/__builtin__/descriptor.py
   pypy/dist/pypy/module/__builtin__/test/test_descriptor.py
Log:
issue377 resolved

Although we need to officialize the API more,
this is roughly how we are supposed to define
subclassable built-in types from modules.


Modified: pypy/dist/pypy/module/__builtin__/descriptor.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/descriptor.py	(original)
+++ pypy/dist/pypy/module/__builtin__/descriptor.py	Sun Jun 22 13:20:40 2008
@@ -10,10 +10,9 @@
      descr_set_dict, interp_attrproperty_w
 
 class W_Super(Wrappable):
-    def __init__(self, space, w_selftype, w_starttype, w_type, w_self):
-        self.w_selftype = w_selftype
+    def __init__(self, space, w_starttype, w_objtype, w_self):
         self.w_starttype = w_starttype
-        self.w_type = w_type
+        self.w_objtype = w_objtype
         self.w_self = w_self
 
     def get(self, space, w_obj, w_type=None):
@@ -21,38 +20,38 @@
         if self.w_self is None or space.is_w(w_obj, space.w_None):
             return w(self)
         else:
-            return space.call_function(self.w_selftype, self.w_starttype, w_obj
-                                       )
+            # if type(self) is W_Super:
+            #     XXX write a fast path for this common case
+            w_selftype = space.type(w(self))
+            return space.call_function(w_selftype, 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_function(object_getattribute(space),
-                                       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 = space.w_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_function(w_get, w_self, self.w_type)
+        # only use a special logic for bound super objects and not for
+        # getting the __class__ of the super object itself.
+        if self.w_objtype is not None and name != '__class__':
+            w_value = space.lookup_in_type_starting_at(self.w_objtype,
+                                                       self.w_starttype,
+                                                       name)
+            if w_value is not None:
+                w_get = space.lookup(w_value, '__get__')
+                if w_get is None:
+                    return w_value
+                # Only pass 'obj' param if this is instance-mode super
+                # (see CPython sourceforge id #743627)
+                if self.w_self is self.w_objtype:
+                    w_obj = space.w_None
+                else:
+                    w_obj = self.w_self
+                return space.get_and_call_function(w_get, w_value,
+                                                   w_obj, self.w_objtype)
+        # fallback to object.__getattribute__()
+        return space.call_function(object_getattribute(space),
+                                   w(self), w(name))
     getattribute.unwrap_spec = ['self', ObjSpace, str]
 
-def descr_new_super(space, w_self, w_starttype, w_obj_or_type=None):
+def descr_new_super(space, w_subtype, 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:
@@ -73,7 +72,11 @@
                 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))
+    # XXX the details of how allocate_instance() should be used are not
+    # really well defined
+    w_result = space.allocate_instance(W_Super, w_subtype)
+    W_Super.__init__(w_result, space, w_starttype, w_type, w_obj_or_type)
+    return w_result
 descr_new_super.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root]
 
 W_Super.typedef = TypeDef(
@@ -99,8 +102,10 @@
         self.w_fdel = w_fdel
         self.w_doc = w_doc
 
-    def new(space, w_type, w_fget=None, w_fset=None, w_fdel=None, w_doc=None):
-        return W_Property(space, w_fget, w_fset, w_fdel, w_doc)
+    def new(space, w_subtype, w_fget=None, w_fset=None, w_fdel=None, w_doc=None):
+        w_result = space.allocate_instance(W_Property, w_subtype)
+        W_Property.__init__(w_result, space, w_fget, w_fset, w_fdel, w_doc)
+        return w_result
     new.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root, W_Root, W_Root]
 
     def get(self, space, w_obj, w_objtype=None):
@@ -129,6 +134,9 @@
     delete.unwrap_spec = ['self', ObjSpace, W_Root]
 
     def getattribute(self, space, attr):
+        # XXX fixme: this is a workaround.  It's hard but not impossible
+        # to have both a __doc__ on the 'property' type, and a __doc__
+        # descriptor that can read the docstring of 'property' instances.
         if attr == '__doc__':
             return self.w_doc
         # shortcuts
@@ -137,6 +145,9 @@
     getattribute.unwrap_spec = ['self', ObjSpace, str]
 
     def setattr(self, space, attr, w_value):
+        # XXX kill me?  This is mostly to make tests happy, raising
+        # a TypeError instead of an AttributeError and using "readonly"
+        # instead of "read-only" in the error message :-/
         raise OperationError(space.w_TypeError, space.wrap(
             "Trying to set readonly attribute %s on property" % (attr,)))
     setattr.unwrap_spec = ['self', ObjSpace, str, W_Root]

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	Sun Jun 22 13:20:40 2008
@@ -134,7 +134,6 @@
 
         assert F().meth(6) == "F(6)[mysuper]E(6)D(6)C(6)B(6)A(6)"
 
-        skip("in-progress: buggy implementation of 'super' subclasses")
         x = mysuper(F, F())
         x.foobar = 42
         assert x.foobar == 42



More information about the Pypy-commit mailing list