[pypy-commit] pypy default: Pull lower, swapcase and upper into base class for str, unicode and bytearray

aliles noreply at buildbot.pypy.org
Wed Mar 14 09:20:30 CET 2012


Author: aliles
Branch: 
Changeset: r53540:434d177e26b2
Date: 2012-03-14 00:38 -0700
http://bitbucket.org/pypy/pypy/changeset/434d177e26b2/

Log:	Pull lower, swapcase and upper into base class for str, unicode and
	bytearray

diff --git a/pypy/objspace/std/abstractstring.py b/pypy/objspace/std/abstractstring.py
--- a/pypy/objspace/std/abstractstring.py
+++ b/pypy/objspace/std/abstractstring.py
@@ -28,6 +28,15 @@
     def istitle(w_self, space):
         return w_self._title(space)
 
+    def lower(w_self, space):
+        return w_self._transform(space, w_self._lower)
+
+    def swapcase(w_self, space):
+        return w_self._transform(space, w_self._swapcase)
+
+    def upper(w_self, space):
+        return w_self._transform(space, w_self._upper)
+
 
 class AbstractCharIterator(object):
 
@@ -63,6 +72,12 @@
         """ representation for debugging purposes """
         return "%s(%r)" % (w_self.__class__.__name__, w_self.raw_value())
 
+    def builder(w_self, space, size=0):
+        raise NotImplemented, "method not implemented"
+
+    def construct(w_self, space, data):
+        raise NotImplemented, "method not implemented"
+
     def immutable_unique_id(w_self, space):
         if w_self.user_overridden_class:
             return None
@@ -84,16 +99,16 @@
         return len(w_self.unwrap(space))
 
     def raw_value(w_self):
-        raise NotImplemented("method not implemented")
+        raise NotImplemented, "method not implemented"
 
     def str_w(w_self, space):
-        raise NotImplemented("method not implemented")
+        raise NotImplemented, "method not implemented"
 
     def unicode_w(w_self, space):
-        raise NotImplemented("method not implemented")
+        raise NotImplemented, "method not implemented"
 
     def unwrap(w_self, space):
-        raise NotImplemented("method not implemented")
+        raise NotImplemented, "method not implemented"
 
     @specialize.arg(2)
     def _all_true(w_self, space, func):
@@ -149,3 +164,13 @@
                 previous_is_cased = False
 
         return space.newbool(cased)
+
+    @specialize.arg(2)
+    def _transform(w_self, space, func):
+        sz = w_self.length(space)
+        it = w_self.iterator(space)
+        bd = w_self.builder(space, sz)
+        for pos in range(sz):
+            ch = it.nextchar()
+            bd.append(func(ch))
+        return w_self.construct(space, bd.build())
diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -41,6 +41,12 @@
     def __init__(w_self, data):
         w_self.data = data
 
+    def builder(w_self, space, size=0):
+        return StringBuilder(size)
+
+    def construct(w_self, space, data):
+        return W_BytearrayObject(data)
+
     def raw_value(w_self):
         return w_self.data
 
@@ -317,6 +323,15 @@
 def str_isupper__Bytearray(space, w_self):
     return w_self.isupper(space)
 
+def str_lower__Bytearray(space, w_self):
+    return w_self.lower(space)
+
+def str_upper__Bytearray(space, w_self):
+    return w_self.upper(space)
+
+def str_swapcase__Bytearray(space, w_self):
+    return w_self.swapcase(space)
+
 def str_count__Bytearray_Int_ANY_ANY(space, w_bytearray, w_char, w_start, w_stop):
     char = w_char.intval
     bytearray = w_bytearray.data
@@ -470,26 +485,11 @@
                                                          w_str2, w_max)
     return String2Bytearray(space, w_res)
 
-def str_upper__Bytearray(space, w_bytearray):
-    w_str = str__Bytearray(space, w_bytearray)
-    w_res = stringobject.str_upper__String(space, w_str)
-    return String2Bytearray(space, w_res)
-
-def str_lower__Bytearray(space, w_bytearray):
-    w_str = str__Bytearray(space, w_bytearray)
-    w_res = stringobject.str_lower__String(space, w_str)
-    return String2Bytearray(space, w_res)
-
 def str_title__Bytearray(space, w_bytearray):
     w_str = str__Bytearray(space, w_bytearray)
     w_res = stringobject.str_title__String(space, w_str)
     return String2Bytearray(space, w_res)
 
-def str_swapcase__Bytearray(space, w_bytearray):
-    w_str = str__Bytearray(space, w_bytearray)
-    w_res = stringobject.str_swapcase__String(space, w_str)
-    return String2Bytearray(space, w_res)
-
 def str_capitalize__Bytearray(space, w_bytearray):
     w_str = str__Bytearray(space, w_bytearray)
     w_res = stringobject.str_capitalize__String(space, w_str)
