Author: Laurence Tratt <[email protected]>
Branch: more_strategies
Changeset: r67877:b18acdb9aaf4
Date: 2013-11-07 23:11 +0000
http://bitbucket.org/pypy/pypy/changeset/b18acdb9aaf4/

Log:    Treat floats in integer lists more carefully.

        Previously floats were all rounded off, which leads to incorrect
        semantics for any float with a fractional component. A float which,
        when converted to an integer, doesn't compare True to itself can
        never match against any integer, so simply bail out when such a
        float is encountered. Bug pointed out to Amaury Forgeot d'Arc.

diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -1556,10 +1556,17 @@
             return self._safe_find(w_list, self.unwrap(w_obj), start, stop)
         elif w_objt is W_FloatObject or w_objt is W_LongObject:
             if w_objt is W_FloatObject:
+                # Floats with a fractional part can never compare True with
+                # respect to an integer, so we convert the float to an int and
+                # see if it compares True to itself or not. If it doesn't, we
+                # can immediately bail out.
+                w_objn = self.space.int(w_obj)
+                if not self.space.eq_w(w_obj, w_objn):
+                    raise ValueError
+                w_obj = w_objn
                 # Asking for an int from a W_FloatObject can return either a
                 # W_IntObject or W_LongObject, so we then need to disambiguate
                 # between the two.
-                w_obj = self.space.int(w_obj)
                 w_objt = type(w_obj)
 
             if w_objt is W_IntObject:
diff --git a/pypy/objspace/std/test/test_listobject.py 
b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -457,8 +457,7 @@
         assert l.__contains__(2)
         assert not l.__contains__("2")
         assert l.__contains__(1.0)
-        assert l.__contains__(1.1)
-        assert l.__contains__(1.9)
+        assert not l.__contains__(1.1)
         assert l.__contains__(1L)
         assert not l.__contains__(object())
         assert not l.__contains__(object())
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to