[pypy-svn] r49038 - in pypy/dist/pypy/module/__builtin__: . test
fijal at codespeak.net
fijal at codespeak.net
Sat Nov 24 14:55:24 CET 2007
Author: fijal
Date: Sat Nov 24 14:55:24 2007
New Revision: 49038
Modified:
pypy/dist/pypy/module/__builtin__/__init__.py
pypy/dist/pypy/module/__builtin__/descriptor.py
pypy/dist/pypy/module/__builtin__/test/test_descriptor.py
Log:
Move property to interp-level + port tests from cpython
Modified: pypy/dist/pypy/module/__builtin__/__init__.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/__init__.py (original)
+++ pypy/dist/pypy/module/__builtin__/__init__.py Sat Nov 24 14:55:24 2007
@@ -55,8 +55,6 @@
'vars' : 'app_inspect.vars',
'dir' : 'app_inspect.dir',
- 'property' : 'app_descriptor.property',
-
'complex' : 'app_complex.complex',
'buffer' : 'app_buffer.buffer',
@@ -127,6 +125,8 @@
'super' : 'descriptor.W_Super',
'staticmethod' : 'descriptor.StaticMethod',
'classmethod' : 'descriptor.W_ClassMethod',
+ 'property' : 'descriptor.W_Property',
+
}
def pick_builtin(self, w_globals):
Modified: pypy/dist/pypy/module/__builtin__/descriptor.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/descriptor.py (original)
+++ pypy/dist/pypy/module/__builtin__/descriptor.py Sat Nov 24 14:55:24 2007
@@ -6,6 +6,8 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter.callmethod import object_getattribute
from pypy.interpreter.function import StaticMethod, Method
+from pypy.interpreter.typedef import GetSetProperty, descr_get_dict, \
+ descr_set_dict
class W_Super(Wrappable):
def __init__(self, space, w_selftype, w_starttype, w_type, w_self):
@@ -129,3 +131,89 @@
If a class method is called for a derived class, the derived class
object is passed as the implied first argument.""",
)
+
+class W_Property(Wrappable):
+ def __init__(self, space, w_fget, w_fset, w_fdel, doc):
+ self.w_fget = w_fget
+ self.w_fset = w_fset
+ self.w_fdel = w_fdel
+ self.doc = doc
+ # eh...
+ w = space.wrap
+ self.w_dict = space.newdict()
+ for w_item, w_value in [(w('fget'), w_fget), (w('fset'), w_fset),
+ (w('fdel'), w_fdel)]:
+ space.setitem(self.w_dict, w_item, w_value)
+
+ def new(space, w_type, w_fget=None, w_fset=None, w_fdel=None, doc=''):
+ return W_Property(space, w_fget, w_fset, w_fdel, doc)
+ new.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root, W_Root, str]
+
+ def get(self, space, w_obj, w_objtype=None):
+ if space.is_w(w_obj, space.w_None):
+ return space.wrap(self)
+ if space.is_w(self.w_fget, space.w_None):
+ raise OperationError(space.w_AttributeError, space.wrap(
+ "unreadable attribute"))
+ return space.call_function(self.w_fget, w_obj)
+ get.unwrap_spec = ['self', ObjSpace, W_Root, W_Root]
+
+ def set(self, space, w_obj, w_value):
+ if space.is_w(self.w_fset, space.w_None):
+ raise OperationError(space.w_AttributeError, space.wrap(
+ "can't set attribute"))
+ space.call_function(self.w_fset, w_obj, w_value)
+ return space.w_None
+ set.unwrap_spec = ['self', ObjSpace, W_Root, W_Root]
+
+ def delete(self, space, w_obj):
+ if space.is_w(self.w_fdel, space.w_None):
+ raise OperationError(space.w_AttributeError, space.wrap(
+ "can't delete attribute"))
+ space.call_function(self.w_fdel, w_obj)
+ return space.w_None
+ delete.unwrap_spec = ['self', ObjSpace, W_Root]
+
+ def getattribute(self, space, attr):
+ if attr == '__doc__':
+ return space.wrap(self.doc)
+ # shortcuts
+ elif attr == 'fget':
+ return self.w_fget
+ elif attr == 'fset':
+ return self.w_fset
+ elif attr == 'fdel':
+ return self.w_fdel
+ return space.call_function(object_getattribute(space),
+ space.wrap(self), space.wrap(attr))
+ getattribute.unwrap_spec = ['self', ObjSpace, str]
+
+ def setattr(self, space, attr, w_value):
+ raise OperationError(space.w_TypeError, space.wrap(
+ "Trying to set readonly attribute %s on property" % (attr,)))
+ setattr.unwrap_spec = ['self', ObjSpace, str, W_Root]
+
+ def descr_get_dict(space, self):
+ return self.w_dict
+
+W_Property.typedef = TypeDef(
+ 'property',
+ __doc__ = '''property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
+
+fget is a function to be used for getting an attribute value, and likewise
+fset is a function for setting, and fdel a function for deleting, an
+attribute. Typical use is to define a managed attribute x:
+class C(object):
+ def getx(self): return self.__x
+ def setx(self, value): self.__x = value
+ def delx(self): del self.__x
+ x = property(getx, setx, delx, "I am the 'x' property.")''',
+ __new__ = interp2app(W_Property.new.im_func),
+ __get__ = interp2app(W_Property.get),
+ __set__ = interp2app(W_Property.set),
+ __delete__ = interp2app(W_Property.delete),
+ __getattribute__ = interp2app(W_Property.getattribute),
+ __dict__ = GetSetProperty(W_Property.descr_get_dict),
+ __setattr__ = interp2app(W_Property.setattr),
+)
+
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 Sat Nov 24 14:55:24 2007
@@ -224,3 +224,71 @@
raises(TypeError, "classmethod(1).__get__(1)")
+ def test_property_docstring(self):
+ assert property.__doc__.startswith('property')
+
+ class A:
+ pass
+
+ A.x = property(lambda x: x, lambda x, y: x, lambda x:x, 'xxx')
+ assert A.x.__doc__ == 'xxx'
+
+ def test_property(self):
+ class C(object):
+ def getx(self):
+ return self.__x
+ def setx(self, value):
+ self.__x = value
+ def delx(self):
+ del self.__x
+ x = property(getx, setx, delx, doc="I'm the x property.")
+ a = C()
+ assert not hasattr(a, "x")
+ a.x = 42
+ assert a._C__x == 42
+ assert a.x == 42
+ del a.x
+ assert not hasattr(a, "x")
+ assert not hasattr(a, "_C__x")
+ C.x.__set__(a, 100)
+ assert C.x.__get__(a) == 100
+ C.x.__delete__(a)
+ assert not hasattr(a, "x")
+
+ raw = C.__dict__['x']
+ assert isinstance(raw, property)
+
+ attrs = dir(raw)
+ assert "__doc__" in attrs
+ assert "fget" in attrs
+ assert "fset" in attrs
+ assert "fdel" in attrs
+
+ assert raw.__doc__ == "I'm the x property."
+ assert raw.fget is C.__dict__['getx']
+ assert raw.fset is C.__dict__['setx']
+ assert raw.fdel is C.__dict__['delx']
+
+ for attr in "__doc__", "fget", "fset", "fdel":
+ try:
+ setattr(raw, attr, 42)
+ except TypeError, msg:
+ if str(msg).find('readonly') < 0:
+ raise Exception("when setting readonly attr %r on a "
+ "property, got unexpected TypeError "
+ "msg %r" % (attr, str(msg)))
+ else:
+ raise Exception("expected TypeError from trying to set "
+ "readonly %r attr on a property" % attr)
+
+ class D(object):
+ __getitem__ = property(lambda s: 1/0)
+
+ d = D()
+ try:
+ for i in d:
+ str(i)
+ except ZeroDivisionError:
+ pass
+ else:
+ raise Exception, "expected ZeroDivisionError from bad property"
More information about the Pypy-commit
mailing list