[pypy-commit] pypy set-strategies: added fixes and tests for symmetric_difference[_update]

l.diekmann noreply at buildbot.pypy.org
Thu Nov 10 13:49:28 CET 2011


Author: Lukas Diekmann <lukas.diekmann at uni-duesseldorf.de>
Branch: set-strategies
Changeset: r49146:28ab4895a815
Date: 2011-05-10 11:59 +0200
http://bitbucket.org/pypy/pypy/changeset/28ab4895a815/

Log:	added fixes and tests for symmetric_difference[_update]

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
@@ -113,6 +113,12 @@
     def difference_update(self, w_other):
         return self.strategy.difference_update(self, w_other)
 
+    def symmetric_difference(self, w_other):
+        return self.strategy.symmetric_difference(self, w_other)
+
+    def symmetric_difference_update(self, w_other):
+        return self.strategy.symmetric_difference_update(self, w_other)
+
     def intersect(self, w_other):
         return self.strategy.intersect(self, w_other)
 
@@ -289,6 +295,31 @@
                 except KeyError:
                     pass
 
+    def symmetric_difference(self, w_set, w_other):
+        #XXX no wrapping when strategies are equal
+        result = w_set._newobj(self.space, newset(self.space))
+        for w_key in w_set.getkeys():
+            if not w_other.has_key(w_key):
+                result.add(w_key)
+        for w_key in w_other.getkeys():
+            if not w_set.has_key(w_key):
+                result.add(w_key)
+        return result
+
+    def symmetric_difference_update(self, w_set, w_other):
+        #XXX no wrapping when strategies are equal
+        newsetdata = newset(self.space)
+        for w_key in w_set.getkeys():
+            if not w_other.has_key(w_key):
+                newsetdata[w_key] = None
+        for w_key in w_other.getkeys():
+            if not w_set.has_key(w_key):
+                newsetdata[w_key] = None
+
+        # do not switch strategy here if other items match
+        w_set.strategy = strategy = self.space.fromcache(ObjectSetStrategy)
+        w_set.sstorage = strategy.cast_to_void_star(newsetdata)
+
     def intersect(self, w_set, w_other):
         if w_set.length() > w_other.length():
             return w_other.intersect(w_set)
@@ -811,9 +842,8 @@
 
 def set_symmetric_difference__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
-    ld, rd = w_left.setdata, w_other.setdata
-    new_ld = _symmetric_difference_dict(space, ld, rd)
-    return w_left._newobj(space, new_ld)
+    w_result = w_left.symmetric_difference(w_other)
+    return w_result
 
 set_symmetric_difference__Set_Frozenset = set_symmetric_difference__Set_Set
 set_symmetric_difference__Frozenset_Set = set_symmetric_difference__Set_Set
@@ -827,26 +857,28 @@
 
 
 def set_symmetric_difference__Set_ANY(space, w_left, w_other):
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld = _symmetric_difference_dict(space, ld, rd)
-    return w_left._newobj(space, new_ld)
+    #XXX deal with iterables withouth turning them into sets
+    setdata = make_setdata_from_w_iterable(space, w_other)
+    w_other_as_set = w_left._newobj(space, setdata)
+
+    w_result = w_left.symmetric_difference(w_other_as_set)
+    return w_result
 
 frozenset_symmetric_difference__Frozenset_ANY = \
         set_symmetric_difference__Set_ANY
 
 def set_symmetric_difference_update__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
-    ld, rd = w_left.setdata, w_other.setdata
-    new_ld = _symmetric_difference_dict(space, ld, rd)
-    w_left.setdata = new_ld
+    w_left.symmetric_difference_update(w_other)
 
 set_symmetric_difference_update__Set_Frozenset = \
                                     set_symmetric_difference_update__Set_Set
 
 def set_symmetric_difference_update__Set_ANY(space, w_left, w_other):
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld = _symmetric_difference_dict(space, ld, rd)
-    w_left.setdata = new_ld
+    #XXX deal with iterables withouth turning them into sets
+    setdata = make_setdata_from_w_iterable(space, w_other)
+    w_other_as_set = w_left._newobj(space, setdata)
+    w_left.symmetric_difference_update(w_other_as_set)
 
 def inplace_xor__Set_Set(space, w_left, w_other):
     set_symmetric_difference_update__Set_Set(space, w_left, w_other)
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
@@ -121,6 +121,33 @@
         assert a == set()
         raises(KeyError, "a.pop()")
 
+    def test_symmetric_difference(self):
+        a = set([1,2,3])
+        b = set([3,4,5])
+        c = a.symmetric_difference(b)
+        assert c == set([1,2,4,5])
+
+        a = set([1,2,3])
+        b = [3,4,5]
+        c = a.symmetric_difference(b)
+        assert c == set([1,2,4,5])
+
+    def test_symmetric_difference_update(self):
+        a = set([1,2,3])
+        b = set([3,4,5])
+        a.symmetric_difference_update(b)
+        assert a == set([1,2,4,5])
+
+        a = set([1,2,3])
+        b = [3,4,5]
+        a.symmetric_difference_update(b)
+        assert a == set([1,2,4,5])
+
+        a = set([1,2,3])
+        b = set([3,4,5])
+        a ^= b
+        assert a == set([1,2,4,5])
+
     def test_subtype(self):
         class subset(set):pass
         a = subset()


More information about the pypy-commit mailing list