[pypy-svn] r29323 - in pypy/dist/pypy/objspace/std: . test

arigo at codespeak.net arigo at codespeak.net
Sun Jun 25 17:51:29 CEST 2006


Author: arigo
Date: Sun Jun 25 17:51:26 2006
New Revision: 29323

Added:
   pypy/dist/pypy/objspace/std/strsliceobject.py   (contents, props changed)
   pypy/dist/pypy/objspace/std/test/test_strsliceobject.py   (contents, props changed)
Modified:
   pypy/dist/pypy/objspace/std/model.py
   pypy/dist/pypy/objspace/std/stringobject.py
   pypy/dist/pypy/objspace/std/stringtype.py
Log:
Experimental (and turned off by default): W_StringSliceObject,
representing a slice of an RPython string.  Only a few operations are
implemented on it, but by automatic delegation to W_StringObject it
still works transparently.

I guess this should at least check how large the slice will be, and only
use W_StringSliceObject for "large enough" slices.



Modified: pypy/dist/pypy/objspace/std/model.py
==============================================================================
--- pypy/dist/pypy/objspace/std/model.py	(original)
+++ pypy/dist/pypy/objspace/std/model.py	Sun Jun 25 17:51:26 2006
@@ -9,6 +9,7 @@
 import pypy.interpreter.special
 
 WITHSMALLINT = False
+WITHSTRSLICE = False
 
 class StdTypeModel:
 
@@ -53,6 +54,8 @@
         from pypy.objspace.std import listobject
         from pypy.objspace.std import dictobject
         from pypy.objspace.std import stringobject
+        if WITHSTRSLICE:
+            from pypy.objspace.std import strsliceobject
         from pypy.objspace.std import typeobject
         from pypy.objspace.std import sliceobject
         from pypy.objspace.std import longobject
@@ -93,6 +96,8 @@
         self.typeorder[setobject.W_SetIterObject] = []
         if WITHSMALLINT:
             self.typeorder[smallintobject.W_SmallIntObject] = []
+        if WITHSTRSLICE:
+            self.typeorder[strsliceobject.W_StringSliceObject] = []
         for type in self.typeorder:
             self.typeorder[type].append((type, None))
 
@@ -140,6 +145,14 @@
          (unicodeobject.W_UnicodeObject, unicodeobject.delegate_String2Unicode),
             ]
 
+        if WITHSTRSLICE:
+            self.typeorder[strsliceobject.W_StringSliceObject] += [
+                (stringobject.W_StringObject,
+                                       strsliceobject.delegate_slice2str),
+                (unicodeobject.W_UnicodeObject,
+                                       strsliceobject.delegate_slice2unicode),
+                ]
+
         # put W_Root everywhere
         self.typeorder[W_Root] = []
         for type in self.typeorder:

Modified: pypy/dist/pypy/objspace/std/stringobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/stringobject.py	(original)
+++ pypy/dist/pypy/objspace/std/stringobject.py	Sun Jun 25 17:51:26 2006
@@ -11,8 +11,7 @@
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.objspace.std.tupleobject import W_TupleObject
 
-# XXX consider reimplementing _value to be a list of characters
-#     instead of a plain string
+from pypy.objspace.std.stringtype import sliced
 
 
 class W_StringObject(W_Object):
@@ -846,7 +845,7 @@
         str = ""
     elif step == 1:
         assert start >= 0 and stop >= 0
-        str = s[start:stop]
+        return sliced(s, start, stop)
     else:
         str = "".join([s[start + i*step] for i in range(sl)])
     return W_StringObject(str)

Modified: pypy/dist/pypy/objspace/std/stringtype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/stringtype.py	(original)
+++ pypy/dist/pypy/objspace/std/stringtype.py	Sun Jun 25 17:51:26 2006
@@ -3,6 +3,17 @@
 
 from sys import maxint
 
