[pypy-svn] r49677 - in pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Wed Dec 12 17:00:16 CET 2007
Author: cfbolz
Date: Wed Dec 12 17:00:15 2007
New Revision: 49677
Modified:
pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/interp_classobj.py
pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/test/test_classobj.py
Log:
binary operations
Modified: pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/interp_classobj.py
==============================================================================
--- pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/interp_classobj.py (original)
+++ pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/interp_classobj.py Wed Dec 12 17:00:15 2007
@@ -198,13 +198,52 @@
return unaryop
def make_binary_returning_notimplemented_instance_method(name):
- def richcmp(self, space, w_other):
+ def binaryop(self, space, w_other):
w_meth = self.getattr(space, space.wrap(name), False)
if w_meth is None:
return space.w_NotImplemented
return space.call_function(w_meth, w_other)
- return richcmp
+ return binaryop
+def make_binary_instance_method(name):
+ specialname = "__%s__" % (name, )
+ rspecialname = "__r%s__" % (name, )
+ objspacename = name
+ if name in ['and', 'or']:
+ objspacename = name + '_'
+
+ def binaryop(self, space, w_other):
+ w_a, w_b = _coerce_helper(space, self, w_other)
+ if w_a is None:
+ w_a = self
+ w_b = w_other
+ if w_a is self:
+ w_meth = self.getattr(space, space.wrap(specialname), False)
+ if w_meth is None:
+ return space.w_NotImplemented
+ return space.call_function(w_meth, w_b)
+ else:
+ return getattr(space, objspacename)(w_a, w_b)
+
+ def rbinaryop(self, space, w_other):
+ w_a, w_b = _coerce_helper(space, self, w_other)
+ if w_a is None or w_a is self:
+ w_meth = self.getattr(space, space.wrap(rspecialname), False)
+ if w_meth is None:
+ return space.w_NotImplemented
+ return space.call_function(w_meth, w_other)
+ else:
+ return getattr(space, objspacename)(w_b, w_a)
+ return binaryop, rbinaryop
+
+def _coerce_helper(space, w_self, w_other):
+ try:
+ w_tup = space.coerce(w_self, w_other)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ return (None, None)
+ return space.unpacktuple(w_tup, 2)
class W_InstanceObject(Wrappable):
def __init__(self, space, w_class, w_dict=None):
@@ -406,6 +445,20 @@
meth,
unwrap_spec=["self", ObjSpace, W_Root])
+for op in "or and xor lshift rshift add sub mul div mod divmod floordiv truediv".split():
+ specialname = "__%s__" % (op, )
+ rspecialname = "__r%s__" % (op, )
+ func, rfunc = make_binary_instance_method(op)
+ # fool the gateway logic by giving it a real unbound method
+ meth = new.instancemethod(func, None, W_InstanceObject)
+ rawdict[specialname] = interp2app(
+ meth,
+ unwrap_spec=["self", ObjSpace, W_Root])
+ rmeth = new.instancemethod(rfunc, None, W_InstanceObject)
+ rawdict[rspecialname] = interp2app(
+ rmeth,
+ unwrap_spec=["self", ObjSpace, W_Root])
+
W_InstanceObject.typedef = TypeDef("instance",
__new__ = interp2app(W_InstanceObject.descr_new),
__getattribute__ = interp2app(W_InstanceObject.descr_getattribute,
Modified: pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/test/test_classobj.py
==============================================================================
--- pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/test/test_classobj.py (original)
+++ pypy/branch/interplevel-oldstyle-classes/pypy/module/__builtin__/test/test_classobj.py Wed Dec 12 17:00:15 2007
@@ -400,3 +400,38 @@
class B:
__metaclass__ = nclassobj
raises(TypeError, coerce, B(), [])
+
+ def test_binaryop(self):
+ class A:
+ __metaclass__ = nclassobj
+ def __add__(self, other):
+ return 1 + other
+ a = A()
+ assert a + 1 == 2
+ assert a + 1.1 == 2.1
+
+ def test_binaryop_coerces(self):
+ class A:
+ __metaclass__ = nclassobj
+ def __add__(self, other):
+ return 1 + other
+ def __coerce__(self, other):
+ return self, int(other)
+
+ a = A()
+ assert a + 1 == 2
+ assert a + 1.1 == 2
+
+
+ def test_binaryop_calls_coerce_always(self):
+ l = []
+ class A:
+ __metaclass__ = nclassobj
+ def __coerce__(self, other):
+ l.append(other)
+
+ a = A()
+ raises(TypeError, "a + 1")
+ raises(TypeError, "a + 1.1")
+ assert l == [1, 1.1]
+
More information about the Pypy-commit
mailing list