[pypy-svn] r39945 - in pypy/dist/pypy: config interpreter interpreter/test lib module/__builtin__ module/mmap module/operator objspace objspace/cpy objspace/flow objspace/std objspace/std/test rlib

xoraxax at codespeak.net xoraxax at codespeak.net
Mon Mar 5 10:50:07 CET 2007


Author: xoraxax
Date: Mon Mar  5 10:50:02 2007
New Revision: 39945

Added:
   pypy/dist/pypy/lib/_functools.py
      - copied unchanged from r39940, pypy/branch/pypy-2.5/pypy/lib/_functools.py
   pypy/dist/pypy/module/operator/
      - copied from r39940, pypy/branch/pypy-2.5/pypy/module/operator/
   pypy/dist/pypy/objspace/std/test/test_index.py
      - copied unchanged from r39940, pypy/branch/pypy-2.5/pypy/objspace/std/test/test_index.py
Removed:
   pypy/dist/pypy/lib/operator.py
Modified:
   pypy/dist/pypy/config/pypyoption.py
   pypy/dist/pypy/interpreter/baseobjspace.py
   pypy/dist/pypy/interpreter/gateway.py
   pypy/dist/pypy/interpreter/test/test_gateway.py
   pypy/dist/pypy/interpreter/test/test_objspace.py
   pypy/dist/pypy/lib/_classobj.py
   pypy/dist/pypy/module/__builtin__/app_functional.py
   pypy/dist/pypy/module/mmap/interp_mmap.py
   pypy/dist/pypy/objspace/cpy/function.py
   pypy/dist/pypy/objspace/cpy/objspace.py
   pypy/dist/pypy/objspace/descroperation.py
   pypy/dist/pypy/objspace/flow/operation.py
   pypy/dist/pypy/objspace/std/dictmultiobject.py
   pypy/dist/pypy/objspace/std/dictobject.py
   pypy/dist/pypy/objspace/std/intobject.py
   pypy/dist/pypy/objspace/std/listmultiobject.py
   pypy/dist/pypy/objspace/std/listobject.py
   pypy/dist/pypy/objspace/std/listtype.py
   pypy/dist/pypy/objspace/std/longobject.py
   pypy/dist/pypy/objspace/std/rangeobject.py
   pypy/dist/pypy/objspace/std/sliceobject.py
   pypy/dist/pypy/objspace/std/slicetype.py
   pypy/dist/pypy/objspace/std/stringobject.py
   pypy/dist/pypy/objspace/std/stringtype.py
   pypy/dist/pypy/objspace/std/strsliceobject.py
   pypy/dist/pypy/objspace/std/test/test_stringobject.py
   pypy/dist/pypy/objspace/std/tupleobject.py
   pypy/dist/pypy/objspace/std/unicodeobject.py
   pypy/dist/pypy/objspace/std/unicodetype.py
   pypy/dist/pypy/rlib/streamio.py
Log:
(xorAxAx, gbrandl, armin with useful svn hints) Merged pypy-2.5 branch into dist.

Modified: pypy/dist/pypy/config/pypyoption.py
==============================================================================
--- pypy/dist/pypy/config/pypyoption.py	(original)
+++ pypy/dist/pypy/config/pypyoption.py	Mon Mar  5 10:50:02 2007
@@ -17,7 +17,7 @@
 default_modules = essential_modules.copy()
 default_modules.update(dict.fromkeys(
     ["_codecs", "gc", "_weakref", "array", "marshal", "errno",
-     "math", "_sre", "_pickle_support",
+     "math", "_sre", "_pickle_support", "operator",
      "recparser", "symbol", "_random", "pypymagic"]))
 
 

Modified: pypy/dist/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/dist/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/dist/pypy/interpreter/baseobjspace.py	Mon Mar  5 10:50:02 2007
@@ -5,7 +5,7 @@
 from pypy.interpreter.miscutils import ThreadLocals
 from pypy.tool.cache import Cache
 from pypy.tool.uid import HUGEVAL_BYTES
-import os
+import os, sys
 
 __all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root']
 
@@ -785,6 +785,28 @@
             step  = 0
         return start, stop, step
 
+    def getindex_w(self, w_obj, exception=None):
+        w_index = self.index(w_obj)
+        try:
+            index = self.int_w(w_index)
+        except OperationError, err:
+            if not err.match(self, self.w_OverflowError):
+                raise
+            if not exception:
+                # w_index is a long object
+                if w_index.get_sign() < 0:
+                    return -sys.maxint-1
+                else:
+                    return sys.maxint
+            else:
+                raise OperationError(
+                    exception, self.wrap(
+                    "cannot fit '%s' into an index-sized "
+                    "integer" % self.type(w_obj).getname(self, '?')))
+        else:
+            return index
+
+
 class AppExecCache(SpaceCache):
     def build(cache, source):
         """ NOT_RPYTHON """
@@ -841,6 +863,7 @@
     ('or_',             '|',         2, ['__or__', '__ror__']),
     ('xor',             '^',         2, ['__xor__', '__rxor__']),
     ('int',             'int',       1, ['__int__']),
+    ('index',           'index',     1, ['__index__']),
     ('float',           'float',     1, ['__float__']),
     ('long',            'long',      1, ['__long__']),
     ('inplace_add',     '+=',        2, ['__iadd__']),

Modified: pypy/dist/pypy/interpreter/gateway.py
==============================================================================
--- pypy/dist/pypy/interpreter/gateway.py	(original)
+++ pypy/dist/pypy/interpreter/gateway.py	Mon Mar  5 10:50:02 2007
@@ -106,7 +106,17 @@
 
     def visit_self(self, cls, app_sig):
         self.visit__Wrappable(cls, app_sig)
-        
+
+    def checked_space_method(self, typ, app_sig):
+        argname = self.orig_arg()
+        assert not argname.startswith('w_'), (
+            "unwrapped %s argument %s of built-in function %r should "
+            "not start with 'w_'" % (typ.__name__, argname, self.func))
+        app_sig.append(argname)
+
+    def visit_index(self, index, app_sig):
+        self.checked_space_method(index, app_sig)
+
     def visit__Wrappable(self, el, app_sig):
         name = el.__name__
         argname = self.orig_arg()
@@ -154,11 +164,7 @@
     def visit__object(self, typ, app_sig):
         if typ not in (int, str, float):
             assert False, "unsupported basic type in unwrap_spec"
-        argname = self.orig_arg()
-        assert not argname.startswith('w_'), (
-            "unwrapped %s argument %s of built-in function %r should "
-            "not start with 'w_'" % (typ.__name__, argname, self.func))
-        app_sig.append(argname)        
+        self.checked_space_method(typ, app_sig)
 
 
 class UnwrapSpec_EmitRun(UnwrapSpecEmit):
@@ -207,6 +213,9 @@
         self.run_args.append("space.%s_w(%s)" %
                              (typ.__name__, self.scopenext()))
 
