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