diff --git a/pypy/objspace/std/ropeobject.py b/pypy/objspace/std/ropeobject.py
--- a/pypy/objspace/std/ropeobject.py
+++ b/pypy/objspace/std/ropeobject.py
@@ -19,6 +19,22 @@
     str_format__String as str_format__Rope,
     DEFAULT_NOOP_TABLE)
 
+
+class RopeBuilder(object):
+    """Mimic sufficent StringBuilder API for over simple character arrays"""
+
+    def __init__(self, size=0):
+        self.data = [' '] * size
+        self.pos = 0
+
+    def append(self, ch):
+        self.data[self.pos] = ch
+        self.pos += 1
+
+    def build(self):
+        return rope.rope_from_charlist(self.data)
+
+
 class W_RopeObject(stringobject.W_AbstractStringObject,
         stringobject.Mixin_StringMethods):
     from pypy.objspace.std.stringtype import str_typedef as typedef
@@ -29,6 +45,12 @@
             assert node.is_bytestring()
         w_self._node = node
 
+    def builder(w_self, space, size=0):
+        return RopeBuilder(size)
+
+    def construct(w_self, space, data):
+        return W_RopeObject(data)
+
     def iterator(w_self, space):
         return rope.ItemIterator(w_self._node)
 
@@ -103,25 +125,14 @@
 otherwise."""
     return w_self.istitle(space)
 
-def _local_transform(node, transform):
-    l = node.length()
-    res = [' '] * l
-    iter = rope.ItemIterator(node)
-    for i in range(l):
-        ch = iter.nextchar()
-        res[i] = transform(ch)
+def str_lower__Rope(space, w_self):
+    return w_self.lower(space)
 
-    return W_RopeObject(rope.rope_from_charlist(res))
-_local_transform._annspecialcase_ = "specialize:arg(1)"
+def str_swapcase__Rope(space, w_self):
+    return w_self.swapcase(space)
 
 def str_upper__Rope(space, w_self):
-    return _local_transform(w_self._node, w_self._upper)
-
-def str_lower__Rope(space, w_self):
-    return _local_transform(w_self._node, w_self._lower)
-
-def str_swapcase__Rope(space, w_self):
-    return _local_transform(w_self._node, w_self._swapcase)
+    return w_self.upper(space)
 
 def str_capitalize__Rope(space, w_self):
     node = w_self._node
diff --git a/pypy/objspace/std/ropeunicodeobject.py b/pypy/objspace/std/ropeunicodeobject.py
--- a/pypy/objspace/std/ropeunicodeobject.py
+++ b/pypy/objspace/std/ropeunicodeobject.py
@@ -4,7 +4,6 @@
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter import gateway
 from pypy.objspace.std.stringobject import W_StringObject
-from pypy.objspace.std.unicodeobject import _normalize_index
 from pypy.objspace.std.ropeobject import W_RopeObject
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.rlib import rope
@@ -76,6 +75,22 @@
     return encode_object(space, w_unistr, encoding, errors)
 
 
+# XXX create shared base class with RopeBuilder
+class RopeUnicodeBuilder(object):
+    """Mimic sufficent StringBuilder API for over simple character arrays"""
+
+    def __init__(self, size=0):
+        self.data = [u' '] * size
+        self.pos = 0
+
+    def append(self, ch):
+        self.data[self.pos] = ch
+        self.pos += 1
+
+    def build(self):
+        return rope.rope_from_unicharlist(self.data)
+
+
 class W_RopeUnicodeObject(unicodeobject.W_AbstractUnicodeObject):
     from pypy.objspace.std.unicodetype import unicode_typedef as typedef
     _immutable_fields_ = ['_node']
@@ -83,6 +98,12 @@
     def __init__(w_self, node):
         w_self._node = node
 
+    def builder(w_self, space, size=0):
+        return RopeUnicodeBuilder(size)
+
+    def construct(w_self, space, data):
+        return W_RopeUnicodeObject(data)
+
     def iterator(w_self, space):
         return rope.ItemIterator(w_self._node)
 
@@ -404,38 +425,14 @@
         previous_is_cased = unicodedb.iscased(unichar)
     return W_RopeUnicodeObject(rope.rope_from_unicharlist(result))
 
+def unicode_lower__RopeUnicode(space, w_self):
+    return w_self.lower(space)
 
-def _local_transform(node, transform):
-    l = node.length()
-    res = [u' '] * l
-    iter = rope.ItemIterator(node)
-    for i in range(l):
-        ch = iter.nextint()
-        res[i] = transform(ch)
-
-    return W_RopeUnicodeObject(rope.rope_from_unicharlist(res))
-_local_transform._annspecialcase_ = "specialize:arg(1)"
-
-def _tolower(ordch):
-    return unichr(unicodedb.tolower(ordch))
-def unicode_lower__RopeUnicode(space, w_self):
-    return _local_transform(w_self._node, _tolower)
-
-def _toupper(ordch):
-    return unichr(unicodedb.toupper(ordch))
 def unicode_upper__RopeUnicode(space, w_self):
-    return _local_transform(w_self._node, _toupper)
-
-def _swapcase(ordch):
-    if unicodedb.islower(ordch):
-        return unichr(unicodedb.toupper(ordch))
-    elif unicodedb.isupper(ordch):
-        return unichr(unicodedb.tolower(ordch))
-    else:
-        return unichr(ordch)
+    return w_self.upper(space)
 
 def unicode_swapcase__RopeUnicode(space, w_self):
-    return _local_transform(w_self._node, _swapcase)
+    return w_self.swapcase(space)
 
 def _convert_idx_params(space, w_self, w_start, w_end):
     self = w_self._node
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -82,6 +82,12 @@
     def __init__(w_self, str):
         w_self._value = str
 
+    def builder(w_self, space, size=0):
+        return StringBuilder(size)
+
+    def construct(w_self, space, data):
+        return W_StringObject(data)
+
     def raw_value(w_self):
         return w_self._value
 
@@ -129,22 +135,14 @@
 otherwise."""
     return w_self.istitle(space)
 
