Author: Maciej Fijalkowski <[email protected]>
Branch: identity-set
Changeset: r65046:bab634a518bf
Date: 2013-06-28 09:27 +0200
http://bitbucket.org/pypy/pypy/changeset/bab634a518bf/

Log:    (andrewchambers) identity set strategy

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
@@ -26,7 +26,7 @@
     def __repr__(self):
         """representation for debugging purposes"""
         reprlist = [repr(w_item) for w_item in self.getkeys()]
-        return "<%s(%s)>" % (self.__class__.__name__, ', '.join(reprlist))
+        return "<%s(%s)(%s)>" % (self.__class__.__name__, self.strategy, ', 
'.join(reprlist))
 
     def from_storage_and_strategy(self, storage, strategy):
         obj = self._newobj(self.space, None)
@@ -780,6 +780,8 @@
             strategy = self.space.fromcache(StringSetStrategy)
         elif type(w_key) is W_UnicodeObject:
             strategy = self.space.fromcache(UnicodeSetStrategy)
+        elif self.space.type(w_key).compares_by_identity():
+            strategy = self.space.fromcache(IdentitySetStrategy)
         else:
             strategy = self.space.fromcache(ObjectSetStrategy)
         w_set.strategy = strategy
@@ -1336,6 +1338,41 @@
                 break
             d_obj[w_item] = None
 
+class IdentitySetStrategy(AbstractUnwrappedSetStrategy, SetStrategy):
+    erase, unerase = rerased.new_erasing_pair("identityset")
+    erase = staticmethod(erase)
+    unerase = staticmethod(unerase)
+    
+    def get_empty_storage(self):
+        return self.erase({})
+
+    def get_empty_dict(self):
+        return {}
+
+    def is_correct_type(self, w_key):
+        w_type = self.space.type(w_key)
+        return w_type.compares_by_identity()
+
+    def may_contain_equal_elements(self, strategy):
+        #empty first, probably more likely
+        if strategy is self.space.fromcache(EmptySetStrategy):
+            return False
+        if strategy is self.space.fromcache(IntegerSetStrategy):
+            return False
+        if strategy is self.space.fromcache(StringSetStrategy):
+            return False
+        if strategy is self.space.fromcache(UnicodeSetStrategy):
+            return False
+        return True
+
+    def unwrap(self, w_item):
+        return w_item
+
+    def wrap(self, item):
+        return item    
+    
+    def iter(self, w_set):
+        return IdentityIteratorImplementation(self.space, self, w_set)        
 
 class IteratorImplementation(object):
     def __init__(self, space, strategy, implementation):
@@ -1427,6 +1464,17 @@
         else:
             return None
 
+class IdentityIteratorImplementation(IteratorImplementation):
+    def __init__(self, space, strategy, w_set):
+        IteratorImplementation.__init__(self, space, strategy, w_set)
+        d = strategy.unerase(w_set.sstorage)
+        self.iterator = d.iterkeys()
+
+    def next_entry(self):
+        for key in self.iterator:
+            return self.space.wrap(key)
+        else:
+            return None
 
 class RDictIteratorImplementation(IteratorImplementation):
     def __init__(self, space, strategy, w_set):
@@ -1545,6 +1593,15 @@
         w_set.strategy = space.fromcache(UnicodeSetStrategy)
         w_set.sstorage = w_set.strategy.get_storage_from_list(iterable_w)
         return
+    
+    # check for compares by identity
+    for w_item in iterable_w:
+        if not space.type(w_item).compares_by_identity():
+            break
+    else:
+        w_set.strategy = space.fromcache(IdentitySetStrategy)
+        w_set.sstorage = w_set.strategy.get_storage_from_list(iterable_w)
+        return    
 
     w_set.strategy = space.fromcache(ObjectSetStrategy)
     w_set.sstorage = w_set.strategy.get_storage_from_list(iterable_w)
diff --git a/pypy/objspace/std/test/test_identityset.py 
b/pypy/objspace/std/test/test_identityset.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/test/test_identityset.py
@@ -0,0 +1,98 @@
+import py
+
+
+
+class AppTestIdentitySet(object):
+    
+    #needed for compares_by_identity
+    spaceconfig = {"objspace.std.withidentitydict": True}
+    
+    def setup_class(cls):
+        from pypy.objspace.std import identitydict
+        if cls.runappdirect:
+            py.test.skip("interp2app doesn't work on appdirect")
+    
+    def w_uses_strategy(self, s , obj):
+        import __pypy__
+        return s in __pypy__.internal_repr(obj)
+    
+    def test_use_identity_strategy(self):
+        
+        class Plain(object):
+            pass
+
+        class CustomEq(object):
+            def __eq__(self, other):
+                return True
+
+        class CustomCmp (object):
+            def __cmp__(self, other):
+                return 0
+
+        class CustomHash(object):
+            def __hash__(self):
+                return 0
+            
+        s = set()
+        
+        assert not self.uses_strategy('IdentitySetStrategy',s)
+        
+        s.add(Plain())
+        
+        assert self.uses_strategy('IdentitySetStrategy',s)
+        
+        for cls in [CustomEq,CustomCmp,CustomHash]:
+            s = set()
+            s.add(cls())
+            assert not self.uses_strategy('IdentitySetStrategy',s)
+        
+        
+    def test_use_identity_strategy_list(self):
+        
+        class X(object):
+            pass
+        
+        assert self.uses_strategy('IdentitySetStrategy',set([X(),X()]))
+        assert not self.uses_strategy('IdentitySetStrategy',set([X(),""]))
+        assert not self.uses_strategy('IdentitySetStrategy',set([X(),u""]))
+        assert not self.uses_strategy('IdentitySetStrategy',set([X(),1]))
+        
+    def test_identity_strategy_add(self):
+        
+        class X(object):
+            pass
+        
+        class NotIdent(object):
+            def __eq__(self,other):
+                pass
+        
+        s = set([X(),X()])
+        s.add('foo')
+        assert not self.uses_strategy('IdentitySetStrategy',s)
+        s = set([X(),X()])
+        s.add(NotIdent())
+        assert not self.uses_strategy('IdentitySetStrategy',s)
+    
+    def test_identity_strategy_sanity(self):
+        
+        class X(object):
+            pass
+        
+        class Y(object):
+            pass
+        
+        a,b,c,d,e,f = X(),Y(),X(),Y(),X(),Y()
+        
+        s = set([a,b]).union(set([c]))
+        assert self.uses_strategy('IdentitySetStrategy',s) 
+        assert set([a,b,c]) == s
+        s = set([a,b,c,d,e,f]) - set([d,e,f])
+        assert self.uses_strategy('IdentitySetStrategy',s)
+        assert set([a,b,c]) == s
+        
+        
+        s = set([a])
+        s.update([b,c])
+        
+        assert s == set([a,b,c])
+
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to