Author: Philip Jenvey <[email protected]>
Branch: py3k
Changeset: r62188:a8c28f968217
Date: 2013-03-07 14:12 -0800
http://bitbucket.org/pypy/pypy/changeset/a8c28f968217/

Log:    add range.index and make a couple fixes to contains/count

diff --git a/pypy/module/__builtin__/functional.py 
b/pypy/module/__builtin__/functional.py
--- a/pypy/module/__builtin__/functional.py
+++ b/pypy/module/__builtin__/functional.py
@@ -4,7 +4,7 @@
 """
 
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from pypy.interpreter.typedef import TypeDef
 from rpython.rlib import jit
@@ -422,24 +422,31 @@
         return True
 
     def descr_contains(self, space, w_item):
-        try:
-            int_value = space.int_w(w_item)
-        except OperationError, e:
-            if not e.match(space, space.w_TypeError):
-                raise
+        w_type = space.type(w_item)
+        if space.is_w(w_type, space.w_int) or space.is_w(w_type, space.w_bool):
+            return space.newbool(self._contains_long(space, w_item))
+        else:
             return space.sequence_contains(self, w_item)
-        else:
-            return space.newbool(self._contains_long(space, w_item))
 
     def descr_count(self, space, w_item):
-        try:
-            int_value = space.int_w(w_item)
-        except OperationError, e:
-            if not e.match(space, space.w_TypeError):
-                raise
+        w_type = space.type(w_item)
+        if space.is_w(w_type, space.w_int) or space.is_w(w_type, space.w_bool):
+            return space.newint(self._contains_long(space, w_item))
+        else:
             return space.sequence_count(self, w_item)
-        else:
-            return space.newint(self._contains_long(space, w_item))
+
+    def descr_index(self, space, w_item):
+        w_type = space.type(w_item)
+        if not (space.is_w(w_type, space.w_int) or
+                space.is_w(w_type, space.w_bool)):
+            return space.sequence_index(self, w_item)
+
+        if not self._contains_long(space, w_item):
+            item_repr = space.unicode_w(space.repr(w_item))
+            raise operationerrfmt(space.w_ValueError, u"%s is not in range",
+                                  item_repr)
+        w_index = space.sub(w_item, self.w_start)
+        return space.floordiv(w_index, self.w_step)
 
 
 W_Range.typedef = TypeDef("range",
@@ -452,6 +459,7 @@
     __reduce__       = interp2app(W_Range.descr_reduce),
     __contains__     = interp2app(W_Range.descr_contains),
     count            = interp2app(W_Range.descr_count),
+    index            = interp2app(W_Range.descr_index),
 )
 
 class W_RangeIterator(Wrappable):
diff --git a/pypy/module/__builtin__/test/test_functional.py 
b/pypy/module/__builtin__/test/test_functional.py
--- a/pypy/module/__builtin__/test/test_functional.py
+++ b/pypy/module/__builtin__/test/test_functional.py
@@ -345,6 +345,69 @@
             assert b not in x
             raises(OverflowError, len, x)
             assert _range_len(x) == expected_len
+            assert x[0] == a
+            idx = sys.maxsize + 1
+            assert x[idx] == a + idx
+            assert a[idx:idx + 1][0] == a + idx
+            try:
+                x[-expected_len - 1]
+            except IndexError:
+                pass
+            else:
+                assert False, 'Expected IndexError'
+            try:
+                x[expected_len]
+            except IndexError:
+                pass
+            else:
+                assert False, 'Expected IndexError'
+
+    def test_range_index(self):
+        u = range(2)
+        assert u.index(0) == 0
+        assert u.index(1) == 1
+        raises(ValueError, u.index, 2)
+        raises(ValueError, u.index, object())
+        raises(TypeError, u.index)
+
+        assert range(1, 10, 3).index(4) == 1
+        assert range(1, -10, -3).index(-5) == 2
+
+        assert range(10**20).index(1) == 1
+        assert range(10**20).index(10**20 - 1) == 10**20 - 1
+
+        raises(ValueError, range(1, 2**100, 2).index, 2**87)
+        assert range(1, 2**100, 2).index(2**87+1) == 2**86
+
+        class AlwaysEqual(object):
+            def __eq__(self, other):
+                return True
+        always_equal = AlwaysEqual()
+        assert range(10).index(always_equal) == 0
+
+    def test_range_types(self):
+        assert 1.0 in range(3)
+        assert True in range(3)
+        assert 1+0j in range(3)
+
+        class C1:
+            def __eq__(self, other): return True
+        assert C1() in range(3)
+
+        # Objects are never coerced into other types for comparison.
+        class C2:
+            def __int__(self): return 1
+            def __index__(self): return 1
+        assert C2() not in range(3)
+        # ..except if explicitly told so.
+        assert int(C2()) in range(3)
+
+        # Check that the range.__contains__ optimization is only
+        # used for ints, not for instances of subclasses of int.
+        class C3(int):
+            def __eq__(self, other): return True
+        assert C3(11) in range(10)
+        assert C3(11) in list(range(10))
 
     def test_range_reduce(self):
         x = range(2, 9, 3)
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -439,6 +439,21 @@
             if space.eq_w(w_next, w_item):
                 count += 1
 
+    def sequence_index(space, w_container, w_item):
+        w_iter = space.iter(w_container)
+        index = 0
+        while 1:
+            try:
+                w_next = space.next(w_iter)
+            except OperationError, e:
+                if not e.match(space, space.w_StopIteration):
+                    raise
+                msg = "sequence.index(x): x not in sequence"
+                raise OperationError(space.w_ValueError, space.wrap(msg))
+            if space.eq_w(w_next, w_item):
+                return space.wrap(index)
+            index += 1
+
     def hash(space, w_obj):
         w_hash = space.lookup(w_obj, '__hash__')
         if w_hash is None:
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to