+    def visit_index(self, typ):
+        self.run_args.append("space.getindex_w(%s)" % (self.scopenext(), ))
+
     def _make_unwrap_activation_class(self, unwrap_spec, cache={}):
         try:
             key = tuple(unwrap_spec)
@@ -316,6 +325,9 @@
         self.unwrap.append("space.%s_w(%s)" % (typ.__name__,
                                                self.nextarg()))
 
+    def visit_index(self, typ):
+        self.unwrap.append("space.getindex_w(%s)" % (self.nextarg()), )
+
     def make_fastfunc(unwrap_spec, func):
         unwrap_info = UnwrapSpec_FastFunc_Unwrap()
         unwrap_info.apply_over(unwrap_spec)

Modified: pypy/dist/pypy/interpreter/test/test_gateway.py
==============================================================================
--- pypy/dist/pypy/interpreter/test/test_gateway.py	(original)
+++ pypy/dist/pypy/interpreter/test/test_gateway.py	Mon Mar  5 10:50:02 2007
@@ -33,6 +33,12 @@
                                                    gateway.Arguments])
         assert code.signature() == (['x', 'y'], 'args', 'keywords')
 
+        def f(space, index):
+            pass
+        code = gateway.BuiltinCode(f, unwrap_spec=[gateway.ObjSpace, "index"])
+        assert code.signature() == (["index"], None, None)
+
+
     def test_call(self):
         def c(space, w_x, w_y, hello_w):
             u = space.unwrap
@@ -50,6 +56,15 @@
         w_result = code.funcrun(FakeFunc(self.space, "c"), args)
         assert self.space.eq_w(w_result, w(102))
 
+    def test_call_index(self):
+        def c(space, index):
+            assert type(index) is int
+        code = gateway.BuiltinCode(c, unwrap_spec=[gateway.ObjSpace,
+                                                   "index"])
+        w = self.space.wrap
+        args = argument.Arguments(self.space, [w(123)])
+        code.funcrun(FakeFunc(self.space, "c"), args)
+
     def test_call_args(self):
         def c(space, w_x, w_y, __args__):
             args_w, kwds_w = __args__.unpack()

Modified: pypy/dist/pypy/interpreter/test/test_objspace.py
==============================================================================
--- pypy/dist/pypy/interpreter/test/test_objspace.py	(original)
+++ pypy/dist/pypy/interpreter/test/test_objspace.py	Mon Mar  5 10:50:02 2007
@@ -1,6 +1,7 @@
 from py.test import raises
 from pypy.interpreter.function import Function
 from pypy.interpreter.pycode import PyCode
+import sys
 
 # this test isn't so much to test that the objspace interface *works*
 # -- it's more to test that it's *there*
@@ -139,6 +140,23 @@
         res = self.space.interp_w(Function, w(None), can_be_None=True)
         assert res is None
 
+    def test_getindex_w(self):
+        w_instance1 = self.space.appexec([], """():
+            class X(object):
+                def __index__(self): return 42
+            return X()""")
+        w_instance2 = self.space.appexec([], """():
+            class Y(object):
+                def __index__(self): return 2**70
+            return Y()""")
+        first = self.space.getindex_w(w_instance1)
+        assert first == 42
+        second = self.space.getindex_w(w_instance2)
+        assert second == sys.maxint
+        self.space.raises_w(self.space.w_IndexError,
+                            self.space.getindex_w, w_instance2, self.space.w_IndexError)
+
+
 class TestModuleMinimal: 
     def test_sys_exists(self):
         assert self.space.sys 

Modified: pypy/dist/pypy/lib/_classobj.py
==============================================================================
--- pypy/dist/pypy/lib/_classobj.py	(original)
+++ pypy/dist/pypy/lib/_classobj.py	Mon Mar  5 10:50:02 2007
@@ -399,6 +399,14 @@
 """, {"op": op})
     del op
 
+    def __index__(self):
+        func = instance_getattr1(self, '__index__', False)
+        if func:
+            return func()
+        else:
+            raise AttributeError('object cannot be interpreted as an index')
+
+
     # coerce
     def __coerce__(self, other):
         func = instance_getattr1(self, '__coerce__', False)

Modified: pypy/dist/pypy/module/__builtin__/app_functional.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/app_functional.py	(original)
+++ pypy/dist/pypy/module/__builtin__/app_functional.py	Mon Mar  5 10:50:02 2007
@@ -4,6 +4,9 @@
 """
 from __future__ import generators
 
+from operator import lt, gt
+
+
 def sum(sequence, total=0):
     """sum(sequence, start=0) -> value
 
@@ -203,47 +206,48 @@
 # min and max could be one function if we had operator.__gt__ and
 # operator.__lt__  Perhaps later when we have operator.
 
-def min(*arr):
+
+def _identity(arg):
+    return arg
+
+
+def min(*arr, **kwargs):
     """return the smallest number in a list,
     or its smallest argument if more than one is given."""
 
+    return min_max(gt, "min", *arr, **kwargs)
+
+def min_max(comp, funcname, *arr, **kwargs):
+    key = kwargs.pop("key", _identity)
+    if len(kwargs):
+        raise TypeError, '%s() got an unexpected keyword argument' % funcname
+
     if not arr:
-        raise TypeError, 'min() takes at least one argument'
+        raise TypeError, '%s() takes at least one argument' % funcname
 
     if len(arr) == 1:
         arr = arr[0]
 
     iterator = iter(arr)
     try:
-        min = iterator.next()
+        min_max_val = iterator.next()
     except StopIteration:
-        raise ValueError, 'min() arg is an empty sequence'
+        raise ValueError, '%s() arg is an empty sequence' % funcname
+
+    keyed_min_max_val = key(min_max_val)
 
     for i in iterator:
-        if min > i:
-            min = i
-    return min
+        keyed = key(i)
+        if comp(keyed_min_max_val, keyed):
+            min_max_val = i
+            keyed_min_max_val = keyed
+    return min_max_val
 
-def max(*arr):
+def max(*arr, **kwargs):
     """return the largest number in a list,
     or its largest argument if more than one is given."""
 
-    if not arr:
-        raise TypeError, 'max() takes at least one argument'
-
-    if len(arr) == 1:
-        arr = arr[0]
-
-    iterator = iter(arr)
-    try:
-        max = iterator.next()
-    except StopIteration:
-        raise ValueError, 'max() arg is an empty sequence'
-
-    for i in iterator:
-        if max < i:
-            max = i
-    return max
+    return min_max(lt, "max", *arr, **kwargs)
 
 class enumerate(object):
     """enumerate(iterable) -> iterator for (index, value) of iterable.
@@ -342,15 +346,15 @@
     def __len__(self):
         return self.len 
 
-    def __getitem__(self, index):
+    def __getitem__(self, i):
         # xrange does NOT support slicing
-        if not isinstance(index, int):
-            raise TypeError, "sequence index must be integer"
+        import operator
+        i = operator.index(i)
         len = self.len 
