[pypy-svn] r26780 - in pypy/dist/pypy: doc/tool interpreter module/_weakref module/_weakref/test objspace/std objspace/std/test

cfbolz at codespeak.net cfbolz at codespeak.net
Fri May 5 02:47:36 CEST 2006


Author: cfbolz
Date: Fri May  5 02:47:35 2006
New Revision: 26780

Modified:
   pypy/dist/pypy/doc/tool/makecontributor.py
   pypy/dist/pypy/interpreter/baseobjspace.py
   pypy/dist/pypy/interpreter/typedef.py
   pypy/dist/pypy/module/_weakref/interp__weakref.py
   pypy/dist/pypy/module/_weakref/test/test_weakref.py
   pypy/dist/pypy/objspace/std/objspace.py
   pypy/dist/pypy/objspace/std/test/test_typeobject.py
   pypy/dist/pypy/objspace/std/typeobject.py
Log:
don't add the field needed for weakref to all objects. Add support for
the __weakref__ descriptor.


Modified: pypy/dist/pypy/doc/tool/makecontributor.py
==============================================================================
--- pypy/dist/pypy/doc/tool/makecontributor.py	(original)
+++ pypy/dist/pypy/doc/tool/makecontributor.py	Fri May  5 02:47:35 2006
@@ -26,9 +26,8 @@
 import uconf # http://codespeak.net/svn/uconf/dist/uconf 
 
 for author, count in items: 
-    user = uconf.system.User(author)
-    realname = user.realname 
-    email = user.email 
+    #user = uconf.system.User(author)
+    #realname = user.realname 
     #print "%5d" % count, "   ", realname, "<%s>" % email 
-    print "   ", realname, "<%s>" % email 
+    print count, "   ", author 
 

Modified: pypy/dist/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/dist/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/dist/pypy/interpreter/baseobjspace.py	Fri May  5 02:47:35 2006
@@ -7,7 +7,8 @@
 from pypy.rpython.rarithmetic import r_uint, intmask
 import os
 
-__all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root']
+__all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root',
+           'WeakrefableMixin']
 
 
 class W_Root(object):
@@ -61,13 +62,32 @@
     def identity_hash(self, space):
         return space.wrap(intmask(hash(self))) #space.id(self)
 
+    # used by _weakref implemenation
+
+    def getweakref(self):
+        return None
+
+    def setweakref(self, space, weakreflifeline):
+        typename = space.type(self).getname(space, '?')
+        raise OperationError(space.w_TypeError, space.wrap(
+            "cannot create weak reference to '%s' object" % typename))
+
 class Wrappable(W_Root):
     """A subclass of Wrappable is an internal, interpreter-level class
     that can nevertheless be exposed at application-level by space.wrap()."""
     def __spacebind__(self, space):
         return self
 
+class WeakrefableMixin(object):
+    _mixin_ = True
+    __lifeline__ = None
+
+    def getweakref(self):
+        return self.__lifeline__
 