-def str_upper__String(space, w_self):
-    self = w_self._value
-    return space.wrap(self.upper())
-
 def str_lower__String(space, w_self):
-    self = w_self._value
-    return space.wrap(self.lower())
+    return w_self.lower(space)
 
 def str_swapcase__String(space, w_self):
-    self = w_self._value
-    builder = StringBuilder(len(self))
-    for i in range(len(self)):
-        ch = self[i]
-        builder.append(w_self._swapcase(ch))
+    return w_self.swapcase(space)
 
-    return space.wrap(builder.build())
+def str_upper__String(space, w_self):
+    return w_self.upper(space)
 
 def str_capitalize__String(space, w_self):
     input = w_self._value
diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py
--- a/pypy/objspace/std/test/test_unicodeobject.py
+++ b/pypy/objspace/std/test/test_unicodeobject.py
@@ -284,6 +284,12 @@
         assert (u'\u019b\u1d00\u1d86\u0221\u1fb7'.capitalize() ==
                 u'\u019b\u1d00\u1d86\u0221\u1fb7')
 
+    def test_lower(self):
+        assert u"ABC".lower() == u"abc"
+
+    def test_upper(self):
+        assert u"abc".upper() == u"ABC"
+
     def test_rjust(self):
         s = u"abc"
         assert s.rjust(2) == s
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -63,10 +63,11 @@
         return unichr(unicodedb.toupper(ord(ch)))
 
     def _swapcase(self, ch):
-        if unicodedb.islower(ch):
-            return unichr(unicodedb.toupper(ord(ch)))
-        elif unicodedb.isupper(ch):
-            return unichr(unicodedb.tolower(ord(ch)))
+        num = ord(ch)
+        if unicodedb.islower(num):
+            return unichr(unicodedb.toupper(num))
+        elif unicodedb.isupper(num):
+            return unichr(unicodedb.tolower(num))
         else:
             return ch
 
@@ -79,6 +80,12 @@
         assert isinstance(unistr, unicode)
         w_self._value = unistr
 
+    def builder(w_self, space, size=0):
+        return UnicodeBuilder(size)
+
+    def construct(w_self, space, data):
+        return W_UnicodeObject(data)
+
     def raw_value(w_self):
         return w_self._value
 
@@ -457,40 +464,13 @@
     return W_UnicodeObject(builder.build())
 
 def unicode_lower__Unicode(space, w_self):
-    input = w_self._value
-    builder = UnicodeBuilder(len(input))
-    for i in range(len(input)):
-        builder.append(unichr(unicodedb.tolower(ord(input[i]))))
-    return W_UnicodeObject(builder.build())
+    return w_self.lower(space)
 
 def unicode_upper__Unicode(space, w_self):
-    input = w_self._value
-    builder = UnicodeBuilder(len(input))
-    for i in range(len(input)):
-        builder.append(unichr(unicodedb.toupper(ord(input[i]))))
-    return W_UnicodeObject(builder.build())
+    return w_self.upper(space)
 
 def unicode_swapcase__Unicode(space, w_self):
-    input = w_self._value
-    builder = UnicodeBuilder(len(input))
-    for i in range(len(input)):
-        unichar = ord(input[i])
-        if unicodedb.islower(unichar):
-            builder.append(unichr(unicodedb.toupper(unichar)))
-        elif unicodedb.isupper(unichar):
-            builder.append(unichr(unicodedb.tolower(unichar)))
-        else:
-            builder.append(input[i])
-    return W_UnicodeObject(builder.build())
-
-def _normalize_index(length, index):
-    if index < 0:
-        index += length
-        if index < 0:
-            index = 0
-    elif index > length:
-        index = length
-    return index
+    return w_self.swapcase(space)
 
 @specialize.arg(4)
 def _convert_idx_params(space, w_self, w_start, w_end, upper_bound=False):


More information about the pypy-commit mailing list