-        if index < 0:
-            index += len
-        if 0 <= index < len:
-            return self.start + index * self.step
+        if i < 0:
+            i += len
+        if 0 <= i < len:
+            return self.start + i * self.step
         raise IndexError, "xrange object index out of range"
 
     def __iter__(self):

Modified: pypy/dist/pypy/module/mmap/interp_mmap.py
==============================================================================
--- pypy/dist/pypy/module/mmap/interp_mmap.py	(original)
+++ pypy/dist/pypy/module/mmap/interp_mmap.py	Mon Mar  5 10:50:02 2007
@@ -350,7 +350,7 @@
                 self.space.wrap("seek out of range"))
         
         self.pos = where
-    seek.unwrap_spec = ['self', int, int]
+    seek.unwrap_spec = ['self', 'index', int]
     
     def tell(self):
         self.check_valid()
@@ -679,7 +679,7 @@
         m.setdata(res, map_size)
 
         return space.wrap(m)
-    mmap.unwrap_spec = [ObjSpace, int, int, int, int, int]
+    mmap.unwrap_spec = [ObjSpace, int, 'index', int, int, int]
 elif _MS_WINDOWS:
     def mmap(space, fileno, length, tagname="", access=_ACCESS_DEFAULT):
         # check size boundaries
@@ -771,4 +771,4 @@
 
         raise OperationError(space.w_EnvironmentError,
                              space.wrap(os.strerror(dwErr)))
-    mmap.unwrap_spec = [ObjSpace, int, int, str, int]
+    mmap.unwrap_spec = [ObjSpace, int, 'index', str, int]

Modified: pypy/dist/pypy/objspace/cpy/function.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/function.py	(original)
+++ pypy/dist/pypy/objspace/cpy/function.py	Mon Mar  5 10:50:02 2007
@@ -52,7 +52,9 @@
     def visit__object(self, el):
         convertermap = {int: 'int_w',
                         str: 'str_w',
-                        float: 'float_w'}
+                        float: 'float_w',
+                        "index": 'getindex_w'
+                        }
         argname = self.orig_arg()
         assert not argname.startswith('w_')
         self.inputargs.append(argname)
@@ -62,6 +64,9 @@
                                 argname))
         self.passedargs.append(argname)
 
+    def visit_index(self, el):
+        self.visit__object("index")
+
     def visit_args_w(self, el):
         argname = self.orig_arg()
         assert argname.endswith('_w')

Modified: pypy/dist/pypy/objspace/cpy/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/cpy/objspace.py	(original)
+++ pypy/dist/pypy/objspace/cpy/objspace.py	Mon Mar  5 10:50:02 2007
@@ -148,6 +148,11 @@
     repr    = staticmethod(PyObject_Repr)
     id      = staticmethod(PyLong_FromVoidPtr_PYOBJ)
 
+    def index(self, w_obj):
+        # XXX we do not support 2.5 yet, so we just do some
+        # hack here to have index working
+        return self.wrap(self.int_w(w_obj))
+
     def bigint_w(self, w_obj):
         if self.is_true(self.isinstance(w_obj, self.w_long)):
             sign = _PyLong_Sign(w_obj)

Modified: pypy/dist/pypy/objspace/descroperation.py
==============================================================================
--- pypy/dist/pypy/objspace/descroperation.py	(original)
+++ pypy/dist/pypy/objspace/descroperation.py	Mon Mar  5 10:50:02 2007
@@ -515,6 +515,7 @@
 
 for targetname, specialname, checkerspec in [
     ('int', '__int__', ("space.w_int", "space.w_long")), 
+    ('index', '__index__', ("space.w_int", "space.w_long")),
     ('long', '__long__', ("space.w_int", "space.w_long")), 
     ('float', '__float__', ("space.w_float",))]:
 
@@ -538,7 +539,7 @@
         assert not hasattr(DescrOperation, %(targetname)r)
         DescrOperation.%(targetname)s = %(targetname)s
         del %(targetname)s 
