[pypy-commit] pypy set-strategies: refactored discard/delitem and wrote some more tests

l.diekmann noreply at buildbot.pypy.org
Thu Nov 10 13:50:08 CET 2011


Author: Lukas Diekmann <lukas.diekmann at uni-duesseldorf.de>
Branch: set-strategies
Changeset: r49179:0b43c3756798
Date: 2011-05-25 14:56 +0200
http://bitbucket.org/pypy/pypy/changeset/0b43c3756798/

Log:	refactored discard/delitem and wrote some more tests

diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -225,7 +225,7 @@
         w_set.add(w_key)
 
     def delitem(self, w_set, w_item):
-        raise KeyError
+        return False
 
     def discard(self, w_set, w_item):
         return False
@@ -321,53 +321,17 @@
             w_set.add(w_key)
 
     def delitem(self, w_set, w_item):
-        # not a normal set operation; only used internally
         d = self.cast_from_void_star(w_set.sstorage)
+        if not self.is_correct_type(w_item):
+            w_set.switch_to_object_strategy(self.space)
+            return w_set.delitem(w_item)
+
+        key = self.unwrap(w_item)
         try:
-            del d[self.unwrap(w_item)]
-        except KeyError:
-            raise
-
-    def discard(self, w_set, w_item):
-        from pypy.objspace.std.dictmultiobject import _is_sane_hash
-        d = self.cast_from_void_star(w_set.sstorage)
-        try:
-            del d[self.unwrap(w_item)]
+            del d[key]
             return True
         except KeyError:
             return False
-        except OperationError, e:
-            # raise any error except TypeError
-            if not e.match(self.space, self.space.w_TypeError):
-                raise
-            # if error is TypeError and w_item is not None, Int, String, Bool or Float
-            # (i.e. FakeObject) switch to object strategy and discard again
-            if (not _is_sane_hash(self.space, w_item) and
-                    self is not self.space.fromcache(ObjectSetStrategy)):
-                w_set.switch_to_object_strategy(self.space)
-                return w_set.discard(w_item)
-            # else we have two cases:
-            # - w_item is as set: then we convert it to frozenset and check again
-            # - type doesn't match (string in intstrategy): then we raise (cause w_f is none)
-            w_f = _convert_set_to_frozenset(self.space, w_item)
-            if w_f is None:
-                raise
-
-        # if w_item is a set and we are not in ObjectSetStrategy we are finished here
-        if not self.space.fromcache(ObjectSetStrategy):
-            return False
-
-        try:
-            del d[w_f] # XXX nonsense in intstrategy
-            return True
-        except KeyError:
-            return False
-        except OperationError, e:
-            #XXX is this ever tested?
-            assert False
-            if not e.match(space, space.w_TypeError):
-                raise
-            return False
 
     def getdict_w(self, w_set):
         result = newset(self.space)
@@ -821,10 +785,7 @@
             w_left.difference_update(w_other)
         else:
             for w_key in space.listview(w_other):
-                try:
-                    w_left.delitem(w_key)
-                except KeyError:
-                    pass
+                w_left.delitem(w_key)
 
 def inplace_sub__Set_Set(space, w_left, w_other):
     w_left.difference_update(w_other)
