[pypy-commit] pypy list-strategies: need to use space.eq_w and be safe against mutating for objectlists

l.diekmann noreply at buildbot.pypy.org
Fri Sep 23 13:15:30 CEST 2011


Author: Lukas Diekmann <lukas.diekmann at uni-duesseldorf.de>
Branch: list-strategies
Changeset: r47548:7e62a6e1516b
Date: 2011-09-14 11:47 +0200
http://bitbucket.org/pypy/pypy/changeset/7e62a6e1516b/

Log:	need to use space.eq_w and be safe against mutating for objectlists

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
@@ -179,7 +179,13 @@
         raise NotImplementedError
 
     def contains(self, w_list, w_obj):
-        raise NotImplementedError
+        # needs to be safe against eq_w() mutating the w_list behind our back
+        i = 0
+        while i < w_list.length(): # intentionally always calling len!
+            if self.space.eq_w(w_list.getitem(i), w_obj):
+                return True
+            i += 1
+        return False
 
     def length(self, w_list):
         raise NotImplementedError
@@ -255,7 +261,7 @@
         pass
 
     def contains(self, w_list, w_obj):
-        return self.space.w_False
+        return False
 
     def length(self, w_list):
         return 0
@@ -349,11 +355,14 @@
             start, step, length = self.unerase(w_list.lstorage)
             obj = self.unwrap(w_obj)
             i = start
+           #if 0 <= (obj - start) <= length * step and (obj - start) % step == 0:
+           #    return True
             while i < start + step * length:
                 if i == obj:
-                    return self.space.w_True
+                    return True
                 i += step
-        return self.space.w_False
+
+        return ListStrategy.contains(self, w_list, w_obj)
 
     def length(self, w_list):
         return self.unerase(w_list.lstorage)[2]
@@ -536,11 +545,10 @@
         if self.is_correct_type(w_obj):
             obj = self.unwrap(w_obj)
             l = self.unerase(w_list.lstorage)
-            #XXX why do I need to check mutation for eq_w?
             for i in l:
                 if i == obj:
-                    return self.space.w_True
-        return self.space.w_False
+                    return True
+        return ListStrategy.contains(self, w_list, w_obj)
 
     def length(self, w_list):
         return len(self.unerase(w_list.lstorage))
@@ -773,6 +781,9 @@
     def init_from_list_w(self, w_list, list_w):
         w_list.lstorage = self.erase(list_w)
 
+    def contains(self, w_list, w_obj):
+        return ListStrategy.contains(self, w_list, w_obj)
+
     def getitems(self, w_list):
         return self.unerase(w_list.lstorage)
 
@@ -947,8 +958,7 @@
     w_list.deleteslice(start, 1, stop-start)
 
 def contains__List_ANY(space, w_list, w_obj):
-    # needs to be safe against eq_w() mutating the w_list behind our back
-    return w_list.contains(w_obj)
+    return space.wrap(w_list.contains(w_obj))
 
 def iter__List(space, w_list):
     from pypy.objspace.std import iterobject
@@ -959,7 +969,6 @@
     w_clone.extend(w_list2)
     return w_clone
 
-
 def inplace_add__List_ANY(space, w_list1, w_iterable2):
     try:
         list_extend__List_ANY(space, w_list1, w_iterable2)
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
@@ -360,6 +360,7 @@
         l = [1,2,3]
         assert l.__contains__(2)
         assert not l.__contains__("2")
+        assert l.__contains__(1.0)
 
         l = ["1","2","3"]
         assert l.__contains__("2")
@@ -845,6 +846,20 @@
         l.remove(5)
         assert l[10:] == [0, 1, 2, 3, 4, 6, 7, 8, 9]
 
+    def test_mutate_while_contains(self):
+        class Mean(object):
+            def __init__(self, i):
+                self.i = i
+            def __eq__(self, other):
+                if self.i == 9 == other:
+                    del l[0]
+                    return True
+                else:
+                    return False
+        l = [Mean(i) for i in range(10)]
+        assert l.__contains__(9)
+        assert not l.__contains__(2)
+
     def test_mutate_while_extend(self):
         # this used to segfault pypy-c (with py.test -A)
         import sys


More information about the pypy-commit mailing list