[pypy-svn] r55442 - in pypy/dist/pypy/objspace: . std std/test
arigo at codespeak.net
arigo at codespeak.net
Sat May 31 11:00:32 CEST 2008
Author: arigo
Date: Sat May 31 11:00:30 2008
New Revision: 55442
Modified:
pypy/dist/pypy/objspace/descroperation.py
pypy/dist/pypy/objspace/std/test/test_unicodeobject.py
pypy/dist/pypy/objspace/std/unicodeobject.py
Log:
A minimal change that fixes the bug compatibility issue with
"unicode + string subclass". The change is similar to the
Jython fix (mostly by accident, the extra check is smaller than
in Jython).
Modified: pypy/dist/pypy/objspace/descroperation.py
==============================================================================
--- pypy/dist/pypy/objspace/descroperation.py (original)
+++ pypy/dist/pypy/objspace/descroperation.py Sat May 31 11:00:30 2008
@@ -460,10 +460,20 @@
# __xxx__ and __rxxx__ methods where found by identity.
# Note that space.is_w() is potentially not happy if one of them
# is None (e.g. with the thunk space)...
- if (w_left_src is not w_right_src # XXX
- and space.is_true(space.issubtype(w_typ2, w_typ1))):
- w_obj1, w_obj2 = w_obj2, w_obj1
- w_left_impl, w_right_impl = w_right_impl, w_left_impl
+ if w_left_src is not w_right_src: # XXX
+ # -- cpython bug compatibility: see objspace/std/test/
+ # -- test_unicodeobject.test_str_unicode_concat_overrides.
+ # -- The following handles "unicode + string subclass" by
+ # -- pretending that the unicode is a superclass of the
+ # -- string, thus giving priority to the string subclass'
+ # -- __radd__() method. The case "string + unicode subclass"
+ # -- is handled directly by add__String_Unicode().
+ if symbol == '+' and space.is_w(w_typ1, space.w_unicode):
+ w_typ1 = space.w_basestring
+ # -- end of bug compatibility
+ if space.is_true(space.issubtype(w_typ2, w_typ1)):
+ w_obj1, w_obj2 = w_obj2, w_obj1
+ w_left_impl, w_right_impl = w_right_impl, w_left_impl
w_res = _invoke_binop(space, w_left_impl, w_obj1, w_obj2)
if w_res is not None:
Modified: pypy/dist/pypy/objspace/std/test/test_unicodeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_unicodeobject.py (original)
+++ pypy/dist/pypy/objspace/std/test/test_unicodeobject.py Sat May 31 11:00:30 2008
@@ -554,3 +554,52 @@
'\x00X\x00Y',
'X\x00\x00\x00Y\x00\x00\x00',
'\x00\x00\x00X\x00\x00\x00Y']
+
+ def test_call_special_methods(self):
+ # xxx not completely clear if these are implementation details or not
+ assert 'abc'.__add__(u'def') == u'abcdef'
+ assert u'abc'.__add__(u'def') == u'abcdef'
+ assert u'abc'.__add__('def') == u'abcdef'
+ # xxx CPython has no str.__radd__ and no unicode.__radd__
+
+ def test_str_unicode_concat_overrides(self):
+ "Test from Jython about being bug-compatible with CPython."
+
+ def check(value, expected):
+ assert type(value) == type(expected)
+ assert value == expected
+
+ def _test_concat(t1, t2):
+ tprecedent = str
+ if issubclass(t1, unicode) or issubclass(t2, unicode):
+ tprecedent = unicode
+
+ class SubclassB(t2):
+ def __add__(self, other):
+ return SubclassB(t2(self) + t2(other))
+ check(SubclassB('py') + SubclassB('thon'), SubclassB('python'))
+ check(t1('python') + SubclassB('3'), tprecedent('python3'))
+ check(SubclassB('py') + t1('py'), SubclassB('pypy'))
+
+ class SubclassC(t2):
+ def __radd__(self, other):
+ return SubclassC(t2(other) + t2(self))
+ check(SubclassC('stack') + SubclassC('less'), t2('stackless'))
+ check(t1('iron') + SubclassC('python'), SubclassC('ironpython'))
+ check(SubclassC('tiny') + t1('py'), tprecedent('tinypy'))
+
+ class SubclassD(t2):
+ def __add__(self, other):
+ return SubclassD(t2(self) + t2(other))
+
+ def __radd__(self, other):
+ return SubclassD(t2(other) + t2(self))
+ check(SubclassD('di') + SubclassD('ct'), SubclassD('dict'))
+ check(t1('list') + SubclassD(' comp'), SubclassD('list comp'))
+ check(SubclassD('dun') + t1('der'), SubclassD('dunder'))
+
+ _test_concat(str, str)
+ _test_concat(unicode, unicode)
+ # the following two cases are really there to emulate a CPython bug.
+ _test_concat(str, unicode) # uses hack in add__String_Unicode()
+ _test_concat(unicode, str) # uses hack in descroperation.binop_impl()
Modified: pypy/dist/pypy/objspace/std/unicodeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/unicodeobject.py (original)
+++ pypy/dist/pypy/objspace/std/unicodeobject.py Sat May 31 11:00:30 2008
@@ -100,14 +100,28 @@
return W_UnicodeObject(w_left._value + w_right._value)
def add__String_Unicode(space, w_left, w_right):
+ # this function is needed to make 'abc'.__add__(u'def') return
+ # u'abcdef' instead of NotImplemented. This is what occurs on
+ # top of CPython.
from pypy.objspace.std.unicodetype import unicode_from_string
+ # XXX fragile implementation detail: for "string + unicode subclass",
+ # if the unicode subclass overrides __radd__(), then it will be
+ # called (see test_str_unicode_concat_overrides). This occurs as a
+ # result of the following call to space.add() in which the first
+ # argument is a unicode and the second argument a subclass of unicode
+ # (and thus the usual logic about calling __radd__() first applies).
return space.add(unicode_from_string(space, w_left) , w_right)
add__Rope_Unicode = add__String_Unicode
def add__Unicode_String(space, w_left, w_right):
+ # this function is needed to make 'abc'.__radd__(u'def') return
+ # u'defabc', although it's completely unclear if that's necessary
+ # given that CPython doesn't even have a method str.__radd__().
from pypy.objspace.std.unicodetype import unicode_from_string
return space.add(w_left, unicode_from_string(space, w_right))
+ # Note about "unicode + string subclass": look for
+ # "cpython bug compatibility" in descroperation.py
add__Unicode_Rope = add__Unicode_String
More information about the Pypy-commit
mailing list