-        \n""" % locals() 
+        \n""" % locals()
     exec compile2(source) 
 
 for targetname, specialname in [
@@ -580,7 +581,7 @@
 for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable:
     if not hasattr(DescrOperation, _name):
         _impl_maker = None
-        if _arity ==2 and _name in ['lt', 'le', 'gt', 'ge', 'ne', 'eq']:
+        if _arity == 2 and _name in ['lt', 'le', 'gt', 'ge', 'ne', 'eq']:
             #print "comparison", _specialnames
             _impl_maker = _make_comparison_impl
         elif _arity == 2 and _name.startswith('inplace_'):

Modified: pypy/dist/pypy/objspace/flow/operation.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/operation.py	(original)
+++ pypy/dist/pypy/objspace/flow/operation.py	Mon Mar  5 10:50:02 2007
@@ -23,6 +23,9 @@
 def do_int(x):
     return x.__int__()
 
+def do_index(x):
+    return x.__index__()
+
 def do_float(x):
     return x.__float__()
 
@@ -162,6 +165,7 @@
     ('divmod',          divmod),
     ('pow',             pow),
     ('int',             do_int),
+    ('index',           do_index),
     ('float',           do_float),
     ('long',            do_long),
     ('inplace_add',     inplace_add),

Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/dictmultiobject.py	(original)
+++ pypy/dist/pypy/objspace/std/dictmultiobject.py	Mon Mar  5 10:50:02 2007
@@ -138,6 +138,7 @@
 
     def get(self, w_lookup):
         return None
+
     def setitem(self, w_key, w_value):
         if _is_str(self.space, w_key):
             return StrDictImplementation(self.space).setitem_str(w_key, w_value)
@@ -1010,6 +1011,15 @@
             result[key] = val
         return result
 
+    def missing_method(w_dict, space, w_key):
+        if not space.is_w(space.type(w_dict), space.w_dict):
+            w_missing = space.lookup(w_dict, "__missing__")
+            if w_missing is None:
+                return None
+            return space.call_function(w_missing, w_dict, w_key)
+        else:
+            return None
+
     def len(w_self):
         return w_self.implementation.length()
 
@@ -1054,6 +1064,11 @@
     w_value = w_dict.implementation.get(w_lookup)
     if w_value is not None:
         return w_value
+
+    w_missing_item = w_dict.missing_method(space, w_lookup)
+    if w_missing_item is not None:
+        return w_missing_item
+
     raise OperationError(space.w_KeyError, w_lookup)
 
 def setitem__DictMulti_ANY_ANY(space, w_dict, w_newkey, w_newvalue):

Modified: pypy/dist/pypy/objspace/std/dictobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/dictobject.py	(original)
+++ pypy/dist/pypy/objspace/std/dictobject.py	Mon Mar  5 10:50:02 2007
@@ -41,6 +41,15 @@
     def get(w_dict, w_lookup, w_default):
         return w_dict.content.get(w_lookup, w_default)
 
+    def missing_method(w_dict, space, w_key):
+        if not space.is_w(space.type(w_dict), space.w_dict):
+            w_missing = space.lookup(w_dict, "__missing__")
+            if w_missing is None:
+                return None
+            return space.call_function(w_missing, w_dict, w_key)
+        else:
+            return None
+
     def set_str_keyed_item(w_dict, w_key, w_value, shadows_type=True):
         w_dict.content[w_key] = w_value
 
@@ -73,7 +82,11 @@
     try:
         return w_dict.content[w_lookup]
     except KeyError:
-        raise OperationError(space.w_KeyError, w_lookup)
+        w_missing_item = w_dict.missing_method(space, w_lookup)
+        if w_missing_item is None:
+            raise OperationError(space.w_KeyError, w_lookup)
+        else:
+            return w_missing_item
 
 def setitem__Dict_ANY_ANY(space, w_dict, w_newkey, w_newvalue):
     w_dict.content[w_newkey] = w_newvalue

Modified: pypy/dist/pypy/objspace/std/intobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/intobject.py	(original)
+++ pypy/dist/pypy/objspace/std/intobject.py	Mon Mar  5 10:50:02 2007
@@ -326,6 +326,9 @@
     a = w_int1.intval
     return wrapint(space, a)
 
+def index__Int(space, w_int1):
+    return int__Int(space, w_int1)
+
 def float__Int(space, w_int1):
     a = w_int1.intval
     x = float(a)

Modified: pypy/dist/pypy/objspace/std/listmultiobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/listmultiobject.py	(original)
+++ pypy/dist/pypy/objspace/std/listmultiobject.py	Mon Mar  5 10:50:02 2007
@@ -1,5 +1,6 @@
 from pypy.objspace.std.objspace import *
 from pypy.objspace.std.inttype import wrapint
+from pypy.objspace.std.listtype import get_list_index
 from pypy.objspace.std.sliceobject import W_SliceObject
 
 from pypy.objspace.std import slicetype
@@ -892,7 +893,7 @@
     return wrapint(space, result)
 
 def getitem__ListMulti_ANY(space, w_list, w_index):
-    idx = space.int_w(w_index)
+    idx = get_list_index(space, w_index)
     idx = _adjust_index(space, idx, w_list.implementation.length(),
                         "list index out of range")
     return w_list.implementation.getitem(idx)
@@ -940,7 +941,7 @@
 
 def mul_list_times(space, w_list, w_times):
     try:
-        times = space.int_w(w_times)
+        times = space.getindex_w(w_times, space.w_OverflowError)
     except OperationError, e:
         if e.match(space, space.w_TypeError):
             raise FailedToImplement
@@ -957,7 +958,7 @@
 
 def inplace_mul__ListMulti_ANY(space, w_list, w_times):
     try:
-        times = space.int_w(w_times)
+        times = space.getindex_w(w_times, space.w_OverflowError)
     except OperationError, e:
         if e.match(space, space.w_TypeError):
             raise FailedToImplement
@@ -1025,7 +1026,7 @@
         w_list2.implementation)
 
 def delitem__ListMulti_ANY(space, w_list, w_idx):
-    idx = space.int_w(w_idx)
+    idx = get_list_index(space, w_idx)
     length = w_list.implementation.length()
     idx = _adjust_index(space, idx, length, "list deletion index out of range")
     if length == 1:
@@ -1059,7 +1060,7 @@
     return space.w_None
 
 def setitem__ListMulti_ANY_ANY(space, w_list, w_index, w_any):
-    idx = space.int_w(w_index)
+    idx = get_list_index(space, w_index)
     idx = _adjust_index(space, idx, w_list.implementation.length(),
                         "list index out of range")
     w_list.implementation = w_list.implementation.i_setitem(idx, w_any)

Modified: pypy/dist/pypy/objspace/std/listobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/listobject.py	(original)
+++ pypy/dist/pypy/objspace/std/listobject.py	Mon Mar  5 10:50:02 2007
@@ -1,5 +1,6 @@
 from pypy.objspace.std.objspace import *
 from pypy.objspace.std.inttype import wrapint
+from pypy.objspace.std.listtype import get_list_index
 from pypy.objspace.std.sliceobject import W_SliceObject
 from pypy.objspace.std.tupleobject import W_TupleObject
 
@@ -42,9 +43,8 @@
     return wrapint(space, result)
 
 def getitem__List_ANY(space, w_list, w_index):
-    idx = space.int_w(w_index)
     try:
-        return w_list.wrappeditems[idx]
+        return w_list.wrappeditems[get_list_index(space, w_index)]
     except IndexError:
         raise OperationError(space.w_IndexError,
                              space.wrap("list index out of range"))
@@ -92,7 +92,7 @@
 
 def mul_list_times(space, w_list, w_times):
     try:
-        times = space.int_w(w_times)
+        times = space.getindex_w(w_times, space.w_OverflowError)
     except OperationError, e:
         if e.match(space, space.w_TypeError):
             raise FailedToImplement
@@ -107,7 +107,7 @@
 
 def inplace_mul__List_ANY(space, w_list, w_times):
     try:
-        times = space.int_w(w_times)
+        times = space.getindex_w(w_times, space.w_OverflowError)
     except OperationError, e:
         if e.match(space, space.w_TypeError):
             raise FailedToImplement
@@ -171,7 +171,7 @@
         w_list2.wrappeditems)
 
 def delitem__List_ANY(space, w_list, w_idx):
-    idx = space.int_w(w_idx)
+    idx = get_list_index(space, w_idx)
     try:
         del w_list.wrappeditems[idx]
     except IndexError:
@@ -227,7 +227,7 @@
     return space.w_None
 
 def setitem__List_ANY_ANY(space, w_list, w_index, w_any):
-    idx = space.int_w(w_index)
+    idx = get_list_index(space, w_index)
     try:
         w_list.wrappeditems[idx] = w_any
     except IndexError:

Modified: pypy/dist/pypy/objspace/std/listtype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/listtype.py	(original)
+++ pypy/dist/pypy/objspace/std/listtype.py	Mon Mar  5 10:50:02 2007
@@ -1,5 +1,6 @@
 from __future__ import generators
 from pypy.interpreter import gateway
+from pypy.interpreter.error import OperationError
 from pypy.objspace.std.stdtypedef import *
 from pypy.objspace.std.register_all import register_all
 from sys import maxint
@@ -61,3 +62,13 @@
     __hash__ = no_hash_descr,
     )
 list_typedef.registermethods(globals())
+
+# ____________________________________________________________
+
+def get_list_index(space, w_index):
+    if not space.lookup(w_index, '__index__'):
+        raise OperationError(
+            space.w_TypeError,
+            space.wrap("list indices must be integers, not %s" %
+                       space.type(w_index).getname(space, '?')))
+    return space.getindex_w(w_index, space.w_IndexError)

