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