[pypy-commit] pypy default: for consistency, the in-place operators need the same bug compatibility hack as the regular operators

arigo noreply at buildbot.pypy.org
Tue May 19 16:25:02 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r77389:5acade5a80c5
Date: 2015-05-19 16:25 +0200
http://bitbucket.org/pypy/pypy/changeset/5acade5a80c5/

Log:	for consistency, the in-place operators need the same bug
	compatibility hack as the regular operators

diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -759,9 +759,26 @@
     noninplacespacemethod = specialname[3:-2]
     if noninplacespacemethod in ['or', 'and']:
         noninplacespacemethod += '_'     # not too clean
+    seq_bug_compat = (symbol == '+=' or symbol == '*=')
+    rhs_method = '__r' + specialname[3:]
+
     def inplace_impl(space, w_lhs, w_rhs):
         w_impl = space.lookup(w_lhs, specialname)
         if w_impl is not None:
+            # 'seq_bug_compat' is for cpython bug-to-bug compatibility:
+            # see objspace/test/test_descrobject.*rmul_overrides.
+            # For cases like "list += object-overriding-__radd__".
+            if (seq_bug_compat and space.type(w_lhs).flag_sequence_bug_compat
+                           and not space.type(w_rhs).flag_sequence_bug_compat):
+                w_res = _invoke_binop(space, space.lookup(w_rhs, rhs_method),
+                                      w_rhs, w_lhs)
+                if w_res is not None:
+                    return w_res
+                # xxx if __radd__ is defined but returns NotImplemented,
+                # then it might be called again below.  Oh well, too bad.
+                # Anyway that's a case where we're likely to end up in
+                # a TypeError.
+            #
             w_res = space.get_and_call_function(w_impl, w_lhs, w_rhs)
             if _check_notimplemented(space, w_res):
                 return w_res
diff --git a/pypy/objspace/test/test_descroperation.py b/pypy/objspace/test/test_descroperation.py
--- a/pypy/objspace/test/test_descroperation.py
+++ b/pypy/objspace/test/test_descroperation.py
@@ -759,6 +759,12 @@
         assert bytearray('2') * oops() == 42
         assert 1000 * oops() == 42
         assert '2'.__mul__(oops()) == '222'
+        x = '2'
+        x *= oops()
+        assert x == 42
+        x = [2]
+        x *= oops()
+        assert x == 42
 
     def test_sequence_rmul_overrides_oldstyle(self):
         class oops:
@@ -783,6 +789,12 @@
         assert [2] + A1([3]) == [2, 3]
         assert type([2] + A1([3])) is list
         assert [2] + A2([3]) == 42
+        x = "2"
+        x += A2([3])
+        assert x == 42
+        x = [2]
+        x += A2([3])
+        assert x == 42
 
     def test_data_descriptor_without_delete(self):
         class D(object):


More information about the pypy-commit mailing list