Modified: pypy/dist/pypy/objspace/std/longobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/longobject.py	(original)
+++ pypy/dist/pypy/objspace/std/longobject.py	Mon Mar  5 10:50:02 2007
@@ -50,6 +50,9 @@
     def is_odd(self):
         return self.num.is_odd()
 
+    def get_sign(self):
+        return self.num.sign
+
 registerimplementation(W_LongObject)
 
 # bool-to-long
@@ -79,6 +82,9 @@
     except OverflowError:
         return long__Long(space, w_value)
 
+def index__Long(space, w_value):
+    return long__Long(space, w_value)
+
 def float__Long(space, w_longobj):
     try:
         return space.newfloat(w_longobj.num.tofloat())

Modified: pypy/dist/pypy/objspace/std/rangeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/rangeobject.py	(original)
+++ pypy/dist/pypy/objspace/std/rangeobject.py	Mon Mar  5 10:50:02 2007
@@ -78,7 +78,7 @@
 def getitem__RangeList_ANY(space, w_rangelist, w_index):
     if w_rangelist.w_list is not None:
         return space.getitem(w_rangelist.w_list, w_index)
-    idx = space.int_w(w_index)
+    idx = space.getindex_w(w_index, space.w_IndexError)
     try:
         return wrapint(space, w_rangelist.getitem(idx))
     except IndexError:

Modified: pypy/dist/pypy/objspace/std/sliceobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/sliceobject.py	(original)
+++ pypy/dist/pypy/objspace/std/sliceobject.py	Mon Mar  5 10:50:02 2007
@@ -111,7 +111,7 @@
 # indices impl
 
 def slice_indices__Slice_ANY(space, w_slice, w_length):
-    length = space.int_w(w_length)
+    length = space.getindex_w(w_length, space.w_OverflowError)
     start, stop, step = w_slice.indices3(space, length)
     return space.newtuple([space.wrap(start), space.wrap(stop),
                            space.wrap(step)])

Modified: pypy/dist/pypy/objspace/std/slicetype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/slicetype.py	(original)
+++ pypy/dist/pypy/objspace/std/slicetype.py	Mon Mar  5 10:50:02 2007
@@ -15,17 +15,19 @@
 
 # utility functions
 def _Eval_SliceIndex(space, w_int):
-    try:
-        x = space.int_w(w_int)
-    except OperationError, e:
-        if not e.match(space, space.w_OverflowError):
-            raise
-        cmp = space.is_true(space.ge(w_int, space.wrap(0)))
-        if cmp:
-            x = sys.maxint
-        else:
-            x = -sys.maxint
-    return x
+    return space.getindex_w(w_int) # clamp if long integer is too large
+    # This is done by getindex_w already.
+    #try:
+    #    x = space.getindex_w(w_int)
+    #except OperationError, e:
+    #    if not e.match(space, space.w_OverflowError):
+    #        raise
+    #    cmp = space.is_true(space.ge(w_int, space.wrap(0)))
+    #    if cmp:
+    #        x = sys.maxint
+    #    else:
+    #        x = -sys.maxint
+    #return x
 
 def adapt_bound(space, w_index, w_size):
     if not (space.is_true(space.isinstance(w_index, space.w_int)) or

Modified: pypy/dist/pypy/objspace/std/stringobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/stringobject.py	(original)
+++ pypy/dist/pypy/objspace/std/stringobject.py	Mon Mar  5 10:50:02 2007
@@ -1,4 +1,4 @@
-# -*- Coding: Latin-1 -*-
+# -*- coding: latin-1 -*-
 
 from pypy.objspace.std.objspace import *
 from pypy.interpreter import gateway
@@ -11,7 +11,8 @@
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.objspace.std.tupleobject import W_TupleObject
 
-from pypy.objspace.std.stringtype import sliced, joined, wrapstr, wrapchar
+from pypy.objspace.std.stringtype import sliced, joined, wrapstr, wrapchar, \
+     stringendswith, stringstartswith
 
 
 class W_StringObject(W_Object):
@@ -343,7 +344,6 @@
         return W_StringObject.EMPTY
 
 def str_rjust__String_ANY_ANY(space, w_self, w_arg, w_fillchar):
-
     u_arg = space.int_w(w_arg)
     u_self = w_self._value
     fillchar = space.str_w(w_fillchar)
@@ -360,7 +360,6 @@
 
 
 def str_ljust__String_ANY_ANY(space, w_self, w_arg, w_fillchar):
-
     u_self = w_self._value
     u_arg = space.int_w(w_arg)
     fillchar = space.str_w(w_fillchar)
@@ -394,19 +393,45 @@
     return space.newbool(self.find(sub) >= 0)
 
 def str_find__String_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__String_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__String_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
+def str_partition__String_String(space, w_self, w_sub):
+    self = w_self._value
+    sub = w_sub._value
+    if not sub:
+        raise OperationError(space.w_ValueError,
+                             space.wrap("empty separator"))
+    pos = self.find(sub)
+    if pos == -1:
+        return space.newtuple([w_self, space.wrap(''), space.wrap('')])
+    else:
+        return space.newtuple([sliced(space, self, 0, pos),
+                               w_sub,
+                               sliced(space, self, pos+len(sub), len(self))])
+
+def str_rpartition__String_String(space, w_self, w_sub):
+    self = w_self._value
+    sub = w_sub._value
+    if not sub:
+        raise OperationError(space.w_ValueError,
+                             space.wrap("empty separator"))
+    pos = self.rfind(sub)
+    if pos == -1:
+        return space.newtuple([space.wrap(''), space.wrap(''), w_self])
+    else:
+        return space.newtuple([sliced(space, self, 0, pos),
+                               w_sub,
+                               sliced(space, self, pos+len(sub), len(self))])
+
 
+def str_index__String_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:
@@ -417,7 +442,6 @@
 
 
 def str_rindex__String_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:
@@ -428,7 +452,6 @@
 
 
 def str_replace__String_String_String_ANY(space, w_self, w_sub, w_by, w_maxsplit=-1):
-
     input = w_self._value
     sub = w_sub._value
     by = w_by._value
@@ -553,26 +576,30 @@
 def str_endswith__String_String_ANY_ANY(space, w_self, w_suffix, w_start, w_end):
     (u_self, suffix, start, end) = _convert_idx_params(space, w_self,
                                                        w_suffix, w_start, w_end)
-    begin = end - len(suffix)
-    if begin < start:
-        return space.w_False
-    for i in range(len(suffix)):
-        if u_self[begin+i] != suffix[i]:
-            return space.w_False
-    return space.w_True
-    
-    
+    return space.newbool(stringendswith(u_self, suffix, start, end))
+
+def str_endswith__String_Tuple_ANY_ANY(space, w_self, w_suffixes, w_start, w_end):
+    (u_self, _, start, end) = _convert_idx_params(space, w_self,
+                                                  space.wrap(''), w_start, w_end)
+    for w_suffix in space.unpacktuple(w_suffixes):
+        suffix = space.str_w(w_suffix) 
+        if stringendswith(u_self, suffix, start, end):
+            return space.w_True
+    return space.w_False
+
 def str_startswith__String_String_ANY_ANY(space, w_self, w_prefix, w_start, w_end):
     (u_self, prefix, start, end) = _convert_idx_params(space, w_self,
                                                        w_prefix, w_start, w_end)
-    stop = start + len(prefix)
-    if stop > end:
-        return space.w_False
-    for i in range(len(prefix)):
-        if u_self[start+i] != prefix[i]:
-            return space.w_False
-    return space.w_True
-    
+    return space.newbool(stringstartswith(u_self, prefix, start, end))
+
+def str_startswith__String_Tuple_ANY_ANY(space, w_self, w_prefixes, w_start, w_end):
+    (u_self, _, start, end) = _convert_idx_params(space, w_self, space.wrap(''),
+                                                  w_start, w_end)
+    for w_prefix in space.unpacktuple(w_prefixes):
+        prefix = space.str_w(w_prefix)
+        if stringstartswith(u_self, prefix, start, end):
+            return space.w_True
+    return space.w_False
     
 def _tabindent(u_token, u_tabsize):
     "calculates distance behind the token to the next tabstop"
@@ -731,7 +758,12 @@
         return space.w_False
 
 def getitem__String_ANY(space, w_str, w_index):
-    ival = space.int_w(w_index)
+    if not space.lookup(w_index, '__index__'):
+        raise OperationError(
+            space.w_TypeError,
+            space.wrap("string indices must be integers, not %s" %
+                       space.type(w_index).getname(space, '?')))
+    ival = space.getindex_w(w_index, space.w_IndexError)
     str = w_str._value
     slen = len(str)
     if ival < 0:
@@ -758,7 +790,7 @@
 
 def mul_string_times(space, w_str, w_times):
     try:
-        mul = space.int_w(w_times)
+        mul = space.getindex_w(w_times, space.w_OverflowError)
     except OperationError, e:
         if e.match(space, space.w_TypeError):
             raise FailedToImplement

Modified: pypy/dist/pypy/objspace/std/stringtype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/stringtype.py	(original)
+++ pypy/dist/pypy/objspace/std/stringtype.py	Mon Mar  5 10:50:02 2007
@@ -28,6 +28,8 @@
         return W_StringObject(c)
 
 def sliced(space, s, start, stop):
+    assert start >= 0
+    assert stop >= 0 
     if space.config.objspace.std.withstrslice:
         from pypy.objspace.std.strsliceobject import W_StringSliceObject
         # XXX heuristic, should be improved!
@@ -133,6 +135,18 @@
                          ' s[start,end].  Optional\narguments start and end'
                          ' are interpreted as in slice notation.\n\nReturn -1'
                          ' on failure.')
