Author: Amaury Forgeot d'Arc <[email protected]>
Branch: py3.3
Changeset: r71010:b33a765ba524
Date: 2014-04-26 21:45 +0200
http://bitbucket.org/pypy/pypy/changeset/b33a765ba524/

Log:    Equality for range objects is now based on equality of the
        underlying sequences (CPython Issue #13201)

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
@@ -447,6 +447,31 @@
         w_index = space.sub(w_item, self.w_start)
         return space.floordiv(w_index, self.w_step)
 
+    def descr_eq(self, space, w_other):
+        # Compare two range objects.
+        if space.is_w(self, w_other):
+            return space.w_True
+        if not isinstance(w_other, W_Range):
+            return space.w_NotImplemented
+        if not space.eq_w(self.w_length, w_other.w_length):
+            return space.w_False
+        if space.eq_w(self.w_length, space.wrap(0)):
+            return space.w_True
+        if not space.eq_w(self.w_start, w_other.w_start):
+            return space.w_False
+        if space.eq_w(self.w_length, space.wrap(1)):
+            return space.w_True
+        return space.eq(self.w_step, w_other.w_step)
+
+    def descr_hash(self, space):
+        if space.eq_w(self.w_length, space.wrap(0)):
+            w_tup = space.newtuple([self.w_length, space.w_None, space.w_None])
+        elif space.eq_w(self.w_length, space.wrap(0)):
+            w_tup = space.newtuple([self.w_length, self.w_start, space.w_None])
+        else:
+            w_tup = space.newtuple([self.w_length, self.w_start, self.w_step])
+        return space.hash(w_tup)
+
 
 W_Range.typedef = TypeDef("range",
     __new__          = interp2app(W_Range.descr_new.im_func),
@@ -457,6 +482,8 @@
     __reversed__     = interp2app(W_Range.descr_reversed),
     __reduce__       = interp2app(W_Range.descr_reduce),
     __contains__     = interp2app(W_Range.descr_contains),
+    __eq__           = interp2app(W_Range.descr_eq),
+    __hash__         = interp2app(W_Range.descr_hash),
     count            = interp2app(W_Range.descr_count),
     index            = interp2app(W_Range.descr_index),
     start            = interp_attrproperty_w('w_start', cls=W_Range),
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
@@ -462,6 +462,50 @@
         raises(AttributeError, "del rangeobj.stop")
         raises(AttributeError, "del rangeobj.step")
 
+    def test_comparison(self):
+        test_ranges = [range(0), range(0, -1), range(1, 1, 3),
+                       range(1), range(5, 6), range(5, 6, 2),
+                       range(5, 7, 2), range(2), range(0, 4, 2),
+                       range(0, 5, 2), range(0, 6, 2)]
+        test_tuples = list(map(tuple, test_ranges))
+
+        # Check that equality of ranges matches equality of the corresponding
+        # tuples for each pair from the test lists above.
+        ranges_eq = [a == b for a in test_ranges for b in test_ranges]
+        tuples_eq = [a == b for a in test_tuples for b in test_tuples]
+        assert ranges_eq == tuples_eq
+
+        # Check that != correctly gives the logical negation of ==
+        ranges_ne = [a != b for a in test_ranges for b in test_ranges]
+        assert ranges_ne == [not x for x in ranges_eq]
+
+        # Equal ranges should have equal hashes.
+        for a in test_ranges:
+            for b in test_ranges:
+                if a == b:
+                    assert (hash(a), hash(b))
+
+        # Ranges are unequal to other types (even sequence types)
+        assert (range(0) == ()) is False
+        assert (() == range(0)) is False
+        assert (range(2) == [0, 1]) is False
+
+        # Huge integers aren't a problem.
+        assert range(0, 2**100 - 1, 2) == range(0, 2**100, 2)
+        assert hash(range(0, 2**100 - 1, 2)) == hash(range(0, 2**100, 2))
+        assert range(0, 2**100, 2) != range(0, 2**100 + 1, 2)
+        assert (range(2**200, 2**201 - 2**99, 2**100) ==
+                range(2**200, 2**201, 2**100))
+        assert (hash(range(2**200, 2**201 - 2**99, 2**100)) ==
+                hash(range(2**200, 2**201, 2**100)))
+        assert (range(2**200, 2**201, 2**100) !=
+                range(2**200, 2**201 + 1, 2**100))
+
+        # Order comparisons are not implemented for ranges.
+        raises(TypeError, "range(0) < range(0)")
+        raises(TypeError, "range(0) > range(0)")
+        raises(TypeError, "range(0) <= range(0)")
+        raises(TypeError, "range(0) >= range(0)")
 
 class AppTestReversed:
     def test_reversed(self):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to