[pypy-svn] r26812 - in pypy/dist/pypy: interpreter module/_weakref/test objspace/std

arigo at codespeak.net arigo at codespeak.net
Fri May 5 14:38:19 CEST 2006


Author: arigo
Date: Fri May  5 14:38:18 2006
New Revision: 26812

Modified:
   pypy/dist/pypy/interpreter/baseobjspace.py
   pypy/dist/pypy/interpreter/typedef.py
   pypy/dist/pypy/module/_weakref/test/test_weakref.py
   pypy/dist/pypy/objspace/std/typeobject.py
   pypy/dist/pypy/objspace/std/typetype.py
Log:
WeakrefableMixin causes trouble: in general we assume that mixins are not
before the normal base class.  Factored it out in a way that still allows
a nice implementation of weakrefable built-in objects.  Made functions,
methods and generators weakrefable.


Modified: pypy/dist/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/dist/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/dist/pypy/interpreter/baseobjspace.py	Fri May  5 14:38:18 2006
@@ -7,8 +7,7 @@
 from pypy.rpython.rarithmetic import r_uint, intmask
 import os
 
-__all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root',
-           'WeakrefableMixin']
+__all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root']
 
 
 class W_Root(object):
@@ -78,16 +77,6 @@
     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 14:38:18 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, WeakrefableMixin
+from pypy.interpreter.baseobjspace import Wrappable, W_Root, ObjSpace
 from pypy.interpreter.error import OperationError
 from pypy.tool.sourcetools import compile2
 from pypy.rpython.objectmodel import instantiate
@@ -16,8 +16,10 @@
         self.name = __name
         self.base = __base
         self.hasdict = '__dict__' in rawdict
+        self.weakrefable = '__weakref__' in rawdict
         if __base is not None:
             self.hasdict |= __base.hasdict
+            self.weakrefable |= __base.weakrefable
         self.rawdict = {}
         self.acceptable_as_base_class = True
         # xxx used by faking
@@ -38,7 +40,6 @@
 
 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]
@@ -54,8 +55,10 @@
     typedef = cls.typedef
     
     if hasdict and typedef.hasdict:
-        return get_unique_interplevel_subclass(cls, False, wants_slots, wants_del, weakrefable)
-    
+        hasdict = False
+    if weakrefable and typedef.weakrefable:
+        weakrefable = False
+
     name = ['User']
     if not hasdict:
         name.append('NoDict')
@@ -69,7 +72,16 @@
     name.append(cls.__name__)
     
     name = ''.join(name)
-    if wants_del:
+    if weakrefable:
+        supercls = get_unique_interplevel_subclass(cls, hasdict, wants_slots,
+                                                   wants_del, False)
+        class Proto(object):
+            _lifeline_ = None
+            def getweakref(self):
+                return self._lifeline_
+            def setweakref(self, space, weakreflifeline):
+                self._lifeline_ = weakreflifeline
+    elif wants_del:
         supercls = get_unique_interplevel_subclass(cls, hasdict, wants_slots,
                                                    False, False)
         parent_destructor = getattr(cls, '__del__', None)
@@ -135,13 +147,8 @@
     
     body = dict([(key, value)
                  for key, value in Proto.__dict__.items()
-                 if not key.startswith('_') or key == '__del__'])
-    
-    if weakrefable and not issubclass(supercls, WeakrefableMixin):
-        subcls = type(name, (WeakrefableMixin, supercls), body)
-    else:
-        subcls = type(name, (supercls,), body)
-    
+                 if not key.startswith('__') or key == '__del__'])
+    subcls = type(name, (supercls,), body)
     return subcls
 
 def make_descr_typecheck_wrapper(func, extraargs=(), cls=None):
@@ -414,6 +421,17 @@
 weakref_descr = GetSetProperty(descr_get_weakref)
 weakref_descr.name = '__weakref__'
 
+def make_weakref_descr(cls):
+    # force the interface into the given cls
+    def getweakref(self):
+        return self._lifeline_
+    def setweakref(self, space, weakreflifeline):
+        self._lifeline_ = weakreflifeline
+    cls._lifeline_ = None
+    cls.getweakref = getweakref
+    cls.setweakref = setweakref
+    return weakref_descr
+
 
 Code.typedef = TypeDef('internal-code',
     co_name = interp_attrproperty('co_name', cls=Code),
@@ -516,6 +534,7 @@
     __name__ = getset_func_name,
     __dict__ = getset_func_dict,
     __module__ = getset___module__,
+    __weakref__ = make_weakref_descr(Function),
     # XXX func_closure, etc.pp
     )
 