+str_partition  = SMM('partition', 2,
+                     doc='S.partition(sep) -> (head, sep, tail)\n\nSearches'
+                         ' for the separator sep in S, and returns the part before'
+                         ' it,\nthe separator itself, and the part after it.  If'
+                         ' the separator is not\nfound, returns S and two empty'
+                         ' strings.')
+str_rpartition = SMM('rpartition', 2,
+                     doc='S.rpartition(sep) -> (tail, sep, head)\n\nSearches'
+                         ' for the separator sep in S, starting at the end of S,'
+                         ' and returns\nthe part before it, the separator itself,'
+                         ' and the part after it.  If the\nseparator is not found,'
+                         ' returns two empty strings and S.')
 str_index      = SMM('index', 4, defaults=(0, maxint),
                      doc='S.index(sub [,start [,end]]) -> int\n\nLike S.find()'
                          ' but raise ValueError when the substring is not'
@@ -256,3 +270,26 @@
 
 str_typedef.custom_hash = True
 str_typedef.registermethods(globals())
+
+# ____________________________________________________________
+
+# Helpers for several string implementations
+
+def stringendswith(u_self, suffix, start, end):
+    begin = end - len(suffix)
+    if begin < start:
+        return False
+    for i in range(len(suffix)):
+        if u_self[begin+i] != suffix[i]:
+            return False
+    return True
+
+def stringstartswith(u_self, prefix, start, end):
+    stop = start + len(prefix)
+    if stop > end:
+        return False
+    for i in range(len(prefix)):
+        if u_self[start+i] != prefix[i]:
+            return False
+    return True
+    

Modified: pypy/dist/pypy/objspace/std/strsliceobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/strsliceobject.py	(original)
+++ pypy/dist/pypy/objspace/std/strsliceobject.py	Mon Mar  5 10:50:02 2007
@@ -2,16 +2,20 @@
 from pypy.objspace.std.stringobject import W_StringObject
 from pypy.objspace.std.unicodeobject import delegate_String2Unicode
 from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.tupleobject import W_TupleObject
 from pypy.objspace.std import slicetype
 from pypy.objspace.std.inttype import wrapint
 
-from pypy.objspace.std.stringtype import wrapstr, wrapchar
+from pypy.objspace.std.stringtype import wrapstr, wrapchar, sliced, \
+     stringendswith, stringstartswith
 
 
 class W_StringSliceObject(W_Object):
     from pypy.objspace.std.stringtype import str_typedef as typedef
 
     def __init__(w_self, str, start, stop):
+        assert start >= 0
+        assert stop >= 0 
         w_self.str = str
         w_self.start = start
         w_self.stop = stop
@@ -63,7 +67,6 @@
 
 
 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)
     if res >= 0:
@@ -71,13 +74,41 @@
     else:
         return space.wrap(res)
 
+def str_partition__StringSlice_String(space, w_self, w_sub):
+    self = w_self.str
+    sub = w_sub._value
+    if not sub:
+        raise OperationError(space.w_ValueError,
+                             space.wrap("empty separator"))
+    pos = self.find(sub, w_self.start, w_self.stop)
+    if pos == -1:
+        return space.newtuple([w_self, space.wrap(''), space.wrap('')])
+    else:
+        return space.newtuple([sliced(space, self, w_self.start, pos),
+                               w_sub,
+                               sliced(space, self, pos+len(sub), w_self.stop)])
+
+def str_rpartition__StringSlice_String(space, w_self, w_sub):
+    self = w_self.str
+    sub = w_sub._value
+    if not sub:
+        raise OperationError(space.w_ValueError,
+                             space.wrap("empty separator"))
+    pos = self.rfind(sub, w_self.start, w_self.stop)
+    if pos == -1:
+        return space.newtuple([space.wrap(''), space.wrap(''), w_self])
+    else:
+        return space.newtuple([sliced(space, self, w_self.start, pos),
+                               w_sub,
+                               sliced(space, self, pos+len(sub), w_self.stop)])
+
+
 def str_count__StringSlice_String_ANY_ANY(space, w_self, w_arg, w_start, w_end): 
     (s, arg, start, end) =  _convert_idx_params(
             space, w_self, w_arg, w_start, w_end)
     return wrapint(space, s.count(arg, start, end))
 
 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)
     if res >= 0:
