[pypy-commit] pypy py3.3: Implement abstract methods and properties: they simply fetch the
amauryfa
noreply at buildbot.pypy.org
Tue Dec 30 22:27:16 CET 2014
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3.3
Changeset: r75173:f215d396c1f4
Date: 2014-12-30 22:25 +0100
http://bitbucket.org/pypy/pypy/changeset/f215d396c1f4/
Log: Implement abstract methods and properties: they simply fetch the
__isabstractmethod__ property from the underlying callables.
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1139,6 +1139,15 @@
# Equivalent to 'obj.__class__'.
return self.type(w_obj)
+ def isabstractmethod_w(self, w_obj):
+ try:
+ w_result = self.getattr(w_obj, self.wrap("__isabstractmethod__"))
+ except OperationError, e:
+ if e.match(self, self.w_AttributeError):
+ return False
+ raise
+ return self.bool_w(self.nonzero(w_result))
+
# CPython rules allows subclasses of BaseExceptions to be exceptions.
# This is slightly less general than the case above, so we prefix
# it with exception_
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -588,6 +588,9 @@
instance.__init__(w_function)
return space.wrap(instance)
+ def descr_isabstract(self, space):
+ return space.newbool(space.isabstractmethod_w(self.w_function))
+
class ClassMethod(W_Root):
"""The classmethod objects."""
@@ -606,6 +609,10 @@
instance.__init__(w_function)
return space.wrap(instance)
+ def descr_isabstract(self, space):
+ return space.newbool(space.isabstractmethod_w(self.w_function))
+
+
class FunctionWithFixedCode(Function):
can_change_code = False
diff --git a/pypy/interpreter/test/test_objspace.py b/pypy/interpreter/test/test_objspace.py
--- a/pypy/interpreter/test/test_objspace.py
+++ b/pypy/interpreter/test/test_objspace.py
@@ -352,6 +352,37 @@
else:
assert w_res is space.w_False
+ def test_isabstract(self, space):
+ w_A = space.appexec([], """():
+ class A:
+ def f(): pass
+ f.__isabstractmethod__ = True
+
+ def g(): pass
+ g.__isabstractmethod__ = True
+ g = classmethod(g)
+
+ def h(): pass
+ h.__isabstractmethod__ = True
+ h = staticmethod(h)
+ return A""")
+ w_B = space.appexec([], """():
+ class B:
+ def f(): pass
+
+ @classmethod
+ def g(): pass
+
+ @staticmethod
+ def h(): pass
+ return B""")
+ assert space.isabstractmethod_w(space.getattr(w_A, space.wrap('f')))
+ assert space.isabstractmethod_w(space.getattr(w_A, space.wrap('g')))
+ assert space.isabstractmethod_w(space.getattr(w_A, space.wrap('h')))
+ assert not space.isabstractmethod_w(space.getattr(w_B, space.wrap('f')))
+ assert not space.isabstractmethod_w(space.getattr(w_B, space.wrap('g')))
+ assert not space.isabstractmethod_w(space.getattr(w_B, space.wrap('h')))
+
class TestModuleMinimal:
def test_sys_exists(self):
assert self.space.sys
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -882,6 +882,7 @@
__get__ = interp2app(StaticMethod.descr_staticmethod_get),
__new__ = interp2app(StaticMethod.descr_staticmethod__new__.im_func),
__func__= interp_attrproperty_w('w_function', cls=StaticMethod),
+ __isabstractmethod__ = GetSetProperty(StaticMethod.descr_isabstract),
)
ClassMethod.typedef = TypeDef(
@@ -889,6 +890,7 @@
__new__ = interp2app(ClassMethod.descr_classmethod__new__.im_func),
__get__ = interp2app(ClassMethod.descr_classmethod_get),
__func__= interp_attrproperty_w('w_function', cls=ClassMethod),
+ __isabstractmethod__ = GetSetProperty(ClassMethod.descr_isabstract),
__doc__ = """classmethod(function) -> class method
Convert a function to be a class method.
diff --git a/pypy/module/__builtin__/descriptor.py b/pypy/module/__builtin__/descriptor.py
--- a/pypy/module/__builtin__/descriptor.py
+++ b/pypy/module/__builtin__/descriptor.py
@@ -2,8 +2,8 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter.function import StaticMethod, ClassMethod
from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
-from pypy.interpreter.typedef import (TypeDef, interp_attrproperty_w,
- generic_new_descr)
+from pypy.interpreter.typedef import (
+ TypeDef, interp_attrproperty_w, generic_new_descr, GetSetProperty)
from pypy.objspace.descroperation import object_getattribute
@@ -199,6 +199,11 @@
w_type = self.getclass(space)
return space.call_function(w_type, w_getter, w_setter, w_deleter, w_doc)
+ def descr_isabstract(self, space):
+ return space.newbool(space.isabstractmethod_w(self.w_fget) or
+ space.isabstractmethod_w(self.w_fset) or
+ space.isabstractmethod_w(self.w_fdel))
+
W_Property.typedef = TypeDef(
'property',
__doc__ = '''property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
@@ -216,6 +221,7 @@
__get__ = interp2app(W_Property.get),
__set__ = interp2app(W_Property.set),
__delete__ = interp2app(W_Property.delete),
+ __isabstractmethod__ = GetSetProperty(W_Property.descr_isabstract),
fdel = interp_attrproperty_w('w_fdel', W_Property),
fget = interp_attrproperty_w('w_fget', W_Property),
fset = interp_attrproperty_w('w_fset', W_Property),
diff --git a/pypy/module/__builtin__/test/test_descriptor.py b/pypy/module/__builtin__/test/test_descriptor.py
--- a/pypy/module/__builtin__/test/test_descriptor.py
+++ b/pypy/module/__builtin__/test/test_descriptor.py
@@ -401,6 +401,12 @@
del x.x
assert x.z == 42
+ def test_abstract_property(self):
+ def foo(self): pass
+ foo.__isabstractmethod__ = True
+ foo = property(foo)
+ assert foo.__isabstractmethod__ is True
+
def test___class___variable(self):
class X:
def f(self):
More information about the pypy-commit
mailing list