[pypy-svn] r75687 - in pypy/branch/fast-forward/pypy/objspace/std: . test

benjamin at codespeak.net benjamin at codespeak.net
Wed Jun 30 17:45:30 CEST 2010


Author: benjamin
Date: Wed Jun 30 17:45:28 2010
New Revision: 75687

Modified:
   pypy/branch/fast-forward/pypy/objspace/std/objecttype.py
   pypy/branch/fast-forward/pypy/objspace/std/test/test_typeobject.py
   pypy/branch/fast-forward/pypy/objspace/std/typeobject.py
   pypy/branch/fast-forward/pypy/objspace/std/typetype.py
Log:
support __abstractmethods__

Modified: pypy/branch/fast-forward/pypy/objspace/std/objecttype.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/objecttype.py	(original)
+++ pypy/branch/fast-forward/pypy/objspace/std/objecttype.py	Wed Jun 30 17:45:28 2010
@@ -47,7 +47,16 @@
         raise operationerrfmt(space.w_TypeError,
                               "__class__ assignment: '%s' object layout differs from '%s'",
                               w_oldcls.getname(space, '?'), w_newcls.getname(space, '?'))
-    
+
+
+app = gateway.applevel("""
+def _abstract_method_error(typ):
+    methods = ", ".join(sorted(typ.__abstractmethods__))
+    err = "Can't instantiate abstract class %s with abstract methods %s"
+    raise TypeError(err % (methods, typ.__name__))
+""")
+_abstract_method_error = app.interphook("_abstract_method_error")
+
 
 def descr__new__(space, w_type, __args__):
     from pypy.objspace.std.objectobject import W_ObjectObject
@@ -63,6 +72,8 @@
             raise OperationError(space.w_TypeError,
                                  space.wrap("default __new__ takes "
                                             "no parameters"))
+    if w_type.is_abstract():
+        _abstract_method_error(space, w_type)
     w_obj = space.allocate_instance(W_ObjectObject, w_type)
     return w_obj
 

Modified: pypy/branch/fast-forward/pypy/objspace/std/test/test_typeobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/test/test_typeobject.py	(original)
+++ pypy/branch/fast-forward/pypy/objspace/std/test/test_typeobject.py	Wed Jun 30 17:45:28 2010
@@ -103,6 +103,14 @@
 
 class AppTestTypeObject:
 
+    def test_abstract_methods(self):
+        class X(object):
+            pass
+        X.__abstractmethods__ = ("meth",)
+        raises(TypeError, X)
+        del X.__abstractmethods__
+        X()
+
     def test_call_type(self):
         assert type(42) is int
         C = type('C', (object,), {'x': lambda: 42})

Modified: pypy/branch/fast-forward/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/typeobject.py	(original)
+++ pypy/branch/fast-forward/pypy/objspace/std/typeobject.py	Wed Jun 30 17:45:28 2010
@@ -15,6 +15,7 @@
 
 from copy_reg import _HEAPTYPE
 _CPYTYPE = 1 # used for non-heap types defined in C
+_ABSTRACT = 1 << 2
 
 # from compiler/misc.py
 
@@ -358,6 +359,15 @@
     def is_cpytype(w_self):
         return w_self.__flags__ & _CPYTYPE
 
+    def is_abstract(w_self):
+        return w_self.__flags__ & _ABSTRACT
+
+    def set_abstract(w_self, abstract):
+        if abstract:
+            w_self.__flags__ |= _ABSTRACT
+        else:
+            w_self.__flags__ &= ~_ABSTRACT
+
     def issubtype(w_self, w_type):
         w_self = hint(w_self, promote=True)
         w_type = hint(w_type, promote=True)

Modified: pypy/branch/fast-forward/pypy/objspace/std/typetype.py
==============================================================================
--- pypy/branch/fast-forward/pypy/objspace/std/typetype.py	(original)
+++ pypy/branch/fast-forward/pypy/objspace/std/typetype.py	Wed Jun 30 17:45:28 2010
@@ -206,6 +206,30 @@
     w_type.mutated()
     w_type.dict_w['__module__'] = w_value
 
+def descr_get___abstractmethods__(space, w_type):
+    w_type = _check(space, w_type)
+    try:
+        return w_type.dict_w["__abstractmethods__"]
+    except KeyError:
+        raise OperationError(space.w_AttributeError,
+                             space.wrap("__abstractmethods__"))
+
+def descr_set___abstractmethods__(space, w_type, w_new):
+    w_type = _check(space, w_type)
+    w_type.dict_w["__abstractmethods__"] = w_new
+    w_type.mutated()
+    w_type.set_abstract(space.is_true(w_new))
+
+def descr_del___abstractmethods__(space, w_type):
+    w_type = _check(space, w_type)
+    try:
+        del w_type.dict_w["__abstractmethods__"]
+    except KeyError:
+        raise OperationError(space.w_AttributeError,
+                             space.wrap("__abstractmethods__"))
+    w_type.mutated()
+    w_type.set_abstract(False)
+
 def descr___subclasses__(space, w_type):
     """Return the list of immediate subclasses."""
     w_type = _check(space, w_type)
@@ -224,6 +248,9 @@
     mro = gateway.interp2app(descr_mro),
     __flags__ = GetSetProperty(descr__flags),
     __module__ = GetSetProperty(descr_get__module, descr_set__module),
+    __abstractmethods__ = GetSetProperty(descr_get___abstractmethods__,
+                                         descr_set___abstractmethods__,
+                                         descr_del___abstractmethods__),
     __subclasses__ = gateway.interp2app(descr___subclasses__),
     __weakref__ = weakref_descr,
     )



More information about the Pypy-commit mailing list