[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