@@ -533,6 +552,7 @@
     __repr__ = interp2app(Method.descr_method_repr),
     __reduce__ = interp2app(Method.descr_method__reduce__,
                             unwrap_spec=['self', ObjSpace]),
+    __weakref__ = make_weakref_descr(Method),
     # XXX getattribute/setattribute etc.pp
     )
 
@@ -563,6 +583,7 @@
     __iter__   = interp2app(GeneratorIterator.descr__iter__),
     gi_running = interp_attrproperty('running', cls=GeneratorIterator),
     gi_frame   = interp_attrproperty('frame', cls=GeneratorIterator),
+    __weakref__ = make_weakref_descr(GeneratorIterator),
 )
 
 Cell.typedef = TypeDef("cell",

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 14:38:18 2006
@@ -169,32 +169,32 @@
         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
+        assert wf()(63) == 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)
+        meth = A.f
+        w_unbound = _weakref.ref(meth)
         assert w_unbound()(A()) == 42
-        w_bound = _weakref.ref(A().f)
+        meth = A().f
+        w_bound = _weakref.ref(meth)
         assert w_bound()() == 42
-        del A
+        del meth
         assert w_unbound() is None
         assert w_bound() is None
 
     def test_set_weakrefable(self):
-        skip("wip")
+        skip("missing: weakrefs to interp-level sets")
         import _weakref
         s = set([1, 2, 3, 4])
         w = _weakref.ref(s)
@@ -203,11 +203,10 @@
         assert w() is None
 
     def test_generator_weakrefable(self):
-        skip("wip")
         import _weakref
         def f(x):
             for i in range(x):
-                yield x
+                yield i
         g = f(10)
         w = _weakref.ref(g)
         r = w().next()

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 14:38:18 2006
@@ -2,7 +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.interpreter.typedef import 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
@@ -38,7 +38,7 @@
 
     return "_%s%s" % (klass, name)
 
-class W_TypeObject(WeakrefableMixin, W_Object):
+class W_TypeObject(W_Object):
     from pypy.objspace.std.typetype import type_typedef as typedef
 
     lazyloaders = {} # can be overridden by specific instances
@@ -52,7 +52,6 @@
         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
@@ -62,6 +61,7 @@
         if overridetypedef is not None:
             w_self.instancetypedef = overridetypedef
             w_self.hasdict = overridetypedef.hasdict
+            w_self.weakrefable = overridetypedef.weakrefable
             w_self.__flags__ = 0 # not a heaptype
             if overridetypedef.base is not None:
                 w_self.w_bestbase = space.gettypeobject(overridetypedef.base)
@@ -102,6 +102,7 @@
                                                 instancetypedef.name))
             w_self.instancetypedef = instancetypedef
             w_self.hasdict = False
+            w_self.weakrefable = False
             hasoldstylebase = False
             w_most_derived_base_with_slots = None
             w_newstyle = None
@@ -171,7 +172,7 @@
                                                  space.wrap("__dict__ slot disallowed: we already got one"))
                         wantdict = True
                     elif slot_name == '__weakref__':
-                        if w_self.weakrefable:
+                        if wantweakref or w_self.weakrefable:
                             raise OperationError(space.w_TypeError,
                                                  space.wrap("__weakref__ slot disallowed: we already got one"))
                                                 
@@ -313,7 +314,14 @@
             return w_self.dict_w['__module__']
         else:
             return space.wrap('__builtin__')
-        
+
+    # for now, weakref support for W_TypeObject is hard to get automatically
+    _lifeline_ = None
+    def getweakref(self):
+        return self._lifeline_
+    def setweakref(self, space, weakreflifeline):
+        self._lifeline_ = weakreflifeline
+
 
 def call__Type(space, w_type, __args__):
     # special case for type(x)

Modified: pypy/dist/pypy/objspace/std/typetype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/typetype.py	(original)
+++ pypy/dist/pypy/objspace/std/typetype.py	Fri May  5 14:38:18 2006
@@ -1,5 +1,6 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter import gateway
+from pypy.interpreter.typedef import weakref_descr
 from pypy.objspace.std.stdtypedef import *
 
 def descr__new__(space, w_typetype, w_name, w_bases, w_dict):
@@ -150,4 +151,5 @@
     mro = gateway.interp2app(descr_mro),
     __flags__ = GetSetProperty(descr__flags),
     __module__ = GetSetProperty(descr_get__module, descr_set__module),
+    __weakref__ = weakref_descr,
     )



More information about the Pypy-commit mailing list