@@ -974,10 +935,20 @@
     frozenset if the argument is a set.
     Returns True if successfully removed.
     """
-    x = w_left.discard(w_item)
+    try:
+        deleted = w_left.delitem(w_item)
+    except OperationError, e:
+        if not e.match(space, space.w_TypeError):
+            raise
+        else:
+            w_f = _convert_set_to_frozenset(space, w_item)
+            if w_f is None:
+                raise
+            deleted = w_left.delitem(w_f)
+
     if w_left.length() == 0:
         w_left.switch_to_empty_strategy()
-    return x
+    return deleted
 
 def set_discard__Set_ANY(space, w_left, w_item):
     _discard_from_set(space, w_left, w_item)
diff --git a/pypy/objspace/std/test/test_setobject.py b/pypy/objspace/std/test/test_setobject.py
--- a/pypy/objspace/std/test/test_setobject.py
+++ b/pypy/objspace/std/test/test_setobject.py
@@ -14,6 +14,7 @@
 from pypy.objspace.std.setobject import and__Set_Set
 from pypy.objspace.std.setobject import set_intersection__Set
 from pypy.objspace.std.setobject import eq__Set_Set
+from pypy.conftest import gettestobjspace
 
 letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
 
@@ -58,6 +59,28 @@
 
 class AppTestAppSetTest:
 
+    def setup_class(self):
+        self.space = gettestobjspace()
+        w_fakeint = self.space.appexec([], """():
+            class FakeInt(object):
+                def __init__(self, value):
+                    self.value = value
+                def __hash__(self):
+                    return hash(self.value)
+
+                def __eq__(self, other):
+                    if other == self.value:
+                        return True
+                    return False
+            return FakeInt
+            """)
+        self.w_FakeInt = w_fakeint
+
+    def test_fakeint(self):
+        f1 = self.FakeInt(4)
+        assert f1 == 4
+        assert hash(f1) == hash(4)
+
     def test_simple(self):
         a = set([1,2,3])
         b = set()
@@ -546,52 +569,77 @@
                 yield i
         set([1,2,3,4,5]).issuperset(foo())
 
+    def test_fakeint_and_equals(self):
+        s1 = set([1,2,3,4])
+        s2 = set([1,2,self.FakeInt(3), 4])
+        assert s1 == s2
 
-    def test_fakeint_intstrategy(self):
-        class FakeInt(object):
+    def test_fakeint_and_discard(self):
+        # test with object strategy
+        s = set([1, 2, 'three', 'four'])
+        s.discard(self.FakeInt(2))
+        assert s == set([1, 'three', 'four'])
+
+        s.remove(self.FakeInt(1))
+        assert s == set(['three', 'four'])
+        raises(KeyError, s.remove, self.FakeInt(16))
+
+        # test with int strategy
+        s = set([1,2,3,4])
+        s.discard(self.FakeInt(4))
+        assert s == set([1,2,3])
+        s.remove(self.FakeInt(3))
+        assert s == set([1,2])
+        raises(KeyError, s.remove, self.FakeInt(16))
+
+    def test_fakeobject_and_has_key(self):
+        s = set([1,2,3,4,5])
+        assert 5 in s
+        assert self.FakeInt(5) in s
+
+    def test_fakeobject_and_pop(self):
+        s = set([1,2,3,self.FakeInt(4), 5])
+        assert s.pop()
+        assert s.pop()
+        assert s.pop()
+        assert s.pop()
+        assert s.pop()
+        assert s == set([])
+
+    def test_fakeobject_and_difference(self):
+        s = set([1,2,'3',4])
+        s.difference_update([self.FakeInt(1), self.FakeInt(2)])
+        assert s == set(['3',4])
+
+        s = set([1,2,3,4])
+        s.difference_update([self.FakeInt(1), self.FakeInt(2)])
+        assert s == set([3,4])
+
+    def test_frozenset_behavior(self):
+        s = set([1,2,3,frozenset([4])])
+        raises(TypeError, s.difference_update, [1,2,3,set([4])])
+
+        s = set([1,2,3,frozenset([4])])
+        s.discard(set([4]))
+        assert s == set([1,2,3])
+
+    def test_discard_unhashable(self):
+        s = set([1,2,3,4])
+        raises(TypeError, s.discard, [1])
+
+
+    def test_discard_evil_compare(self):
+        class Evil(object):
             def __init__(self, value):
                 self.value = value
             def __hash__(self):
                 return hash(self.value)
-
             def __eq__(self, other):
+                if isinstance(other, frozenset):
+                    raise TypeError
                 if other == self.value:
                     return True
                 return False
+        s = set([1,2, Evil(frozenset([1]))])
+        raises(TypeError, s.discard, set([1]))
 
-        f1 = FakeInt(4)
-        assert f1 == 4
-        assert hash(f1) == hash(4)
-
-        # test with object strategy
-        s = set([1, 2, 'three', 'four'])
-        s.discard(FakeInt(2))
-        assert s == set([1, 'three', 'four'])
-        s.remove(FakeInt(1))
-        assert s == set(['three', 'four'])
-        raises(KeyError, s.remove, FakeInt(16))
-
-        # test with int strategy
-        s = set([1,2,3,4])
-        s.discard(FakeInt(4))
-        assert s == set([1,2,3])
-        s.remove(FakeInt(3))
-        assert s == set([1,2])
-        raises(KeyError, s.remove, FakeInt(16))
-
-
-    def test_fakeobject_and_has_key(test):
-        class FakeInt(object):
-            def __init__(self, value):
-                self.value = value
-            def __hash__(self):
-                return hash(self.value)
-
-            def __eq__(self, other):
-                if other == self.value:
-                    return True
-                return False
-
-        s = set([1,2,3,4,5])
-        assert 5 in s
-        assert FakeInt(5) in s


More information about the pypy-commit mailing list