@@ -86,7 +117,6 @@
         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:
@@ -97,7 +127,6 @@
 
 
 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:
@@ -106,13 +135,46 @@
 
     return space.wrap(res - w_self.start)
 
+def str_endswith__StringSlice_String_ANY_ANY(space, w_self, w_suffix, w_start, w_end):
+    (u_self, suffix, start, end) = _convert_idx_params(space, w_self,
+                                                       w_suffix, w_start, w_end)
+    return space.newbool(stringendswith(u_self, suffix, start, end))
+
+def str_endswith__StringSlice_Tuple_ANY_ANY(space, w_self, w_suffixes, w_start, w_end):
+    (u_self, _, start, end) = _convert_idx_params(space, w_self,
+                                                  space.wrap(''), w_start, w_end)
+    for w_suffix in space.unpacktuple(w_suffixes):
+        suffix = space.str_w(w_suffix) 
+        if stringendswith(u_self, suffix, start, end):
+            return space.w_True
+    return space.w_False
+
+def str_startswith__StringSlice_String_ANY_ANY(space, w_self, w_prefix, w_start, w_end):
+    (u_self, prefix, start, end) = _convert_idx_params(space, w_self,
+                                                       w_prefix, w_start, w_end)
+    return space.newbool(stringstartswith(u_self, prefix, start, end))
+
+def str_startswith__StringSlice_Tuple_ANY_ANY(space, w_self, w_prefixes, w_start, w_end):
+    (u_self, _, start, end) = _convert_idx_params(space, w_self, space.wrap(''),
+                                                  w_start, w_end)
+    for w_prefix in space.unpacktuple(w_prefixes):
+        prefix = space.str_w(w_prefix)
+        if stringstartswith(u_self, prefix, start, end):
+            return space.w_True
+    return space.w_False
+
 
 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)
+    if not space.lookup(w_index, '__index__'):
+        raise OperationError(
+            space.w_TypeError,
+            space.wrap("string indices must be integers, not %s" %
+                       space.type(w_index).getname(space, '?')))
+    ival = space.getindex_w(w_index, space.w_IndexError)
     slen = w_str.stop - w_str.start
     if ival < 0:
         ival += slen
@@ -148,5 +210,6 @@
         return w_str
     return W_StringSliceObject(w_str.str, w_str.start, w_str.stop)
 
+
 from pypy.objspace.std import stringtype
 register_all(vars(), stringtype)

Modified: pypy/dist/pypy/objspace/std/test/test_stringobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_stringobject.py	(original)
+++ pypy/dist/pypy/objspace/std/test/test_stringobject.py	Mon Mar  5 10:50:02 2007
@@ -5,7 +5,7 @@
 
 class TestW_StringObject:
 
-    def teardown_method(self,method):
+    def teardown_method(self, method):
         pass
 
 ##    def test_order_rich(self):
@@ -334,6 +334,18 @@
         assert 'abc'.startswith('bc', 1, 2) is False
         assert 'abc'.startswith('c', -1, 4) is True
 
+    def test_startswith_tuples(self):
+        assert 'hello'.startswith(('he', 'ha'))
+        assert not 'hello'.startswith(('lo', 'llo'))
+        assert 'hello'.startswith(('hellox', 'hello'))
+        assert not 'hello'.startswith(())
+        assert 'helloworld'.startswith(('hellowo', 'rld', 'lowo'), 3)
+        assert not 'helloworld'.startswith(('hellowo', 'ello', 'rld'), 3)
+        assert 'hello'.startswith(('lo', 'he'), 0, -1)
+        assert not 'hello'.startswith(('he', 'hel'), 0, 1)
+        assert 'hello'.startswith(('he', 'hel'), 0, 2)
+        raises(TypeError, 'hello'.startswith, (42,))
+    
     def test_endswith(self):
         assert 'ab'.endswith('ab') is True
         assert 'ab'.endswith('b') is True
@@ -350,7 +362,19 @@
         assert 'abc'.endswith('bc', 1) is True
         assert 'abc'.endswith('bc', 2) is False
         assert 'abc'.endswith('b', -3, -1) is True
-      
+
+    def test_endswith_tuple(self):
+        assert not 'hello'.endswith(('he', 'ha'))
+        assert 'hello'.endswith(('lo', 'llo'))
+        assert 'hello'.endswith(('hellox', 'hello'))
+        assert not 'hello'.endswith(())
+        assert 'helloworld'.endswith(('hellowo', 'rld', 'lowo'), 3)
+        assert not 'helloworld'.endswith(('hellowo', 'ello', 'rld'), 3, -1)
+        assert 'hello'.endswith(('hell', 'ell'), 0, -1)
+        assert not 'hello'.endswith(('he', 'hel'), 0, 1)
+        assert 'hello'.endswith(('he', 'hell'), 0, 4)
+        raises(TypeError, 'hello'.endswith, (42,))
+
     def test_expandtabs(self):
         assert 'abc\rab\tdef\ng\thi'.expandtabs() ==    'abc\rab      def\ng       hi'
         assert 'abc\rab\tdef\ng\thi'.expandtabs(8) ==   'abc\rab      def\ng       hi'
@@ -436,6 +460,36 @@
         raises(TypeError, 'abcdefghijklmn'.rindex, 'abc', -10.0, 30)
 
 
+    def test_partition(self):
+
+        assert ('this is the par', 'ti', 'tion method') == \
+            'this is the partition method'.partition('ti')
+
+        # from raymond's original specification
+        S = 'http://www.python.org'
+        assert ('http', '://', 'www.python.org') == S.partition('://')
+        assert ('http://www.python.org', '', '') == S.partition('?')
+        assert ('', 'http://', 'www.python.org') == S.partition('http://')
+        assert ('http://www.python.', 'org', '') == S.partition('org')
+
+        raises(ValueError, S.partition, '')
+        raises(TypeError, S.partition, None)
+
+    def test_rpartition(self):
+
+        assert ('this is the rparti', 'ti', 'on method') == \
+            'this is the rpartition method'.rpartition('ti')
+
+        # from raymond's original specification
+        S = 'http://www.python.org'
+        assert ('http', '://', 'www.python.org') == S.rpartition('://')
+        assert ('', '', 'http://www.python.org') == S.rpartition('?')
+        assert ('', 'http://', 'www.python.org') == S.rpartition('http://')
+        assert ('http://www.python.', 'org', '') == S.rpartition('org')
+
+        raises(ValueError, S.rpartition, '')
+        raises(TypeError, S.rpartition, None)
+
     def test_split_maxsplit(self):
         assert "/a/b/c".split('/', 2) == ['','a','b/c']
         assert "a/b/c".split("/") == ['a', 'b', 'c']