+from pypy.objspace.std.model import WITHSTRSLICE
+if WITHSTRSLICE:
+    def sliced(s, start, stop):
+        from pypy.objspace.std.strsliceobject import W_StringSliceObject
+        return W_StringSliceObject(s, start, stop)
+else:
+    def sliced(s, start, stop):
+        from pypy.objspace.std.stringobject import W_StringObject
+        return W_StringObject(s[start:stop])
+
+
 str_join    = SMM('join', 2,
                   doc='S.join(sequence) -> string\n\nReturn a string which is'
                       ' the concatenation of the strings in the\nsequence. '

Added: pypy/dist/pypy/objspace/std/strsliceobject.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/std/strsliceobject.py	Sun Jun 25 17:51:26 2006
@@ -0,0 +1,131 @@
+from pypy.objspace.std.objspace import *
+from pypy.objspace.std.stringobject import W_StringObject
+from pypy.objspace.std.unicodeobject import delegate_String2Unicode
+
+
+class W_StringSliceObject(W_Object):
+    from pypy.objspace.std.stringtype import str_typedef as typedef
+
+    def __init__(w_self, str, start, stop):
+        w_self.str = str
+        w_self.start = start
+        w_self.stop = stop
+
+    def force(w_self):
+        str = w_self.str[w_self.start:w_self.stop]
+        w_self.str = str
+        w_self.start = 0
+        w_self.stop = len(str)
+        return str
+
+    def __repr__(w_self):
+        """ representation for debugging purposes """
+        return "%s(%r[%d:%d])" % (w_self.__class__.__name__,
+                                  w_self.str, w_self.start, w_self.stop)
+
+
+registerimplementation(W_StringSliceObject)
+
+
+def delegate_slice2str(space, w_strslice):
+    return W_StringObject(w_strslice.force())
+
+def delegate_slice2unicode(space, w_strslice):
+    w_str = W_StringObject(w_strslice.force())
+    return delegate_String2Unicode(space, w_str)
+
+# ____________________________________________________________
+
+def contains__StringSlice_String(space, w_self, w_sub):
+    sub = w_sub._value
+    return space.newbool(w_self.str.find(sub, w_self.start, w_self.stop) >= 0)
+
+
+def _convert_idx_params(space, w_self, w_sub, w_start, w_end):
+    length = w_self.stop - w_self.start
+    sub = w_sub._value
+    w_start = slicetype.adapt_bound(space, w_start, space.wrap(length))
+    w_end = slicetype.adapt_bound(space, w_end, space.wrap(length))
+
+    start = space.int_w(w_start)
+    end = space.int_w(w_end)
+    assert start >= 0
+    assert end >= 0
+
+    return (w_self.str, sub, w_self.start + start, end)
+
+
+def str_find__StringSlice_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
+
+    (self, sub, start, end) =  _convert_idx_params(space, w_self, w_sub, w_start, w_end)
+    res = self.find(sub, start, end)
+    return space.wrap(res)
+
+def str_rfind__StringSlice_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
+
+    (self, sub, start, end) =  _convert_idx_params(space, w_self, w_sub, w_start, w_end)
+    res = self.rfind(sub, start, end)
+    return space.wrap(res)
+
+def str_index__StringSlice_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
+
+    (self, sub, start, end) =  _convert_idx_params(space, w_self, w_sub, w_start, w_end)
+    res = self.find(sub, start, end)
+    if res < 0:
+        raise OperationError(space.w_ValueError,
+                             space.wrap("substring not found in string.index"))
+
+    return space.wrap(res)
+
+
+def str_rindex__StringSlice_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
+
+    (self, sub, start, end) =  _convert_idx_params(space, w_self, w_sub, w_start, w_end)
+    res = self.rfind(sub, start, end)
+    if res < 0:
+        raise OperationError(space.w_ValueError,
+                             space.wrap("substring not found in string.rindex"))
+
+    return space.wrap(res)
+
+
+def str_w__StringSlice(space, w_str):
+    return w_str.force()
+
+
+def getitem__StringSlice_ANY(space, w_str, w_index):
+    ival = space.int_w(w_index)
+    slen = w_str.stop - w_str.start
+    if ival < 0:
+        ival += slen
+    if ival < 0 or ival >= slen:
+        exc = space.call_function(space.w_IndexError,
+                                  space.wrap("string index out of range"))
+        raise OperationError(space.w_IndexError, exc)
+    return W_StringObject(w_str.str[w_str.start + ival])
+
+def getitem__StringSlice_Slice(space, w_str, w_slice):
+    w = space.wrap
+    length = w_str.stop - w_str.start
+    start, stop, step, sl = w_slice.indices4(space, length)
+    if sl == 0:
+        str = ""
+    else:
+        s = w_str.str
+        start = w_str.start + start
+        if step == 1:
+            stop = w_str.start + stop
+            assert start >= 0 and stop >= 0
+            return W_StringSliceObject(s, start, stop)
+        else:
+            str = "".join([s[start + i*step] for i in range(sl)])
+    return W_StringObject(str)
+
+def len__StringSlice(space, w_str):
+    return space.wrap(w_str.stop - w_str.start)
+
+
+def str__StringSlice(space, w_str):
+    if type(w_str) is W_StringSliceObject:
+        return w_str
+    return W_StringSliceObject(w_str.str, w_str.start, w_str.stop)

Added: pypy/dist/pypy/objspace/std/test/test_strsliceobject.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/std/test/test_strsliceobject.py	Sun Jun 25 17:51:26 2006
@@ -0,0 +1,79 @@
+import autopath, py
+
+from pypy.objspace.std.model import WITHSTRSLICE
+if not WITHSTRSLICE:
+    py.test.skip("WITHSTRSLICE is not enabled")
+
+
+class AppTestStringObject:
+
+    def test_basic(self):
+        import sys
+        def slice(s): return (s*3)[len(s):-len(s)]
+        s = slice('0123456789')
+        assert len(s) == 10
+        assert s[5] == '5'
+        assert s[-2] == '8'
+        assert s[3:7] == '3456'
+        assert 'W_StringSliceObject' in sys.pypy_repr(s)
+        assert 'W_StringSliceObject' in sys.pypy_repr(s[3:7])
+
+    def test_find(self):
+        def slice(s): return (s*3)[len(s):-len(s)]
+        assert slice('abcdefghiabc').find('abc') == 0
+        assert slice('abcdefghiabc').find('abc', 1) == 9
+        assert slice('abcdefghiabc').find('def', 4) == -1
+
+    def test_index(self):
+        from sys import maxint
+        def slice(s): return (s*3)[len(s):-len(s)]
+        assert slice('abcdefghiabc').index('') == 0
+        assert slice('abcdefghiabc').index('def') == 3
+        assert slice('abcdefghiabc').index('abc') == 0
+        assert slice('abcdefghiabc').index('abc', 1) == 9
+        assert slice('abcdefghiabc').index('def', -4*maxint, 4*maxint) == 3
+        raises(ValueError, slice('abcdefghiabc').index, 'hib')
+        raises(ValueError, slice('abcdefghiab').index, 'abc', 1)
+        raises(ValueError, slice('abcdefghi').index, 'ghi', 8)
+        raises(ValueError, slice('abcdefghi').index, 'ghi', -1)
+        raises(TypeError, slice('abcdefghijklmn').index, 'abc', 0, 0.0)
+        raises(TypeError, slice('abcdefghijklmn').index, 'abc', -10.0, 30)
+
+    def test_rfind(self):
+        def slice(s): return (s*3)[len(s):-len(s)]
+        assert slice('abcdefghiabc').rfind('abc') == 9
+        assert slice('abcdefghiabc').rfind('') == 12
+        assert slice('abcdefghiabc').rfind('abcd') == 0
+        assert slice('abcdefghiabc').rfind('abcz') == -1
+
+    def test_rindex(self):
+        from sys import maxint
+        def slice(s): return (s*3)[len(s):-len(s)]
+        assert slice('abcdefghiabc').rindex('') == 12
+        assert slice('abcdefghiabc').rindex('def') == 3
+        assert slice('abcdefghiabc').rindex('abc') == 9
+        assert slice('abcdefghiabc').rindex('abc', 0, -1) == 0
+        assert slice('abcdefghiabc').rindex('abc', -4*maxint, 4*maxint) == 9
+        raises(ValueError, slice('abcdefghiabc').rindex, 'hib')
+        raises(ValueError, slice('defghiabc').rindex, 'def', 1)
+        raises(ValueError, slice('defghiabc').rindex, 'abc', 0, -1)
+        raises(ValueError, slice('abcdefghi').rindex, 'ghi', 0, 8)
+        raises(ValueError, slice('abcdefghi').rindex, 'ghi', 0, -1)
+        raises(TypeError, slice('abcdefghijklmn').rindex, 'abc', 0, 0.0)
+        raises(TypeError, slice('abcdefghijklmn').rindex, 'abc', -10.0, 30)
+
+    def test_contains(self):
+        def slice(s): return (s*3)[len(s):-len(s)]
+        assert '' in slice('abc')
+        assert 'a' in slice('abc')
+        assert 'ab' in slice('abc')
+        assert not 'd' in slice('abc')
+        raises(TypeError, slice('a').__contains__, 1)
+        
+    def test_hash(self):
+        # check that we have the same hash as CPython for at least 31 bits
+        # (but don't go checking CPython's special case -1)
+        # disabled: assert hash('') == 0 --- different special case
+        def slice(s): return (s*3)[len(s):-len(s)]
+        assert hash(slice('hello')) & 0x7fffffff == 0x347697fd
+        assert hash(slice('hello world!')) & 0x7fffffff == 0x2f0bb411



More information about the Pypy-commit mailing list