+    def setweakref(self, space, weakreflifeline):
+        self.__lifeline__ = weakreflifeline
+    
 class InternalSpaceCache(Cache):
     """A generic cache for an object space.  Arbitrary information can
     be attached to the space by defining a function or class 'f' which

Modified: pypy/dist/pypy/interpreter/typedef.py
==============================================================================
--- pypy/dist/pypy/interpreter/typedef.py	(original)
+++ pypy/dist/pypy/interpreter/typedef.py	Fri May  5 02:47:35 2006
@@ -5,7 +5,7 @@
 import py
 from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.argument import Arguments
-from pypy.interpreter.baseobjspace import Wrappable, W_Root, ObjSpace
+from pypy.interpreter.baseobjspace import Wrappable, W_Root, ObjSpace, WeakrefableMixin
 from pypy.interpreter.error import OperationError
 from pypy.tool.sourcetools import compile2
 from pypy.rpython.objectmodel import instantiate
@@ -36,26 +36,25 @@
         return True
 
 
-def get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel=False):
-    key = cls, hasdict, wants_slots, needsdel
+def get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel=False,
+                                    weakrefable=False):
+    weakrefable = weakrefable and not issubclass(cls, WeakrefableMixin)
+    key = cls, hasdict, wants_slots, needsdel, weakrefable
     try:
         return _subclass_cache[key]
     except KeyError:
-        name = hasdict and "WithDict" or "NoDict"
-        name += wants_slots and "WithSlots" or "NoSlots"
-        name += needsdel and "WithDel" or "NoDel"
-        subcls = _buildusercls(cls, hasdict, wants_slots, needsdel)
+        subcls = _buildusercls(cls, hasdict, wants_slots, needsdel, weakrefable)
         _subclass_cache[key] = subcls
         return subcls
 get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo"
 _subclass_cache = {}
 
-def _buildusercls(cls, hasdict, wants_slots, wants_del):
+def _buildusercls(cls, hasdict, wants_slots, wants_del, weakrefable):
     "NOT_RPYTHON: initialization-time only"
     typedef = cls.typedef
     
     if hasdict and typedef.hasdict:
-        return get_unique_interplevel_subclass(cls, False, wants_slots, wants_del)
+        return get_unique_interplevel_subclass(cls, False, wants_slots, wants_del, weakrefable)
     
     name = ['User']
     if not hasdict:
@@ -64,12 +63,15 @@
         name.append('WithSlots')
     if wants_del:
         name.append('WithDel')
+    if weakrefable:
+        name.append('Weakrefable')
+    
     name.append(cls.__name__)
     
     name = ''.join(name)
-    
     if wants_del:
-        supercls = get_unique_interplevel_subclass(cls, hasdict, wants_slots, False)
+        supercls = get_unique_interplevel_subclass(cls, hasdict, wants_slots,
+                                                   False, False)
         parent_destructor = getattr(cls, '__del__', None)
         class Proto(object):
             def __del__(self):
@@ -81,7 +83,7 @@
                 if parent_destructor is not None:
                     parent_destructor(self)
     elif wants_slots:
-        supercls = get_unique_interplevel_subclass(cls, hasdict, False, False)
+        supercls = get_unique_interplevel_subclass(cls, hasdict, False, False, False)
         
         class Proto(object):
             def user_setup_slots(self, nslots):
@@ -93,7 +95,7 @@
             def getslotvalue(self, index):
                 return self.slots_w[index]
     elif hasdict:
-        supercls = get_unique_interplevel_subclass(cls, False, False, False)
+        supercls = get_unique_interplevel_subclass(cls, False, False, False, False)
         
         class Proto(object):
             def getdict(self):
@@ -135,7 +137,10 @@
                  for key, value in Proto.__dict__.items()
                  if not key.startswith('_') or key == '__del__'])
     
-    subcls = type(name, (supercls,), body)
+    if weakrefable and not issubclass(supercls, WeakrefableMixin):
+        subcls = type(name, (WeakrefableMixin, supercls), body)
+    else:
+        subcls = type(name, (supercls,), body)
     
     return subcls
 
@@ -374,6 +379,12 @@
 def descr_set_dict(space, w_obj, w_dict):
     w_obj.setdict(space, w_dict)
 
+def descr_get_weakref(space, w_obj):
+    lifeline = w_obj.getweakref()
+    if lifeline is None:
+        return space.w_None
+    return lifeline.get_any_weakref(space)
+
 def generic_ne(space, w_obj1, w_obj2):
     if space.eq_w(w_obj1, w_obj2):
         return space.w_False
@@ -400,6 +411,10 @@
     w_docstring = space.wrap(code.getdocstring())
     return space.newtuple([w_docstring])
 
+weakref_descr = GetSetProperty(descr_get_weakref)
+weakref_descr.name = '__weakref__'
+
+
 Code.typedef = TypeDef('internal-code',
     co_name = interp_attrproperty('co_name', cls=Code),
     co_varnames = GetSetProperty(fget_co_varnames, cls=Code),

Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py
==============================================================================
--- pypy/dist/pypy/module/_weakref/interp__weakref.py	(original)
+++ pypy/dist/pypy/module/_weakref/interp__weakref.py	Fri May  5 02:47:35 2006
@@ -7,9 +7,6 @@
 from pypy.rpython.objectmodel import cast_address_to_object, cast_object_to_address
 from pypy.rpython.lltypesystem.llmemory import NULL
 
-W_Weakrefable = W_Root
-W_Weakrefable.__lifeline__ = None
-
 
 class WeakrefLifeline(object):
     def __init__(self):
@@ -67,6 +64,18 @@
         if self.cached_weakref_index == index:
             self.cached_weakref_index = -1
 
+    def get_any_weakref(self, space):
+        if self.cached_weakref_index != -1:
+            return cast_address_to_object(
+                self.addr_refs[self.cached_weakref_index], W_WeakrefBase)
+        w_weakreftype = space.gettypeobject(W_Weakref.typedef)
+        for i in range(len(self.addr_refs)):
+            addr = self.addr_refs[i]
+            if addr != NULL:
+                w_ref = cast_address_to_object(addr, W_WeakrefBase)
+                if space.is_true(space.isinstance(w_ref, w_weakreftype)):
+                    return w_ref
+        return space.w_None
 
 class W_WeakrefBase(Wrappable):
     def __init__(w_self, space, lifeline, index, w_obj, w_callable):
@@ -79,7 +88,7 @@
     def dereference(self):
         if self.address == NULL:
             return self.space.w_None
-        return cast_address_to_object(self.address, W_Weakrefable)
+        return cast_address_to_object(self.address, W_Root)
         
     def invalidate(w_self):
         w_self.address = NULL
@@ -113,10 +122,11 @@
         return self.w_hash
 
 def descr__new__weakref(space, w_subtype, w_obj, w_callable=None):
-    assert isinstance(w_obj, W_Weakrefable)
-    if w_obj.__lifeline__ is None:
-        w_obj.__lifeline__ = WeakrefLifeline()
-    return w_obj.__lifeline__.get_weakref(space, w_subtype, w_obj, w_callable)
+    lifeline = w_obj.getweakref()
+    if lifeline is None:
+        lifeline = WeakrefLifeline()
+        w_obj.setweakref(space, lifeline)
+    return lifeline.get_weakref(space, w_subtype, w_obj, w_callable)
 
 def descr__eq__(space, ref1, ref2):
     if ref1.address == NULL or ref2.address == NULL:
@@ -138,12 +148,10 @@
 
 
 def getweakrefcount(space, w_obj):
-    if not isinstance(w_obj, W_Weakrefable):
-        return space.wrap(0)
-    if w_obj.__lifeline__ is None:
+    lifeline = w_obj.getweakref()
+    if lifeline is None:
         return space.wrap(0)
     else:
-        lifeline = w_obj.__lifeline__
         result = 0
         for i in range(len(lifeline.addr_refs)):
             if lifeline.addr_refs[i] != NULL:
@@ -151,12 +159,10 @@
         return space.wrap(result)
 
 def getweakrefs(space, w_obj):
-    if not isinstance(w_obj, W_Weakrefable):
-        return space.newlist([])
-    if w_obj.__lifeline__ is None:
+    lifeline = w_obj.getweakref()
+    if lifeline is None:
         return space.newlist([])
     else:
-        lifeline = w_obj.__lifeline__
         result = []
         for i in range(len(lifeline.addr_refs)):
             addr = lifeline.addr_refs[i]
@@ -178,10 +184,11 @@
         return space.call_args(w_obj, __args__)
 
 def proxy(space, w_obj, w_callable=None):
-    assert isinstance(w_obj, W_Weakrefable)
-    if w_obj.__lifeline__ is None:
-        w_obj.__lifeline__ = WeakrefLifeline()
-    return w_obj.__lifeline__.get_proxy(space, w_obj, w_callable)
+    lifeline = w_obj.getweakref()
+    if lifeline is None:
+        lifeline = WeakrefLifeline()
+        w_obj.setweakref(space, lifeline) 
+    return lifeline.get_proxy(space, w_obj, w_callable)
 
 def descr__new__proxy(space, w_subtype, w_obj, w_callable=None):
     raise OperationError(

Modified: pypy/dist/pypy/module/_weakref/test/test_weakref.py
==============================================================================
--- pypy/dist/pypy/module/_weakref/test/test_weakref.py	(original)
+++ pypy/dist/pypy/module/_weakref/test/test_weakref.py	Fri May  5 02:47:35 2006
@@ -13,6 +13,7 @@
         assert _weakref.getweakrefcount(a) == 0
         ref = _weakref.ref(a)
         assert ref() is a
+        assert a.__weakref__ is ref
         assert _weakref.getweakrefcount(a) == 1
         del a
         assert ref() is None
@@ -144,6 +145,78 @@
         w = _weakref.ref(A())
         raises(TypeError, hash, w)
 
+    def test_weakref_subclassing(self):
+        import _weakref
+        class A(object):
+            pass
+        class Ref(_weakref.ref):
+            pass
+        def callable(ref):
+            b.a = 42
+        a = A()
+        b = A()
+        b.a = 1
+        w = Ref(a, callable)
+        assert a.__weakref__ is w
+        assert b.__weakref__ is None
+        w1 = _weakref.ref(a)
+        w2 = _weakref.ref(a, callable)
+        assert a.__weakref__ is w1
+        del a
+        assert w1() is None
+        assert w() is None
+        assert w2() is None
+        assert b.a == 42
+
+    def test_function_weakrefable(self):
+        skip("wip")
+        import _weakref
+        def f(x):
+            return 42
+        wf = _weakref.ref(f)
+        assert wf()() == 42
+        del f
+        assert wf() is None
+
+    def test_method_weakrefable(self):
+        skip("wip")
+        import _weakref
+        class A(object):
+            def f(self):
+                return 42
+        a = A()
+        w_unbound = _weakref.ref(A.f)
+        assert w_unbound()(A()) == 42
+        w_bound = _weakref.ref(A().f)
+        assert w_bound()() == 42
+        del A
+        assert w_unbound() is None
+        assert w_bound() is None
+
+    def test_set_weakrefable(self):
+        skip("wip")
+        import _weakref
+        s = set([1, 2, 3, 4])
+        w = _weakref.ref(s)
+        assert w() is s
+        del s
+        assert w() is None
+
+    def test_generator_weakrefable(self):
+        skip("wip")
+        import _weakref
+        def f(x):
+            for i in range(x):
+                yield x
+        g = f(10)
+        w = _weakref.ref(g)
+        r = w().next()
+        assert r == 0
+        r = g.next()
+        assert r == 1
+        del g
+        assert w() is None
+
     def test_weakref_subclass_with_del(self):
         import _weakref
         class Ref(_weakref.ref):

Modified: pypy/dist/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/std/objspace.py	(original)
+++ pypy/dist/pypy/objspace/std/objspace.py	Fri May  5 02:47:35 2006
@@ -417,7 +417,7 @@
             instance =  instantiate(cls)
         else:
             w_subtype = w_type.check_user_subclass(w_subtype)
-            subcls = get_unique_interplevel_subclass(cls, w_subtype.hasdict, w_subtype.nslots != 0, w_subtype.needsdel)
+            subcls = get_unique_interplevel_subclass(cls, w_subtype.hasdict, w_subtype.nslots != 0, w_subtype.needsdel, w_subtype.weakrefable)
             instance = instantiate(subcls)
             instance.user_setup(self, w_subtype, w_subtype.nslots)
         assert isinstance(instance, cls)

Modified: pypy/dist/pypy/objspace/std/test/test_typeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_typeobject.py	(original)
+++ pypy/dist/pypy/objspace/std/test/test_typeobject.py	Fri May  5 02:47:35 2006
@@ -321,7 +321,7 @@
         class C:
             __metaclass__ = T
         assert d
-        assert sorted(d[0].keys()) == ['__dict__','__doc__','__metaclass__','__module__']
+        assert sorted(d[0].keys()) == ['__dict__','__doc__','__metaclass__','__module__', '__weakref__']
         d = []
         class T(type):
             def mro(cls):

Modified: pypy/dist/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/typeobject.py	(original)
+++ pypy/dist/pypy/objspace/std/typeobject.py	Fri May  5 02:47:35 2006
@@ -2,6 +2,7 @@
 from pypy.interpreter.function import Function, StaticMethod
 from pypy.interpreter.argument import Arguments
 from pypy.interpreter import gateway
+from pypy.interpreter.typedef import WeakrefableMixin, weakref_descr
 from pypy.objspace.std.stdtypedef import std_dict_descr, issubtypedef, Member
 from pypy.objspace.std.objecttype import object_typedef
 from pypy.objspace.std.dictproxyobject import W_DictProxyObject
@@ -37,7 +38,7 @@
 
     return "_%s%s" % (klass, name)
 
-class W_TypeObject(W_Object):
+class W_TypeObject(WeakrefableMixin, W_Object):
     from pypy.objspace.std.typetype import type_typedef as typedef
 
     lazyloaders = {} # can be overridden by specific instances
@@ -51,6 +52,7 @@
         w_self.ensure_static__new__()
         w_self.nslots = 0
         w_self.needsdel = False
+        w_self.weakrefable = False
         w_self.w_bestbase = None
 
         # make sure there is a __doc__ in dict_w
@@ -121,6 +123,7 @@
                                                             "multiple inheritance"))
                 w_self.hasdict = w_self.hasdict or w_base.hasdict
                 w_self.needsdel = w_self.needsdel or w_base.needsdel
+                w_self.weakrefable = w_self.weakrefable or w_base.weakrefable
             if not w_newstyle: # only classic bases
                 raise OperationError(space.w_TypeError,
                                      space.wrap("a new-style class can't have only classic bases"))
@@ -135,8 +138,10 @@
                 w_self.w_bestbase = w_newstyle
 
             wantdict = True
+            wantweakref = True
             if '__slots__' in dict_w:
                 wantdict = False
+                wantweakref = False
 
                 w_slots = dict_w['__slots__']
                 if space.is_true(space.isinstance(w_slots, space.w_str)):
@@ -165,6 +170,12 @@
                             raise OperationError(space.w_TypeError,
                                                  space.wrap("__dict__ slot disallowed: we already got one"))
                         wantdict = True
+                    elif slot_name == '__weakref__':
+                        if w_self.weakrefable:
+                            raise OperationError(space.w_TypeError,
+                                                 space.wrap("__weakref__ slot disallowed: we already got one"))
+                                                
+                        wantweakref = True
                     else:
                         # create member
                         slot_name = _mangle(slot_name, name)
@@ -182,6 +193,9 @@
                 w_self.hasdict = True
             if '__del__' in dict_w:
                 w_self.needsdel = True
+            if wantweakref and not w_self.weakrefable:
+                w_self.dict_w['__weakref__'] = space.wrap(weakref_descr)
+                w_self.weakrefable = True
             w_type = space.type(w_self)
             if not space.is_w(w_type, space.w_type):
                 w_self.mro_w = []



More information about the Pypy-commit mailing list