Modified: pypy/dist/pypy/objspace/std/tupleobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/tupleobject.py	(original)
+++ pypy/dist/pypy/objspace/std/tupleobject.py	Mon Mar  5 10:50:02 2007
@@ -28,13 +28,18 @@
     return wrapint(space, result)
 
 def getitem__Tuple_ANY(space, w_tuple, w_index):
-    items = w_tuple.wrappeditems
+    if not space.lookup(w_index, '__index__'):
+        raise OperationError(
+            space.w_TypeError,
+            space.wrap("tuple indices must be integers, not %s" %
+                       space.type(w_index).getname(space, '?')))
     try:
-        w_item = items[space.int_w(w_index)]
+        # XXX: getindex_w should get a second argument space.w_IndexError,
+        #      but that doesn't exist the first time this is called.
+        return w_tuple.wrappeditems[space.getindex_w(w_index)]
     except IndexError:
         raise OperationError(space.w_IndexError,
                              space.wrap("tuple index out of range"))
-    return w_item
 
 def getitem__Tuple_Slice(space, w_tuple, w_slice):
     items = w_tuple.wrappeditems
@@ -64,7 +69,7 @@
 
 def mul_tuple_times(space, w_tuple, w_times):
     try:
-        times = space.int_w(w_times)
+        times = space.getindex_w(w_times, space.w_OverflowError)
     except OperationError, e:
         if e.match(space, space.w_TypeError):
             raise FailedToImplement

Modified: pypy/dist/pypy/objspace/std/unicodeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/unicodeobject.py	(original)
+++ pypy/dist/pypy/objspace/std/unicodeobject.py	Mon Mar  5 10:50:02 2007
@@ -3,6 +3,7 @@
 from pypy.objspace.std.stringobject import W_StringObject
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.tupleobject import W_TupleObject
 from pypy.rlib.rarithmetic import intmask, ovfcheck
 from pypy.module.unicodedata import unicodedb_3_2_0 as unicodedb
 
@@ -203,7 +204,12 @@
     return space.wrap(len(w_uni._value))
 
 def getitem__Unicode_ANY(space, w_uni, w_index):
-    ival = space.int_w(w_index)
+    if not space.lookup(w_index, '__index__'):
+        raise OperationError(
+            space.w_TypeError,
+            space.wrap("string indices must be integers, not %s" %
+                       space.type(w_index).getname(space, '?')))
+    ival = space.getindex_w(w_index, space.w_IndexError)
     uni = w_uni._value
     ulen = len(uni)
     if ival < 0:
@@ -230,7 +236,7 @@
 def mul__Unicode_ANY(space, w_uni, w_times):
     chars = w_uni._value
     charlen = len(chars)
-    times = space.int_w(w_times)
+    times = space.getindex_w(w_times, space.w_OverflowError)
     if times <= 0 or charlen == 0:
         return W_UnicodeObject([])
     if times == 1:
@@ -860,15 +866,44 @@
                         type(retval).__name__)
     return retval
 
-def repr__Unicode(unistr):
-    import _codecs
-    return ''.join(_codecs.unicodeescape_string(unistr,len(unistr),True))
+# XXX: These should probably be written on interplevel 
+
+def unicode_partition__Unicode_Unicode(unistr, unisub):
+    pos = unistr.find(unisub)
+    if pos == -1:
+        return (unistr, u'', u'')
+    else:
+        return (unistr[:pos], unisub, unistr[pos+len(unisub):])
+
+def unicode_rpartition__Unicode_Unicode(unistr, unisub):
+    pos = unistr.rfind(unisub)
+    if pos == -1:
+        return (u'', u'', unistr)
+    else:
+        return (unistr[:pos], unisub, unistr[pos+len(unisub):])
+
+def unicode_startswith__Unicode_Tuple_ANY_ANY(unistr, prefixes, start, end):
+    for prefix in prefixes:
+        if unistr.startswith(prefix):
+            return True
+    return False
+
+def unicode_endswith__Unicode_Tuple_ANY_ANY(unistr, suffixes, start, end):
+    for suffix in suffixes:
+        if unistr.endswith(suffix):
+            return True
+    return False
 
 ''')
+
+mod__Unicode_ANY = app.interphook('mod__Unicode_ANY')
 unicode_expandtabs__Unicode_ANY = app.interphook('unicode_expandtabs__Unicode_ANY')
 unicode_translate__Unicode_ANY = app.interphook('unicode_translate__Unicode_ANY')
-mod__Unicode_ANY = app.interphook('mod__Unicode_ANY')
 unicode_encode__Unicode_ANY_ANY = app.interphook('unicode_encode__Unicode_ANY_ANY')
+unicode_partition__Unicode_Unicode = app.interphook('unicode_partition__Unicode_Unicode')
+unicode_rpartition__Unicode_Unicode = app.interphook('unicode_rpartition__Unicode_Unicode')
+unicode_startswith__Unicode_Tuple_ANY_ANY = app.interphook('unicode_startswith__Unicode_Tuple_ANY_ANY')
+unicode_endswith__Unicode_Tuple_ANY_ANY = app.interphook('unicode_endswith__Unicode_Tuple_ANY_ANY')
 
 # Move this into the _codecs module as 'unicodeescape_string (Remember to cater for quotes)'
 def repr__Unicode(space, w_unicode):

Modified: pypy/dist/pypy/objspace/std/unicodetype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/unicodetype.py	(original)
+++ pypy/dist/pypy/objspace/std/unicodetype.py	Mon Mar  5 10:50:02 2007
@@ -207,6 +207,19 @@
                              ' string x with zeros on the left, to fill a'
                              ' field\nof the specified width. The string x is'
                              ' never truncated.')
+unicode_partition  = SMM('partition', 2,
+                         doc='S.partition(sep) -> (head, sep, tail)\n\nSearches'
+                         ' for the separator sep in S, and returns the part before'
+                         ' it,\nthe separator itself, and the part after it.  If'
+                         ' the separator is not\nfound, returns S and two empty'
+                         ' strings.')
+unicode_rpartition = SMM('rpartition', 2,
+                     doc='S.rpartition(sep) -> (tail, sep, head)\n\nSearches'
+                         ' for the separator sep in S, starting at the end of S,'
+                         ' and returns\nthe part before it, the separator itself,'
+                         ' and the part after it.  If the\nseparator is not found,'
+                         ' returns two empty strings and S.')
+
 
 # ____________________________________________________________
 

Modified: pypy/dist/pypy/rlib/streamio.py
==============================================================================
--- pypy/dist/pypy/rlib/streamio.py	(original)
+++ pypy/dist/pypy/rlib/streamio.py	Mon Mar  5 10:50:02 2007
@@ -356,7 +356,7 @@
     ("read", [int]),
     ("write", [str]),
     ("tell", []),
-    ("seek", [int, int]),
+    ("seek", ["index", int]),
     ("readall", []),
     ("readline", []),
     ("truncate", [int]),



More information about the Pypy-commit mailing list