[pypy-commit] pypy default: merge set-strategies:
arigo
noreply at buildbot.pypy.org
Mon Mar 26 21:28:59 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r54009:43f380907aa7
Date: 2012-03-26 21:27 +0200
http://bitbucket.org/pypy/pypy/changeset/43f380907aa7/
Log: merge set-strategies:
Add strategies to lists and sets. Some clean-ups in dicts,
too. (See the branch for details.)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_containers.py b/pypy/module/pypyjit/test_pypy_c/test_containers.py
--- a/pypy/module/pypyjit/test_pypy_c/test_containers.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_containers.py
@@ -128,3 +128,82 @@
loop, = log.loops_by_filename(self.filepath)
ops = loop.ops_by_id('look')
assert 'call' not in log.opnames(ops)
+
+ #XXX the following tests only work with strategies enabled
+
+ def test_should_not_create_intobject_with_sets(self):
+ def main(n):
+ i = 0
+ s = set()
+ while i < n:
+ s.add(i)
+ i += 1
+ log = self.run(main, [1000])
+ assert log.result == main(1000)
+ loop, = log.loops_by_filename(self.filepath)
+ opnames = log.opnames(loop.allops())
+ assert opnames.count('new_with_vtable') == 0
+
+ def test_should_not_create_stringobject_with_sets(self):
+ def main(n):
+ i = 0
+ s = set()
+ while i < n:
+ s.add(str(i))
+ i += 1
+ log = self.run(main, [1000])
+ assert log.result == main(1000)
+ loop, = log.loops_by_filename(self.filepath)
+ opnames = log.opnames(loop.allops())
+ assert opnames.count('new_with_vtable') == 0
+
+ def test_should_not_create_intobject_with_lists(self):
+ def main(n):
+ i = 0
+ l = []
+ while i < n:
+ l.append(i)
+ i += 1
+ log = self.run(main, [1000])
+ assert log.result == main(1000)
+ loop, = log.loops_by_filename(self.filepath)
+ opnames = log.opnames(loop.allops())
+ assert opnames.count('new_with_vtable') == 0
+
+ def test_should_not_create_stringobject_with_lists(self):
+ def main(n):
+ i = 0
+ l = []
+ while i < n:
+ l.append(str(i))
+ i += 1
+ log = self.run(main, [1000])
+ assert log.result == main(1000)
+ loop, = log.loops_by_filename(self.filepath)
+ opnames = log.opnames(loop.allops())
+ assert opnames.count('new_with_vtable') == 0
+
+ def test_optimized_create_list_from_string(self):
+ def main(n):
+ i = 0
+ l = []
+ while i < n:
+ l = list("abc" * i)
+ i += 1
+ log = self.run(main, [1000])
+ assert log.result == main(1000)
+ loop, = log.loops_by_filename(self.filepath)
+ opnames = log.opnames(loop.allops())
+ assert opnames.count('new_with_vtable') == 0
+
+ def test_optimized_create_set_from_list(self):
+ def main(n):
+ i = 0
+ while i < n:
+ s = set([1,2,3])
+ i += 1
+ log = self.run(main, [1000])
+ assert log.result == main(1000)
+ loop, = log.loops_by_filename(self.filepath)
+ opnames = log.opnames(loop.allops())
+ assert opnames.count('new_with_vtable') == 0
diff --git a/pypy/objspace/std/celldict.py b/pypy/objspace/std/celldict.py
--- a/pypy/objspace/std/celldict.py
+++ b/pypy/objspace/std/celldict.py
@@ -127,10 +127,10 @@
def iter(self, w_dict):
return ModuleDictIteratorImplementation(self.space, self, w_dict)
- def keys(self, w_dict):
+ def w_keys(self, w_dict):
space = self.space
- iterator = self.unerase(w_dict.dstorage).iteritems
- return [space.wrap(key) for key, cell in iterator()]
+ l = self.unerase(w_dict.dstorage).keys()
+ return space.newlist_str(l)
def values(self, w_dict):
iterator = self.unerase(w_dict.dstorage).itervalues
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -90,9 +90,9 @@
def _add_indirections():
dict_methods = "setitem setitem_str getitem \
getitem_str delitem length \
- clear keys values \
+ clear w_keys values \
items iter setdefault \
- popitem".split()
+ popitem listview_str listview_int".split()
def make_method(method):
def f(self, *args):
@@ -113,7 +113,7 @@
def get_empty_storage(self):
raise NotImplementedError
- def keys(self, w_dict):
+ def w_keys(self, w_dict):
iterator = self.iter(w_dict)
result = []
while 1:
@@ -121,7 +121,7 @@
if w_key is not None:
result.append(w_key)
else:
- return result
+ return self.space.newlist(result)
def values(self, w_dict):
iterator = self.iter(w_dict)
@@ -160,6 +160,11 @@
w_dict.strategy = strategy
w_dict.dstorage = storage
+ def listview_str(self, w_dict):
+ return None
+
+ def listview_int(self, w_dict):
+ return None
class EmptyDictStrategy(DictStrategy):
@@ -371,8 +376,9 @@
self.switch_to_object_strategy(w_dict)
return w_dict.getitem(w_key)
- def keys(self, w_dict):
- return [self.wrap(key) for key in self.unerase(w_dict.dstorage).iterkeys()]
+ def w_keys(self, w_dict):
+ l = [self.wrap(key) for key in self.unerase(w_dict.dstorage).iterkeys()]
+ return self.space.newlist(l)
def values(self, w_dict):
return self.unerase(w_dict.dstorage).values()
@@ -425,8 +431,8 @@
def iter(self, w_dict):
return ObjectIteratorImplementation(self.space, self, w_dict)
- def keys(self, w_dict):
- return self.unerase(w_dict.dstorage).keys()
+ def w_keys(self, w_dict):
+ return self.space.newlist(self.unerase(w_dict.dstorage).keys())
class StringDictStrategy(AbstractTypedStrategy, DictStrategy):
@@ -469,9 +475,15 @@
assert key is not None
return self.unerase(w_dict.dstorage).get(key, None)
+ def listview_str(self, w_dict):
+ return self.unerase(w_dict.dstorage).keys()
+
def iter(self, w_dict):
return StrIteratorImplementation(self.space, self, w_dict)
+ def w_keys(self, w_dict):
+ return self.space.newlist_str(self.listview_str(w_dict))
+
class _WrappedIteratorMixin(object):
_mixin_ = True
@@ -534,6 +546,14 @@
def iter(self, w_dict):
return IntIteratorImplementation(self.space, self, w_dict)
+ def listview_int(self, w_dict):
+ return self.unerase(w_dict.dstorage).keys()
+
+ def w_keys(self, w_dict):
+ # XXX there is no space.newlist_int yet
+ space = self.space
+ return space.call_function(space.w_list, w_dict)
+
class IntIteratorImplementation(_WrappedIteratorMixin, IteratorImplementation):
pass
@@ -688,7 +708,7 @@
return space.newlist(w_self.items())
def dict_keys__DictMulti(space, w_self):
- return space.newlist(w_self.keys())
+ return w_self.w_keys()
def dict_values__DictMulti(space, w_self):
return space.newlist(w_self.values())
diff --git a/pypy/objspace/std/dictproxyobject.py b/pypy/objspace/std/dictproxyobject.py
--- a/pypy/objspace/std/dictproxyobject.py
+++ b/pypy/objspace/std/dictproxyobject.py
@@ -76,7 +76,7 @@
def keys(self, w_dict):
space = self.space
- return [space.wrap(key) for key in self.unerase(w_dict.dstorage).dict_w.iterkeys()]
+ return space.newlist_str(self.unerase(w_dict.dstorage).dict_w.keys())
def values(self, w_dict):
return [unwrap_cell(self.space, w_value) for w_value in self.unerase(w_dict.dstorage).dict_w.itervalues()]
diff --git a/pypy/objspace/std/dicttype.py b/pypy/objspace/std/dicttype.py
--- a/pypy/objspace/std/dicttype.py
+++ b/pypy/objspace/std/dicttype.py
@@ -62,8 +62,14 @@
w_fill = space.w_None
if space.is_w(w_type, space.w_dict):
w_dict = W_DictMultiObject.allocate_and_init_instance(space, w_type)
- for w_key in space.listview(w_keys):
- w_dict.setitem(w_key, w_fill)
+
+ strlist = space.listview_str(w_keys)
+ if strlist is not None:
+ for key in strlist:
+ w_dict.setitem_str(key, w_fill)
+ else:
+ for w_key in space.listview(w_keys):
+ w_dict.setitem(w_key, w_fill)
else:
w_dict = space.call_function(w_type)
for w_key in space.listview(w_keys):
diff --git a/pypy/objspace/std/frozensettype.py b/pypy/objspace/std/frozensettype.py
--- a/pypy/objspace/std/frozensettype.py
+++ b/pypy/objspace/std/frozensettype.py
@@ -39,13 +39,11 @@
def descr__frozenset__new__(space, w_frozensettype,
w_iterable=gateway.NoneNotWrapped):
from pypy.objspace.std.setobject import W_FrozensetObject
- from pypy.objspace.std.setobject import make_setdata_from_w_iterable
if (space.is_w(w_frozensettype, space.w_frozenset) and
w_iterable is not None and type(w_iterable) is W_FrozensetObject):
return w_iterable
w_obj = space.allocate_instance(W_FrozensetObject, w_frozensettype)
- data = make_setdata_from_w_iterable(space, w_iterable)
- W_FrozensetObject.__init__(w_obj, space, data)
+ W_FrozensetObject.__init__(w_obj, space, w_iterable)
return w_obj
frozenset_typedef = StdTypeDef("frozenset",
diff --git a/pypy/objspace/std/iterobject.py b/pypy/objspace/std/iterobject.py
--- a/pypy/objspace/std/iterobject.py
+++ b/pypy/objspace/std/iterobject.py
@@ -29,9 +29,8 @@
class W_SeqIterObject(W_AbstractSeqIterObject):
"""Sequence iterator implementation for general sequences."""
-class W_FastListIterObject(W_AbstractSeqIterObject):
- """Sequence iterator specialized for lists, accessing directly their
- RPython-level list of wrapped objects.
+class W_FastListIterObject(W_AbstractSeqIterObject): # XXX still needed
+ """Sequence iterator specialized for lists.
"""
class W_FastTupleIterObject(W_AbstractSeqIterObject):
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
@@ -139,6 +139,16 @@
new erased object as storage"""
self.strategy.init_from_list_w(self, list_w)
+ def clear(self, space):
+ """Initializes (or overrides) the listobject as empty."""
+ self.space = space
+ if space.config.objspace.std.withliststrategies:
+ strategy = space.fromcache(EmptyListStrategy)
+ else:
+ strategy = space.fromcache(ObjectListStrategy)
+ self.strategy = strategy
+ strategy.clear(self)
+
def clone(self):
"""Returns a clone by creating a new listobject
with the same strategy and a copy of the storage"""
@@ -200,6 +210,11 @@
""" Return the items in the list as unwrapped strings. If the list does
not use the list strategy, return None. """
return self.strategy.getitems_str(self)
+
+ def getitems_int(self):
+ """ Return the items in the list as unwrapped ints. If the list does
+ not use the list strategy, return None. """
+ return self.strategy.getitems_int(self)
# ___________________________________________________
@@ -300,6 +315,9 @@
def getitems_str(self, w_list):
return None
+ def getitems_int(self, w_list):
+ return None
+
def getstorage_copy(self, w_list):
raise NotImplementedError
@@ -358,6 +376,9 @@
assert len(list_w) == 0
w_list.lstorage = self.erase(None)
+ def clear(self, w_list):
+ w_list.lstorage = self.erase(None)
+
erase, unerase = rerased.new_erasing_pair("empty")
erase = staticmethod(erase)
unerase = staticmethod(unerase)
@@ -516,6 +537,9 @@
raise IndexError
return start + i * step
+ def getitems_int(self, w_list):
+ return self._getitems_range(w_list, False)
+
def getitem(self, w_list, i):
return self.wrap(self._getitem_unwrapped(w_list, i))
@@ -696,6 +720,7 @@
for i in l:
if i == obj:
return True
+ return False
return ListStrategy.contains(self, w_list, w_obj)
def length(self, w_list):
@@ -937,6 +962,9 @@
def init_from_list_w(self, w_list, list_w):
w_list.lstorage = self.erase(list_w)
+ def clear(self, w_list):
+ w_list.lstorage = self.erase([])
+
def contains(self, w_list, w_obj):
return ListStrategy.contains(self, w_list, w_obj)
@@ -970,6 +998,9 @@
if reverse:
l.reverse()
+ def getitems_int(self, w_list):
+ return self.unerase(w_list.lstorage)
+
class FloatListStrategy(AbstractUnwrappedStrategy, ListStrategy):
_none_value = 0.0
_applevel_repr = "float"
@@ -1027,37 +1058,49 @@
def getitems_str(self, w_list):
return self.unerase(w_list.lstorage)
-
# _______________________________________________________
init_signature = Signature(['sequence'], None, None)
init_defaults = [None]
def init__List(space, w_list, __args__):
- from pypy.objspace.std.tupleobject import W_TupleObject
+ from pypy.objspace.std.tupleobject import W_AbstractTupleObject
# this is on the silly side
w_iterable, = __args__.parse_obj(
None, 'list', init_signature, init_defaults)
- w_list.__init__(space, [])
+ w_list.clear(space)
if w_iterable is not None:
- # unfortunately this is duplicating space.unpackiterable to avoid
- # assigning a new RPython list to 'wrappeditems', which defeats the
- # W_FastListIterObject optimization.
- if isinstance(w_iterable, W_ListObject):
- w_list.extend(w_iterable)
- elif isinstance(w_iterable, W_TupleObject):
- w_list.extend(W_ListObject(space, w_iterable.wrappeditems[:]))
- else:
- _init_from_iterable(space, w_list, w_iterable)
+ if type(w_iterable) is W_ListObject:
+ w_iterable.copy_into(w_list)
+ return
+ elif isinstance(w_iterable, W_AbstractTupleObject):
+ w_list.__init__(space, w_iterable.getitems_copy())
+ return
+
+ intlist = space.listview_int(w_iterable)
+ if intlist is not None:
+ w_list.strategy = strategy = space.fromcache(IntegerListStrategy)
+ # need to copy because intlist can share with w_iterable
+ w_list.lstorage = strategy.erase(intlist[:])
+ return
+
+ strlist = space.listview_str(w_iterable)
+ if strlist is not None:
+ w_list.strategy = strategy = space.fromcache(StringListStrategy)
+ # need to copy because intlist can share with w_iterable
+ w_list.lstorage = strategy.erase(strlist[:])
+ return
+
+ # xxx special hack for speed
+ from pypy.interpreter.generator import GeneratorIterator
+ if isinstance(w_iterable, GeneratorIterator):
+ w_iterable.unpack_into_w(w_list)
+ return
+ # /xxx
+ _init_from_iterable(space, w_list, w_iterable)
def _init_from_iterable(space, w_list, w_iterable):
# in its own function to make the JIT look into init__List
- # xxx special hack for speed
- from pypy.interpreter.generator import GeneratorIterator
- if isinstance(w_iterable, GeneratorIterator):
- w_iterable.unpack_into_w(w_list)
- return
- # /xxx
w_iterator = space.iter(w_iterable)
while True:
try:
diff --git a/pypy/objspace/std/listtype.py b/pypy/objspace/std/listtype.py
--- a/pypy/objspace/std/listtype.py
+++ b/pypy/objspace/std/listtype.py
@@ -43,7 +43,7 @@
def descr__new__(space, w_listtype, __args__):
from pypy.objspace.std.listobject import W_ListObject
w_obj = space.allocate_instance(W_ListObject, w_listtype)
- W_ListObject.__init__(w_obj, space, [])
+ w_obj.clear(space)
return w_obj
# ____________________________________________________________
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -694,6 +694,8 @@
self.delitem(w_dict, w_key)
return (w_key, w_value)
+ # XXX could implement a more efficient w_keys based on space.newlist_str
+
def materialize_r_dict(space, obj, dict_w):
map = obj._get_mapdict_map()
new_obj = map.materialize_r_dict(space, obj, dict_w)
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -227,10 +227,7 @@
return W_ComplexObject(x.real, x.imag)
if isinstance(x, set):
- rdict_w = r_dict(self.eq_w, self.hash_w)
- for item in x:
- rdict_w[self.wrap(item)] = None
- res = W_SetObject(self, rdict_w)
+ res = W_SetObject(self, self.newlist([self.wrap(item) for item in x]))
return res
if isinstance(x, frozenset):
@@ -325,7 +322,7 @@
def newset(self):
from pypy.objspace.std.setobject import newset
- return W_SetObject(self, newset(self))
+ return W_SetObject(self, None)
def newslice(self, w_start, w_end, w_step):
return W_SliceObject(w_start, w_end, w_step)
@@ -403,7 +400,7 @@
def unpackiterable(self, w_obj, expected_length=-1):
if isinstance(w_obj, W_AbstractTupleObject):
t = w_obj.getitems_copy()
- elif isinstance(w_obj, W_ListObject):
+ elif type(w_obj) is W_ListObject:
t = w_obj.getitems_copy()
else:
return ObjSpace.unpackiterable(self, w_obj, expected_length)
@@ -417,7 +414,7 @@
"""
if isinstance(w_obj, W_AbstractTupleObject):
t = w_obj.tolist()
- elif isinstance(w_obj, W_ListObject):
+ elif type(w_obj) is W_ListObject:
if unroll:
t = w_obj.getitems_unroll()
else:
@@ -438,7 +435,7 @@
return self.fixedview(w_obj, expected_length, unroll=True)
def listview(self, w_obj, expected_length=-1):
- if isinstance(w_obj, W_ListObject):
+ if type(w_obj) is W_ListObject:
t = w_obj.getitems()
elif isinstance(w_obj, W_AbstractTupleObject):
t = w_obj.getitems_copy()
@@ -449,8 +446,25 @@
return t
def listview_str(self, w_obj):
- if isinstance(w_obj, W_ListObject):
+ # note: uses exact type checking for objects with strategies,
+ # and isinstance() for others. See test_listobject.test_uses_custom...
+ if type(w_obj) is W_ListObject:
return w_obj.getitems_str()
+ if type(w_obj) is W_DictMultiObject:
+ return w_obj.listview_str()
+ if type(w_obj) is W_SetObject or type(w_obj) is W_FrozensetObject:
+ return w_obj.listview_str()
+ if isinstance(w_obj, W_StringObject):
+ return w_obj.listview_str()
+ return None
+
+ def listview_int(self, w_obj):
+ if type(w_obj) is W_ListObject:
+ return w_obj.getitems_int()
+ if type(w_obj) is W_DictMultiObject:
+ return w_obj.listview_int()
+ if type(w_obj) is W_SetObject or type(w_obj) is W_FrozensetObject:
+ return w_obj.listview_int()
return None
def sliceindices(self, w_slice, w_length):
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
@@ -7,6 +7,12 @@
from pypy.interpreter.argument import Signature
from pypy.objspace.std.settype import set_typedef as settypedef
from pypy.objspace.std.frozensettype import frozenset_typedef as frozensettypedef
+from pypy.rlib import rerased
+from pypy.rlib.objectmodel import instantiate
+from pypy.interpreter.generator import GeneratorIterator
+from pypy.objspace.std.listobject import W_ListObject
+from pypy.objspace.std.intobject import W_IntObject
+from pypy.objspace.std.stringobject import W_StringObject
class W_BaseSetObject(W_Object):
typedef = None
@@ -20,88 +26,859 @@
return True
return False
-
- def __init__(w_self, space, setdata):
+ def __init__(w_self, space, w_iterable=None):
"""Initialize the set by taking ownership of 'setdata'."""
- assert setdata is not None
- w_self.setdata = setdata
+ w_self.space = space
+ set_strategy_and_setdata(space, w_self, w_iterable)
def __repr__(w_self):
"""representation for debugging purposes"""
- reprlist = [repr(w_item) for w_item in w_self.setdata.keys()]
+ reprlist = [repr(w_item) for w_item in w_self.getkeys()]
return "<%s(%s)>" % (w_self.__class__.__name__, ', '.join(reprlist))
+ def from_storage_and_strategy(w_self, storage, strategy):
+ obj = w_self._newobj(w_self.space, None)
+ assert isinstance(obj, W_BaseSetObject)
+ obj.strategy = strategy
+ obj.sstorage = storage
+ return obj
+
_lifeline_ = None
def getweakref(self):
return self._lifeline_
+
def setweakref(self, space, weakreflifeline):
self._lifeline_ = weakreflifeline
def delweakref(self):
self._lifeline_ = None
+ def switch_to_object_strategy(self, space):
+ d = self.strategy.getdict_w(self)
+ self.strategy = strategy = space.fromcache(ObjectSetStrategy)
+ self.sstorage = strategy.erase(d)
+
+ def switch_to_empty_strategy(self):
+ self.strategy = strategy = self.space.fromcache(EmptySetStrategy)
+ self.sstorage = strategy.get_empty_storage()
+
+ # _____________ strategy methods ________________
+
+
+ def clear(self):
+ """ Removes all elements from the set. """
+ self.strategy.clear(self)
+
+ def copy_real(self):
+ """ Returns a clone of the set. Frozensets storages are also copied."""
+ return self.strategy.copy_real(self)
+
+ def length(self):
+ """ Returns the number of items inside the set. """
+ return self.strategy.length(self)
+
+ def add(self, w_key):
+ """ Adds an element to the set. The element must be wrapped. """
+ self.strategy.add(self, w_key)
+
+ def remove(self, w_item):
+ """ Removes the given element from the set. Element must be wrapped. """
+ return self.strategy.remove(self, w_item)
+
+ def getdict_w(self):
+ """ Returns a dict with all elements of the set. Needed only for switching to ObjectSetStrategy. """
+ return self.strategy.getdict_w(self)
+
+ def listview_str(self):
+ """ If this is a string set return its contents as a list of uwnrapped strings. Otherwise return None. """
+ return self.strategy.listview_str(self)
+
+ def listview_int(self):
+ """ If this is an int set return its contents as a list of uwnrapped ints. Otherwise return None. """
+ return self.strategy.listview_int(self)
+
+ def get_storage_copy(self):
+ """ Returns a copy of the storage. Needed when we want to clone all elements from one set and
+ put them into another. """
+ return self.strategy.get_storage_copy(self)
+
+ def getkeys(self):
+ """ Returns a list of all elements inside the set. Only used in __repr__. Use as less as possible."""
+ return self.strategy.getkeys(self)
+
+ def difference(self, w_other):
+ """ Returns a set with all items that are in this set, but not in w_other. W_other must be a set."""
+ return self.strategy.difference(self, w_other)
+
+ def difference_update(self, w_other):
+ """ As difference but overwrites the sets content with the result. W_other must be a set."""
+ self.strategy.difference_update(self, w_other)
+
+ def symmetric_difference(self, w_other):
+ """ Returns a set with all items that are either in this set or in w_other, but not in both. W_other must be a set. """
+ return self.strategy.symmetric_difference(self, w_other)
+
+ def symmetric_difference_update(self, w_other):
+ """ As symmetric_difference but overwrites the content of the set with the result. W_other must be a set."""
+ self.strategy.symmetric_difference_update(self, w_other)
+
+ def intersect(self, w_other):
+ """ Returns a set with all items that exists in both sets, this set and in w_other. W_other must be a set. """
+ return self.strategy.intersect(self, w_other)
+
+ def intersect_update(self, w_other):
+ """ Keeps only those elements found in both sets, removing all other elements. W_other must be a set."""
+ self.strategy.intersect_update(self, w_other)
+
+ def issubset(self, w_other):
+ """ Checks wether this set is a subset of w_other. W_other must be a set. """
+ return self.strategy.issubset(self, w_other)
+
+ def isdisjoint(self, w_other):
+ """ Checks wether this set and the w_other are completly different, i.e. have no equal elements. W_other must be a set."""
+ return self.strategy.isdisjoint(self, w_other)
+
+ def update(self, w_other):
+ """ Appends all elements from the given set to this set. W_other must be a set."""
+ self.strategy.update(self, w_other)
+
+ def has_key(self, w_key):
+ """ Checks wether this set contains the given wrapped key."""
+ return self.strategy.has_key(self, w_key)
+
+ def equals(self, w_other):
+ """ Checks wether this set and the given set are equal, i.e. contain the same elements. W_other must be a set."""
+ return self.strategy.equals(self, w_other)
+
+ def iter(self):
+ """ Returns an iterator of the elements from this set. """
+ return self.strategy.iter(self)
+
+ def popitem(self):
+ """ Removes an arbitrary element from the set. May raise KeyError if set is empty."""
+ return self.strategy.popitem(self)
+
class W_SetObject(W_BaseSetObject):
from pypy.objspace.std.settype import set_typedef as typedef
- def _newobj(w_self, space, rdict_w):
- """Make a new set by taking ownership of 'rdict_w'."""
+ def _newobj(w_self, space, w_iterable):
+ """Make a new set by taking ownership of 'w_iterable'."""
if type(w_self) is W_SetObject:
- return W_SetObject(space, rdict_w)
+ return W_SetObject(space, w_iterable)
w_type = space.type(w_self)
w_obj = space.allocate_instance(W_SetObject, w_type)
- W_SetObject.__init__(w_obj, space, rdict_w)
+ W_SetObject.__init__(w_obj, space, w_iterable)
return w_obj
class W_FrozensetObject(W_BaseSetObject):
from pypy.objspace.std.frozensettype import frozenset_typedef as typedef
hash = 0
- def _newobj(w_self, space, rdict_w):
- """Make a new frozenset by taking ownership of 'rdict_w'."""
+ def _newobj(w_self, space, w_iterable):
+ """Make a new frozenset by taking ownership of 'w_iterable'."""
if type(w_self) is W_FrozensetObject:
- return W_FrozensetObject(space, rdict_w)
+ return W_FrozensetObject(space, w_iterable)
w_type = space.type(w_self)
w_obj = space.allocate_instance(W_FrozensetObject, w_type)
- W_FrozensetObject.__init__(w_obj, space, rdict_w)
+ W_FrozensetObject.__init__(w_obj, space, w_iterable)
return w_obj
registerimplementation(W_BaseSetObject)
registerimplementation(W_SetObject)
registerimplementation(W_FrozensetObject)
-class W_SetIterObject(W_Object):
- from pypy.objspace.std.settype import setiter_typedef as typedef
+class SetStrategy(object):
+ def __init__(self, space):
+ self.space = space
- def __init__(w_self, setdata):
- w_self.content = content = setdata
- w_self.len = len(content)
- w_self.pos = 0
- w_self.iterator = w_self.content.iterkeys()
+ def get_empty_dict(self):
+ """ Returns an empty dictionary depending on the strategy. Used to initalize a new storage. """
+ raise NotImplementedError
- def next_entry(w_self):
- for w_key in w_self.iterator:
+ def get_empty_storage(self):
+ """ Returns an empty storage (erased) object. Used to initialize an empty set."""
+ raise NotImplementedError
+
+ def listview_str(self, w_set):
+ return None
+
+ def listview_int(self, w_set):
+ return None
+
+ #def erase(self, storage):
+ # raise NotImplementedError
+
+ #def unerase(self, storage):
+ # raise NotImplementedError
+
+ # __________________ methods called on W_SetObject _________________
+
+ def clear(self, w_set):
+ raise NotImplementedError
+
+ def copy_real(self, w_set):
+ raise NotImplementedError
+
+ def length(self, w_set):
+ raise NotImplementedError
+
+ def add(self, w_set, w_key):
+ raise NotImplementedError
+
+ def remove(self, w_set, w_item):
+ raise NotImplementedError
+
+ def getdict_w(self, w_set):
+ raise NotImplementedError
+
+ def get_storage_copy(self, w_set):
+ raise NotImplementedError
+
+ def getkeys(self, w_set):
+ raise NotImplementedError
+
+ def difference(self, w_set, w_other):
+ raise NotImplementedError
+
+ def difference_update(self, w_set, w_other):
+ raise NotImplementedError
+
+ def symmetric_difference(self, w_set, w_other):
+ raise NotImplementedError
+
+ def symmetric_difference_update(self, w_set, w_other):
+ raise NotImplementedError
+
+ def intersect(self, w_set, w_other):
+ raise NotImplementedError
+
+ def intersect_update(self, w_set, w_other):
+ raise NotImplementedError
+
+ def issubset(self, w_set, w_other):
+ raise NotImplementedError
+
+ def isdisjoint(self, w_set, w_other):
+ raise NotImplementedError
+
+ def update(self, w_set, w_other):
+ raise NotImplementedError
+
+ def has_key(self, w_set, w_key):
+ raise NotImplementedError
+
+ def equals(self, w_set, w_other):
+ raise NotImplementedError
+
+ def iter(self, w_set):
+ raise NotImplementedError
+
+ def popitem(self, w_set):
+ raise NotImplementedError
+
+class EmptySetStrategy(SetStrategy):
+
+ erase, unerase = rerased.new_erasing_pair("empty")
+ erase = staticmethod(erase)
+ unerase = staticmethod(unerase)
+
+ def get_empty_storage(self):
+ return self.erase(None)
+
+ def is_correct_type(self, w_key):
+ return False
+
+ def length(self, w_set):
+ return 0
+
+ def clear(self, w_set):
+ pass
+
+ def copy_real(self, w_set):
+ storage = self.erase(None)
+ clone = w_set.from_storage_and_strategy(storage, self)
+ return clone
+
+ def add(self, w_set, w_key):
+ if type(w_key) is W_IntObject:
+ strategy = self.space.fromcache(IntegerSetStrategy)
+ elif type(w_key) is W_StringObject:
+ strategy = self.space.fromcache(StringSetStrategy)
+ else:
+ strategy = self.space.fromcache(ObjectSetStrategy)
+ w_set.strategy = strategy
+ w_set.sstorage = strategy.get_empty_storage()
+ w_set.add(w_key)
+
+ def remove(self, w_set, w_item):
+ return False
+
+ def getdict_w(self, w_set):
+ return newset(self.space)
+
+ def get_storage_copy(self, w_set):
+ return w_set.sstorage
+
+ def getkeys(self, w_set):
+ return []
+
+ def has_key(self, w_set, w_key):
+ return False
+
+ def equals(self, w_set, w_other):
+ if w_other.strategy is self or w_other.length() == 0:
+ return True
+ return False
+
+ def difference(self, w_set, w_other):
+ return w_set.copy_real()
+
+ def difference_update(self, w_set, w_other):
+ pass
+
+ def intersect(self, w_set, w_other):
+ return w_set.copy_real()
+
+ def intersect_update(self, w_set, w_other):
+ pass
+
+ def isdisjoint(self, w_set, w_other):
+ return True
+
+ def issubset(self, w_set, w_other):
+ return True
+
+ def symmetric_difference(self, w_set, w_other):
+ return w_other.copy_real()
+
+ def symmetric_difference_update(self, w_set, w_other):
+ w_set.strategy = w_other.strategy
+ w_set.sstorage = w_other.get_storage_copy()
+
+ def update(self, w_set, w_other):
+ w_set.strategy = w_other.strategy
+ w_set.sstorage = w_other.get_storage_copy()
+
+ def iter(self, w_set):
+ return EmptyIteratorImplementation(self.space, w_set)
+
+ def popitem(self, w_set):
+ raise OperationError(self.space.w_KeyError,
+ self.space.wrap('pop from an empty set'))
+
+class AbstractUnwrappedSetStrategy(object):
+ _mixin_ = True
+
+ def is_correct_type(self, w_key):
+ """ Checks wether the given wrapped key fits this strategy."""
+ raise NotImplementedError
+
+ def unwrap(self, w_item):
+ """ Returns the unwrapped value of the given wrapped item."""
+ raise NotImplementedError
+
+ def wrap(self, item):
+ """ Returns a wrapped version of the given unwrapped item. """
+ raise NotImplementedError
+
+ def get_storage_from_list(self, list_w):
+ setdata = self.get_empty_dict()
+ for w_item in list_w:
+ setdata[self.unwrap(w_item)] = None
+ return self.erase(setdata)
+
+ def get_storage_from_unwrapped_list(self, items):
+ setdata = self.get_empty_dict()
+ for item in items:
+ setdata[item] = None
+ return self.erase(setdata)
+
+ def length(self, w_set):
+ return len(self.unerase(w_set.sstorage))
+
+ def clear(self, w_set):
+ w_set.switch_to_empty_strategy()
+
+ def copy_real(self, w_set):
+ # may be used internally on frozen sets, although frozenset().copy()
+ # returns self in frozenset_copy__Frozenset.
+ strategy = w_set.strategy
+ d = self.unerase(w_set.sstorage)
+ storage = self.erase(d.copy())
+ clone = w_set.from_storage_and_strategy(storage, strategy)
+ return clone
+
+ def add(self, w_set, w_key):
+ if self.is_correct_type(w_key):
+ d = self.unerase(w_set.sstorage)
+ d[self.unwrap(w_key)] = None
+ else:
+ w_set.switch_to_object_strategy(self.space)
+ w_set.add(w_key)
+
+ def remove(self, w_set, w_item):
+ from pypy.objspace.std.dictmultiobject import _never_equal_to_string
+ d = self.unerase(w_set.sstorage)
+ if not self.is_correct_type(w_item):
+ #XXX check type of w_item and immediately return False in some cases
+ w_set.switch_to_object_strategy(self.space)
+ return w_set.remove(w_item)
+
+ key = self.unwrap(w_item)
+ try:
+ del d[key]
+ return True
+ except KeyError:
+ return False
+
+ def getdict_w(self, w_set):
+ result = newset(self.space)
+ keys = self.unerase(w_set.sstorage).keys()
+ for key in keys:
+ result[self.wrap(key)] = None
+ return result
+
+ def get_storage_copy(self, w_set):
+ d = self.unerase(w_set.sstorage)
+ copy = self.erase(d.copy())
+ return copy
+
+ def getkeys(self, w_set):
+ keys = self.unerase(w_set.sstorage).keys()
+ keys_w = [self.wrap(key) for key in keys]
+ return keys_w
+
+ def has_key(self, w_set, w_key):
+ from pypy.objspace.std.dictmultiobject import _never_equal_to_string
+ if not self.is_correct_type(w_key):
+ #XXX check type of w_item and immediately return False in some cases
+ w_set.switch_to_object_strategy(self.space)
+ return w_set.has_key(w_key)
+ d = self.unerase(w_set.sstorage)
+ return self.unwrap(w_key) in d
+
+ def equals(self, w_set, w_other):
+ if w_set.length() != w_other.length():
+ return False
+ items = self.unerase(w_set.sstorage).keys()
+ for key in items:
+ if not w_other.has_key(self.wrap(key)):
+ return False
+ return True
+
+ def _difference_wrapped(self, w_set, w_other):
+ strategy = self.space.fromcache(ObjectSetStrategy)
+
+ d_new = strategy.get_empty_dict()
+ for obj in self.unerase(w_set.sstorage):
+ w_item = self.wrap(obj)
+ if not w_other.has_key(w_item):
+ d_new[w_item] = None
+
+ return strategy.erase(d_new)
+
+ def _difference_unwrapped(self, w_set, w_other):
+ iterator = self.unerase(w_set.sstorage).iterkeys()
+ other_dict = self.unerase(w_other.sstorage)
+ result_dict = self.get_empty_dict()
+ for key in iterator:
+ if key not in other_dict:
+ result_dict[key] = None
+ return self.erase(result_dict)
+
+ def _difference_base(self, w_set, w_other):
+ if self is w_other.strategy:
+ strategy = w_set.strategy
+ storage = self._difference_unwrapped(w_set, w_other)
+ elif not w_set.strategy.may_contain_equal_elements(w_other.strategy):
+ strategy = w_set.strategy
+ storage = w_set.sstorage
+ else:
+ strategy = self.space.fromcache(ObjectSetStrategy)
+ storage = self._difference_wrapped(w_set, w_other)
+ return storage, strategy
+
+ def difference(self, w_set, w_other):
+ storage, strategy = self._difference_base(w_set, w_other)
+ w_newset = w_set.from_storage_and_strategy(storage, strategy)
+ return w_newset
+
+ def difference_update(self, w_set, w_other):
+ storage, strategy = self._difference_base(w_set, w_other)
+ w_set.strategy = strategy
+ w_set.sstorage = storage
+
+ def _symmetric_difference_unwrapped(self, w_set, w_other):
+ d_new = self.get_empty_dict()
+ d_this = self.unerase(w_set.sstorage)
+ d_other = self.unerase(w_other.sstorage)
+ for key in d_other.keys():
+ if not key in d_this:
+ d_new[key] = None
+ for key in d_this.keys():
+ if not key in d_other:
+ d_new[key] = None
+
+ storage = self.erase(d_new)
+ return storage
+
+ def _symmetric_difference_wrapped(self, w_set, w_other):
+ newsetdata = newset(self.space)
+ for obj in self.unerase(w_set.sstorage):
+ w_item = self.wrap(obj)
+ if not w_other.has_key(w_item):
+ newsetdata[w_item] = None
+
+ w_iterator = w_other.iter()
+ while True:
+ w_item = w_iterator.next_entry()
+ if w_item is None:
+ break
+ if not w_set.has_key(w_item):
+ newsetdata[w_item] = None
+
+ strategy = self.space.fromcache(ObjectSetStrategy)
+ return strategy.erase(newsetdata)
+
+ def _symmetric_difference_base(self, w_set, w_other):
+ if self is w_other.strategy:
+ strategy = w_set.strategy
+ storage = self._symmetric_difference_unwrapped(w_set, w_other)
+ else:
+ strategy = self.space.fromcache(ObjectSetStrategy)
+ storage = self._symmetric_difference_wrapped(w_set, w_other)
+ return storage, strategy
+
+ def symmetric_difference(self, w_set, w_other):
+ storage, strategy = self._symmetric_difference_base(w_set, w_other)
+ return w_set.from_storage_and_strategy(storage, strategy)
+
+ def symmetric_difference_update(self, w_set, w_other):
+ storage, strategy = self._symmetric_difference_base(w_set, w_other)
+ w_set.strategy = strategy
+ w_set.sstorage = storage
+
+ def _intersect_base(self, w_set, w_other):
+ if self is w_other.strategy:
+ strategy = w_set.strategy
+ storage = strategy._intersect_unwrapped(w_set, w_other)
+ elif not w_set.strategy.may_contain_equal_elements(w_other.strategy):
+ strategy = self.space.fromcache(EmptySetStrategy)
+ storage = strategy.get_empty_storage()
+ else:
+ strategy = self.space.fromcache(ObjectSetStrategy)
+ storage = self._intersect_wrapped(w_set, w_other)
+ return storage, strategy
+
+ def _intersect_wrapped(self, w_set, w_other):
+ result = newset(self.space)
+ for key in self.unerase(w_set.sstorage):
+ w_key = self.wrap(key)
+ if w_other.has_key(w_key):
+ result[w_key] = None
+
+ strategy = self.space.fromcache(ObjectSetStrategy)
+ return strategy.erase(result)
+
+ def _intersect_unwrapped(self, w_set, w_other):
+ result = self.get_empty_dict()
+ d_this = self.unerase(w_set.sstorage)
+ d_other = self.unerase(w_other.sstorage)
+ for key in d_this:
+ if key in d_other:
+ result[key] = None
+ return self.erase(result)
+
+ def intersect(self, w_set, w_other):
+ if w_set.length() > w_other.length():
+ return w_other.intersect(w_set)
+
+ storage, strategy = self._intersect_base(w_set, w_other)
+ return w_set.from_storage_and_strategy(storage, strategy)
+
+ def intersect_update(self, w_set, w_other):
+ if w_set.length() > w_other.length():
+ w_intersection = w_other.intersect(w_set)
+ strategy = w_intersection.strategy
+ storage = w_intersection.sstorage
+ else:
+ storage, strategy = self._intersect_base(w_set, w_other)
+ w_set.strategy = strategy
+ w_set.sstorage = storage
+
+ def _issubset_unwrapped(self, w_set, w_other):
+ d_other = self.unerase(w_other.sstorage)
+ for item in self.unerase(w_set.sstorage):
+ if not item in d_other:
+ return False
+ return True
+
+ def _issubset_wrapped(self, w_set, w_other):
+ for obj in self.unerase(w_set.sstorage):
+ w_item = self.wrap(obj)
+ if not w_other.has_key(w_item):
+ return False
+ return True
+
+ def issubset(self, w_set, w_other):
+ if w_set.length() == 0:
+ return True
+
+ if w_set.strategy is w_other.strategy:
+ return self._issubset_unwrapped(w_set, w_other)
+ elif not w_set.strategy.may_contain_equal_elements(w_other.strategy):
+ return False
+ else:
+ return self._issubset_wrapped(w_set, w_other)
+
+ def _isdisjoint_unwrapped(self, w_set, w_other):
+ d_set = self.unerase(w_set.sstorage)
+ d_other = self.unerase(w_other.sstorage)
+ for key in d_set:
+ if key in d_other:
+ return False
+ return True
+
+ def _isdisjoint_wrapped(self, w_set, w_other):
+ d = self.unerase(w_set.sstorage)
+ for key in d:
+ if w_other.has_key(self.wrap(key)):
+ return False
+ return True
+
+ def isdisjoint(self, w_set, w_other):
+ if w_other.length() == 0:
+ return True
+ if w_set.length() > w_other.length():
+ return w_other.isdisjoint(w_set)
+
+ if w_set.strategy is w_other.strategy:
+ return self._isdisjoint_unwrapped(w_set, w_other)
+ elif not w_set.strategy.may_contain_equal_elements(w_other.strategy):
+ return True
+ else:
+ return self._isdisjoint_wrapped(w_set, w_other)
+
+ def update(self, w_set, w_other):
+ if self is w_other.strategy:
+ d_set = self.unerase(w_set.sstorage)
+ d_other = self.unerase(w_other.sstorage)
+ d_set.update(d_other)
+ return
+
+ w_set.switch_to_object_strategy(self.space)
+ w_set.update(w_other)
+
+ def popitem(self, w_set):
+ storage = self.unerase(w_set.sstorage)
+ try:
+ # this returns a tuple because internally sets are dicts
+ result = storage.popitem()
+ except KeyError:
+ # strategy may still be the same even if dict is empty
+ raise OperationError(self.space.w_KeyError,
+ self.space.wrap('pop from an empty set'))
+ return self.wrap(result[0])
+
+class StringSetStrategy(AbstractUnwrappedSetStrategy, SetStrategy):
+ erase, unerase = rerased.new_erasing_pair("string")
+ erase = staticmethod(erase)
+ unerase = staticmethod(unerase)
+
+ def get_empty_storage(self):
+ return self.erase({})
+
+ def get_empty_dict(self):
+ return {}
+
+ def listview_str(self, w_set):
+ return self.unerase(w_set.sstorage).keys()
+
+ def is_correct_type(self, w_key):
+ return type(w_key) is W_StringObject
+
+ def may_contain_equal_elements(self, strategy):
+ if strategy is self.space.fromcache(IntegerSetStrategy):
+ return False
+ if strategy is self.space.fromcache(EmptySetStrategy):
+ return False
+ return True
+
+ def unwrap(self, w_item):
+ return self.space.str_w(w_item)
+
+ def wrap(self, item):
+ return self.space.wrap(item)
+
+ def iter(self, w_set):
+ return StringIteratorImplementation(self.space, self, w_set)
+
+class IntegerSetStrategy(AbstractUnwrappedSetStrategy, SetStrategy):
+ erase, unerase = rerased.new_erasing_pair("integer")
+ erase = staticmethod(erase)
+ unerase = staticmethod(unerase)
+
+ def get_empty_storage(self):
+ return self.erase({})
+
+ def get_empty_dict(self):
+ return {}
+
+ def listview_int(self, w_set):
+ return self.unerase(w_set.sstorage).keys()
+
+ def is_correct_type(self, w_key):
+ from pypy.objspace.std.intobject import W_IntObject
+ return type(w_key) is W_IntObject
+
+ def may_contain_equal_elements(self, strategy):
+ if strategy is self.space.fromcache(StringSetStrategy):
+ return False
+ if strategy is self.space.fromcache(EmptySetStrategy):
+ return False
+ return True
+
+ def unwrap(self, w_item):
+ return self.space.int_w(w_item)
+
+ def wrap(self, item):
+ return self.space.wrap(item)
+
+ def iter(self, w_set):
+ return IntegerIteratorImplementation(self.space, self, w_set)
+
+class ObjectSetStrategy(AbstractUnwrappedSetStrategy, SetStrategy):
+ erase, unerase = rerased.new_erasing_pair("object")
+ erase = staticmethod(erase)
+ unerase = staticmethod(unerase)
+
+ def get_empty_storage(self):
+ return self.erase(self.get_empty_dict())
+
+ def get_empty_dict(self):
+ return newset(self.space)
+
+ def is_correct_type(self, w_key):
+ return True
+
+ def may_contain_equal_elements(self, strategy):
+ if strategy is self.space.fromcache(EmptySetStrategy):
+ return False
+ return True
+
+ def unwrap(self, w_item):
+ return w_item
+
+ def wrap(self, item):
+ return item
+
+ def iter(self, w_set):
+ return RDictIteratorImplementation(self.space, self, w_set)
+
+ def update(self, w_set, w_other):
+ d_obj = self.unerase(w_set.sstorage)
+ w_iterator = w_other.iter()
+ while True:
+ w_item = w_iterator.next_entry()
+ if w_item is None:
+ break
+ d_obj[w_item] = None
+
+class IteratorImplementation(object):
+ def __init__(self, space, implementation):
+ self.space = space
+ self.setimplementation = implementation
+ self.len = implementation.length()
+ self.pos = 0
+
+ def next(self):
+ if self.setimplementation is None:
+ return None
+ if self.len != self.setimplementation.length():
+ self.len = -1 # Make this error state sticky
+ raise OperationError(self.space.w_RuntimeError,
+ self.space.wrap("set changed size during iteration"))
+ # look for the next entry
+ if self.pos < self.len:
+ result = self.next_entry()
+ self.pos += 1
+ return result
+ # no more entries
+ self.setimplementation = None
+ return None
+
+ def next_entry(self):
+ """ Purely abstract method
+ """
+ raise NotImplementedError
+
+ def length(self):
+ if self.setimplementation is not None:
+ return self.len - self.pos
+ return 0
+
+class EmptyIteratorImplementation(IteratorImplementation):
+ def next_entry(self):
+ return None
+
+
+class StringIteratorImplementation(IteratorImplementation):
+ def __init__(self, space, strategy, w_set):
+ IteratorImplementation.__init__(self, space, 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 IntegerIteratorImplementation(IteratorImplementation):
+ #XXX same implementation in dictmultiobject on dictstrategy-branch
+ def __init__(self, space, strategy, dictimplementation):
+ IteratorImplementation.__init__(self, space, dictimplementation)
+ d = strategy.unerase(dictimplementation.sstorage)
+ self.iterator = d.iterkeys()
+
+ def next_entry(self):
+ # note that this 'for' loop only runs once, at most
+ for key in self.iterator:
+ return self.space.wrap(key)
+ else:
+ return None
+
+class RDictIteratorImplementation(IteratorImplementation):
+ def __init__(self, space, strategy, dictimplementation):
+ IteratorImplementation.__init__(self, space, dictimplementation)
+ d = strategy.unerase(dictimplementation.sstorage)
+ self.iterator = d.iterkeys()
+
+ def next_entry(self):
+ # note that this 'for' loop only runs once, at most
+ for w_key in self.iterator:
return w_key
else:
return None
+class W_SetIterObject(W_Object):
+ from pypy.objspace.std.settype import setiter_typedef as typedef
+ # XXX this class should be killed, and the various
+ # iterimplementations should be W_Objects directly.
+
+ def __init__(w_self, space, iterimplementation):
+ w_self.space = space
+ w_self.iterimplementation = iterimplementation
+
registerimplementation(W_SetIterObject)
def iter__SetIterObject(space, w_setiter):
return w_setiter
def next__SetIterObject(space, w_setiter):
- content = w_setiter.content
- if content is not None:
- if w_setiter.len != len(content):
- w_setiter.len = -1 # Make this error state sticky
- raise OperationError(space.w_RuntimeError,
- space.wrap("Set changed size during iteration"))
- # look for the next entry
- w_result = w_setiter.next_entry()
- if w_result is not None:
- w_setiter.pos += 1
- return w_result
- # no more entries
- w_setiter.content = None
+ iterimplementation = w_setiter.iterimplementation
+ w_key = iterimplementation.next()
+ if w_key is not None:
+ return w_key
raise OperationError(space.w_StopIteration, space.w_None)
# XXX __length_hint__()
@@ -116,107 +893,91 @@
def newset(space):
return r_dict(space.eq_w, space.hash_w, force_non_null=True)
-def make_setdata_from_w_iterable(space, w_iterable=None):
- """Return a new r_dict with the content of w_iterable."""
+def set_strategy_and_setdata(space, w_set, w_iterable):
+ from pypy.objspace.std.intobject import W_IntObject
+ if w_iterable is None :
+ w_set.strategy = strategy = space.fromcache(EmptySetStrategy)
+ w_set.sstorage = strategy.get_empty_storage()
+ return
+
if isinstance(w_iterable, W_BaseSetObject):
- return w_iterable.setdata.copy()
- data = newset(space)
- if w_iterable is not None:
- for w_item in space.listview(w_iterable):
- data[w_item] = None
- return data
+ w_set.strategy = w_iterable.strategy
+ w_set.sstorage = w_iterable.get_storage_copy()
+ return
+
+ stringlist = space.listview_str(w_iterable)
+ if stringlist is not None:
+ strategy = space.fromcache(StringSetStrategy)
+ w_set.strategy = strategy
+ w_set.sstorage = strategy.get_storage_from_unwrapped_list(stringlist)
+ return
+
+ intlist = space.listview_int(w_iterable)
+ if intlist is not None:
+ strategy = space.fromcache(IntegerSetStrategy)
+ w_set.strategy = strategy
+ w_set.sstorage = strategy.get_storage_from_unwrapped_list(intlist)
+ return
+
+ iterable_w = space.listview(w_iterable)
+
+ if len(iterable_w) == 0:
+ w_set.strategy = strategy = space.fromcache(EmptySetStrategy)
+ w_set.sstorage = strategy.get_empty_storage()
+ return
+
+ _pick_correct_strategy(space, w_set, iterable_w)
+
+def _pick_correct_strategy(space, w_set, iterable_w):
+ # check for integers
+ for w_item in iterable_w:
+ if type(w_item) is not W_IntObject:
+ break
+ else:
+ w_set.strategy = space.fromcache(IntegerSetStrategy)
+ w_set.sstorage = w_set.strategy.get_storage_from_list(iterable_w)
+ return
+
+ # check for strings
+ for w_item in iterable_w:
+ if type(w_item) is not W_StringObject:
+ break
+ else:
+ w_set.strategy = space.fromcache(StringSetStrategy)
+ 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)
def _initialize_set(space, w_obj, w_iterable=None):
- w_obj.setdata.clear()
- if w_iterable is not None:
- w_obj.setdata = make_setdata_from_w_iterable(space, w_iterable)
+ w_obj.clear()
+ set_strategy_and_setdata(space, w_obj, w_iterable)
def _convert_set_to_frozenset(space, w_obj):
- if space.isinstance_w(w_obj, space.w_set):
- return W_FrozensetObject(space,
- make_setdata_from_w_iterable(space, w_obj))
+ if isinstance(w_obj, W_SetObject):
+ w_frozen = W_FrozensetObject(space, None)
+ w_frozen.strategy = w_obj.strategy
+ w_frozen.sstorage = w_obj.sstorage
+ return w_frozen
+ elif space.isinstance_w(w_obj, space.w_set):
+ w_frz = space.allocate_instance(W_FrozensetObject, space.w_frozenset)
+ W_FrozensetObject.__init__(w_frz, space, w_obj)
+ return w_frz
else:
return None
-# helper functions for set operation on dicts
-
-def _is_eq(ld, rd):
- if len(ld) != len(rd):
- return False
- for w_key in ld:
- if w_key not in rd:
- return False
- return True
-
-def _difference_dict(space, ld, rd):
- result = newset(space)
- for w_key in ld:
- if w_key not in rd:
- result[w_key] = None
- return result
-
-def _difference_dict_update(space, ld, rd):
- if ld is rd:
- ld.clear() # for the case 'a.difference_update(a)'
- else:
- for w_key in rd:
- try:
- del ld[w_key]
- except KeyError:
- pass
-
-def _intersection_dict(space, ld, rd):
- result = newset(space)
- if len(ld) > len(rd):
- ld, rd = rd, ld # loop over the smaller dict
- for w_key in ld:
- if w_key in rd:
- result[w_key] = None
- return result
-
-def _isdisjoint_dict(ld, rd):
- if len(ld) > len(rd):
- ld, rd = rd, ld # loop over the smaller dict
- for w_key in ld:
- if w_key in rd:
- return False
- return True
-
-def _symmetric_difference_dict(space, ld, rd):
- result = newset(space)
- for w_key in ld:
- if w_key not in rd:
- result[w_key] = None
- for w_key in rd:
- if w_key not in ld:
- result[w_key] = None
- return result
-
-def _issubset_dict(ldict, rdict):
- if len(ldict) > len(rdict):
- return False
-
- for w_key in ldict:
- if w_key not in rdict:
- return False
- return True
-
-
-#end helper functions
-
def set_update__Set(space, w_left, others_w):
"""Update a set with the union of itself and another."""
- ld = w_left.setdata
for w_other in others_w:
if isinstance(w_other, W_BaseSetObject):
- ld.update(w_other.setdata) # optimization only
+ w_left.update(w_other) # optimization only
else:
for w_key in space.listview(w_other):
- ld[w_key] = None
+ w_left.add(w_key)
def inplace_or__Set_Set(space, w_left, w_other):
- ld, rd = w_left.setdata, w_other.setdata
- ld.update(rd)
+ w_left.update(w_other)
return w_left
inplace_or__Set_Frozenset = inplace_or__Set_Set
@@ -226,10 +987,10 @@
This has no effect if the element is already present.
"""
- w_left.setdata[w_other] = None
+ w_left.add(w_other)
def set_copy__Set(space, w_set):
- return w_set._newobj(space, w_set.setdata.copy())
+ return w_set.copy_real()
def frozenset_copy__Frozenset(space, w_left):
if type(w_left) is W_FrozensetObject:
@@ -238,63 +999,51 @@
return set_copy__Set(space, w_left)
def set_clear__Set(space, w_left):
- w_left.setdata.clear()
+ w_left.clear()
def sub__Set_Set(space, w_left, w_other):
- ld, rd = w_left.setdata, w_other.setdata
- new_ld = _difference_dict(space, ld, rd)
- return w_left._newobj(space, new_ld)
+ return w_left.difference(w_other)
sub__Set_Frozenset = sub__Set_Set
sub__Frozenset_Set = sub__Set_Set
sub__Frozenset_Frozenset = sub__Set_Set
def set_difference__Set(space, w_left, others_w):
- result = w_left.setdata
- if len(others_w) == 0:
- result = result.copy()
- for w_other in others_w:
- if isinstance(w_other, W_BaseSetObject):
- rd = w_other.setdata # optimization only
- else:
- rd = make_setdata_from_w_iterable(space, w_other)
- result = _difference_dict(space, result, rd)
- return w_left._newobj(space, result)
+ result = w_left.copy_real()
+ set_difference_update__Set(space, result, others_w)
+ return result
frozenset_difference__Frozenset = set_difference__Set
def set_difference_update__Set(space, w_left, others_w):
- ld = w_left.setdata
for w_other in others_w:
if isinstance(w_other, W_BaseSetObject):
# optimization only
- _difference_dict_update(space, ld, w_other.setdata)
+ w_left.difference_update(w_other)
else:
- for w_key in space.listview(w_other):
- try:
- del ld[w_key]
- except KeyError:
- pass
+ w_other_as_set = w_left._newobj(space, w_other)
+ w_left.difference_update(w_other_as_set)
def inplace_sub__Set_Set(space, w_left, w_other):
- ld, rd = w_left.setdata, w_other.setdata
- _difference_dict_update(space, ld, rd)
+ w_left.difference_update(w_other)
return w_left
inplace_sub__Set_Frozenset = inplace_sub__Set_Set
def eq__Set_Set(space, w_left, w_other):
# optimization only (the general case is eq__Set_settypedef)
- return space.wrap(_is_eq(w_left.setdata, w_other.setdata))
+ return space.wrap(w_left.equals(w_other))
eq__Set_Frozenset = eq__Set_Set
eq__Frozenset_Frozenset = eq__Set_Set
eq__Frozenset_Set = eq__Set_Set
def eq__Set_settypedef(space, w_left, w_other):
- rd = make_setdata_from_w_iterable(space, w_other)
- return space.wrap(_is_eq(w_left.setdata, rd))
+ # tested in test_buildinshortcut.py
+ #XXX do not make new setobject here
+ w_other_as_set = w_left._newobj(space, w_other)
+ return space.wrap(w_left.equals(w_other_as_set))
eq__Set_frozensettypedef = eq__Set_settypedef
eq__Frozenset_settypedef = eq__Set_settypedef
@@ -308,15 +1057,16 @@
eq__Frozenset_ANY = eq__Set_ANY
def ne__Set_Set(space, w_left, w_other):
- return space.wrap(not _is_eq(w_left.setdata, w_other.setdata))
+ return space.wrap(not w_left.equals(w_other))
ne__Set_Frozenset = ne__Set_Set
ne__Frozenset_Frozenset = ne__Set_Set
ne__Frozenset_Set = ne__Set_Set
def ne__Set_settypedef(space, w_left, w_other):
- rd = make_setdata_from_w_iterable(space, w_other)
- return space.wrap(not _is_eq(w_left.setdata, rd))
+ #XXX this is not tested
+ w_other_as_set = w_left._newobj(space, w_other)
+ return space.wrap(not w_left.equals(w_other_as_set))
ne__Set_frozensettypedef = ne__Set_settypedef
ne__Frozenset_settypedef = ne__Set_settypedef
@@ -331,12 +1081,12 @@
def contains__Set_ANY(space, w_left, w_other):
try:
- return space.newbool(w_other in w_left.setdata)
+ return space.newbool(w_left.has_key(w_other))
except OperationError, e:
if e.match(space, space.w_TypeError):
w_f = _convert_set_to_frozenset(space, w_other)
if w_f is not None:
- return space.newbool(w_f in w_left.setdata)
+ return space.newbool(w_left.has_key(w_f))
raise
contains__Frozenset_ANY = contains__Set_ANY
@@ -345,19 +1095,23 @@
# optimization only (the general case works too)
if space.is_w(w_left, w_other):
return space.w_True
- ld, rd = w_left.setdata, w_other.setdata
- return space.wrap(_issubset_dict(ld, rd))
+ if w_left.length() > w_other.length():
+ return space.w_False
+ return space.wrap(w_left.issubset(w_other))
set_issubset__Set_Frozenset = set_issubset__Set_Set
frozenset_issubset__Frozenset_Set = set_issubset__Set_Set
frozenset_issubset__Frozenset_Frozenset = set_issubset__Set_Set
def set_issubset__Set_ANY(space, w_left, w_other):
- if space.is_w(w_left, w_other):
- return space.w_True
+ # not checking whether w_left is w_other here, because if that were the
+ # case the more precise multimethod would have applied.
- ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
- return space.wrap(_issubset_dict(ld, rd))
+ w_other_as_set = w_left._newobj(space, w_other)
+
+ if w_left.length() > w_other_as_set.length():
+ return space.w_False
+ return space.wrap(w_left.issubset(w_other_as_set))
frozenset_issubset__Frozenset_ANY = set_issubset__Set_ANY
@@ -370,9 +1124,9 @@
# optimization only (the general case works too)
if space.is_w(w_left, w_other):
return space.w_True
-
- ld, rd = w_left.setdata, w_other.setdata
- return space.wrap(_issubset_dict(rd, ld))
+ if w_left.length() < w_other.length():
+ return space.w_False
+ return space.wrap(w_other.issubset(w_left))
set_issuperset__Set_Frozenset = set_issuperset__Set_Set
set_issuperset__Frozenset_Set = set_issuperset__Set_Set
@@ -382,8 +1136,11 @@
if space.is_w(w_left, w_other):
return space.w_True
- ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
- return space.wrap(_issubset_dict(rd, ld))
+ w_other_as_set = w_left._newobj(space, w_other)
+
+ if w_left.length() < w_other_as_set.length():
+ return space.w_False
+ return space.wrap(w_other_as_set.issubset(w_left))
frozenset_issuperset__Frozenset_ANY = set_issuperset__Set_ANY
@@ -395,7 +1152,7 @@
# automatic registration of "lt(x, y)" as "not ge(y, x)" would not give the
# correct answer here!
def lt__Set_Set(space, w_left, w_other):
- if len(w_left.setdata) >= len(w_other.setdata):
+ if w_left.length() >= w_other.length():
return space.w_False
else:
return le__Set_Set(space, w_left, w_other)
@@ -405,7 +1162,7 @@
lt__Frozenset_Frozenset = lt__Set_Set
def gt__Set_Set(space, w_left, w_other):
- if len(w_left.setdata) <= len(w_other.setdata):
+ if w_left.length() <= w_other.length():
return space.w_False
else:
return ge__Set_Set(space, w_left, w_other)
@@ -421,26 +1178,19 @@
Returns True if successfully removed.
"""
try:
- del w_left.setdata[w_item]
- return True
- except KeyError:
- return False
+ deleted = w_left.remove(w_item)
except OperationError, e:
if not e.match(space, space.w_TypeError):
raise
- w_f = _convert_set_to_frozenset(space, w_item)
- if w_f is None:
- raise
+ else:
+ w_f = _convert_set_to_frozenset(space, w_item)
+ if w_f is None:
+ raise
+ deleted = w_left.remove(w_f)
- try:
- del w_left.setdata[w_f]
- return True
- except KeyError:
- return False
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- return False
+ if w_left.length() == 0:
+ w_left.switch_to_empty_strategy()
+ return deleted
def set_discard__Set_ANY(space, w_left, w_item):
_discard_from_set(space, w_left, w_item)
@@ -454,8 +1204,12 @@
if w_set.hash != 0:
return space.wrap(w_set.hash)
hash = r_uint(1927868237)
- hash *= r_uint(len(w_set.setdata) + 1)
- for w_item in w_set.setdata:
+ hash *= r_uint(w_set.length() + 1)
+ w_iterator = w_set.iter()
+ while True:
+ w_item = w_iterator.next_entry()
+ if w_item is None:
+ break
h = space.hash_w(w_item)
value = (r_uint(h ^ (h << 16) ^ 89869747) * multi)
hash = hash ^ value
@@ -468,71 +1222,75 @@
return space.wrap(hash)
def set_pop__Set(space, w_left):
- try:
- w_key, _ = w_left.setdata.popitem()
- except KeyError:
- raise OperationError(space.w_KeyError,
- space.wrap('pop from an empty set'))
- return w_key
+ return w_left.popitem()
def and__Set_Set(space, w_left, w_other):
- ld, rd = w_left.setdata, w_other.setdata
- new_ld = _intersection_dict(space, ld, rd)
- return w_left._newobj(space, new_ld)
+ new_set = w_left.intersect(w_other)
+ return new_set
and__Set_Frozenset = and__Set_Set
and__Frozenset_Set = and__Set_Set
and__Frozenset_Frozenset = and__Set_Set
-def _intersection_multiple(space, w_left, others_w):
- result = w_left.setdata
- for w_other in others_w:
+def set_intersection__Set(space, w_left, others_w):
+ #XXX find smarter implementations
+ others_w = [w_left] + others_w
+
+ # find smallest set in others_w to reduce comparisons
+ startindex, startlength = 0, -1
+ for i in range(len(others_w)):
+ w_other = others_w[i]
+ try:
+ length = space.int_w(space.len(w_other))
+ except OperationError, e:
+ if (e.match(space, space.w_TypeError) or
+ e.match(space, space.w_AttributeError)):
+ continue
+ raise
+
+ if startlength == -1 or length < startlength:
+ startindex = i
+ startlength = length
+
+ others_w[startindex], others_w[0] = others_w[0], others_w[startindex]
+
+ result = w_left._newobj(space, others_w[0])
+ for i in range(1,len(others_w)):
+ w_other = others_w[i]
if isinstance(w_other, W_BaseSetObject):
# optimization only
- result = _intersection_dict(space, result, w_other.setdata)
+ result.intersect_update(w_other)
else:
- result2 = newset(space)
- for w_key in space.listview(w_other):
- if w_key in result:
- result2[w_key] = None
- result = result2
+ w_other_as_set = w_left._newobj(space, w_other)
+ result.intersect_update(w_other_as_set)
return result
-def set_intersection__Set(space, w_left, others_w):
- if len(others_w) == 0:
- result = w_left.setdata.copy()
- else:
- result = _intersection_multiple(space, w_left, others_w)
- return w_left._newobj(space, result)
-
frozenset_intersection__Frozenset = set_intersection__Set
def set_intersection_update__Set(space, w_left, others_w):
- result = _intersection_multiple(space, w_left, others_w)
- w_left.setdata = result
+ result = set_intersection__Set(space, w_left, others_w)
+ w_left.strategy = result.strategy
+ w_left.sstorage = result.sstorage
+ return
def inplace_and__Set_Set(space, w_left, w_other):
- ld, rd = w_left.setdata, w_other.setdata
- new_ld = _intersection_dict(space, ld, rd)
- w_left.setdata = new_ld
+ w_left.intersect_update(w_other)
return w_left
inplace_and__Set_Frozenset = inplace_and__Set_Set
def set_isdisjoint__Set_Set(space, w_left, w_other):
# optimization only (the general case works too)
- ld, rd = w_left.setdata, w_other.setdata
- disjoint = _isdisjoint_dict(ld, rd)
- return space.newbool(disjoint)
+ return space.newbool(w_left.isdisjoint(w_other))
set_isdisjoint__Set_Frozenset = set_isdisjoint__Set_Set
set_isdisjoint__Frozenset_Frozenset = set_isdisjoint__Set_Set
set_isdisjoint__Frozenset_Set = set_isdisjoint__Set_Set
def set_isdisjoint__Set_ANY(space, w_left, w_other):
- ld = w_left.setdata
+ #XXX may be optimized when other strategies are added
for w_key in space.listview(w_other):
- if w_key in ld:
+ if w_left.has_key(w_key):
return space.w_False
return space.w_True
@@ -540,9 +1298,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
@@ -556,26 +1313,23 @@
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)
+ w_other_as_set = w_left._newobj(space, w_other)
+ 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
+ w_other_as_set = w_left._newobj(space, w_other)
+ 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)
@@ -584,34 +1338,33 @@
inplace_xor__Set_Frozenset = inplace_xor__Set_Set
def or__Set_Set(space, w_left, w_other):
- ld, rd = w_left.setdata, w_other.setdata
- result = ld.copy()
- result.update(rd)
- return w_left._newobj(space, result)
+ w_copy = w_left.copy_real()
+ w_copy.update(w_other)
+ return w_copy
or__Set_Frozenset = or__Set_Set
or__Frozenset_Set = or__Set_Set
or__Frozenset_Frozenset = or__Set_Set
def set_union__Set(space, w_left, others_w):
- result = w_left.setdata.copy()
+ result = w_left.copy_real()
for w_other in others_w:
if isinstance(w_other, W_BaseSetObject):
- result.update(w_other.setdata) # optimization only
+ result.update(w_other) # optimization only
else:
for w_key in space.listview(w_other):
- result[w_key] = None
- return w_left._newobj(space, result)
+ result.add(w_key)
+ return result
frozenset_union__Frozenset = set_union__Set
def len__Set(space, w_left):
- return space.newint(len(w_left.setdata))
+ return space.newint(w_left.length())
len__Frozenset = len__Set
def iter__Set(space, w_left):
- return W_SetIterObject(w_left.setdata)
+ return W_SetIterObject(space, w_left.iter())
iter__Frozenset = iter__Set
diff --git a/pypy/objspace/std/settype.py b/pypy/objspace/std/settype.py
--- a/pypy/objspace/std/settype.py
+++ b/pypy/objspace/std/settype.py
@@ -68,7 +68,7 @@
def descr__new__(space, w_settype, __args__):
from pypy.objspace.std.setobject import W_SetObject, newset
w_obj = space.allocate_instance(W_SetObject, w_settype)
- W_SetObject.__init__(w_obj, space, newset(space))
+ W_SetObject.__init__(w_obj, space)
return w_obj
set_typedef = StdTypeDef("set",
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -69,6 +69,14 @@
def str_w(w_self, space):
return w_self._value
+ def listview_str(w_self):
+ return _create_list_from_string(w_self._value)
+
+def _create_list_from_string(value):
+ # need this helper function to allow the jit to look inside and inline
+ # listview_str
+ return [s for s in value]
+
registerimplementation(W_StringObject)
W_StringObject.EMPTY = W_StringObject('')
diff --git a/pypy/objspace/std/test/test_builtinshortcut.py b/pypy/objspace/std/test/test_builtinshortcut.py
--- a/pypy/objspace/std/test/test_builtinshortcut.py
+++ b/pypy/objspace/std/test/test_builtinshortcut.py
@@ -85,6 +85,20 @@
def setup_class(cls):
from pypy import conftest
cls.space = conftest.gettestobjspace(**WITH_BUILTINSHORTCUT)
+ w_fakeint = cls.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
+ """)
+ cls.w_FakeInt = w_fakeint
class AppTestString(test_stringobject.AppTestStringObject):
def setup_class(cls):
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -131,6 +131,45 @@
assert self.space.eq_w(space.call_function(get, w("33")), w(None))
assert self.space.eq_w(space.call_function(get, w("33"), w(44)), w(44))
+ def test_fromkeys_fastpath(self):
+ space = self.space
+ w = space.wrap
+
+ w_l = self.space.newlist([w("a"),w("b")])
+ w_l.getitems = None
+ w_d = space.call_method(space.w_dict, "fromkeys", w_l)
+
+ assert space.eq_w(w_d.getitem_str("a"), space.w_None)
+ assert space.eq_w(w_d.getitem_str("b"), space.w_None)
+
+ def test_listview_str_dict(self):
+ w = self.space.wrap
+
+ w_d = self.space.newdict()
+ w_d.initialize_content([(w("a"), w(1)), (w("b"), w(2))])
+
+ assert self.space.listview_str(w_d) == ["a", "b"]
+
+ def test_listview_int_dict(self):
+ w = self.space.wrap
+ w_d = self.space.newdict()
+ w_d.initialize_content([(w(1), w("a")), (w(2), w("b"))])
+
+ assert self.space.listview_int(w_d) == [1, 2]
+
+ def test_keys_on_string_int_dict(self):
+ w = self.space.wrap
+ w_d = self.space.newdict()
+ w_d.initialize_content([(w(1), w("a")), (w(2), w("b"))])
+
+ w_l = self.space.call_method(w_d, "keys")
+ assert sorted(self.space.listview_int(w_l)) == [1,2]
+
+ w_d = self.space.newdict()
+ w_d.initialize_content([(w("a"), w(1)), (w("b"), w(6))])
+
+ w_l = self.space.call_method(w_d, "keys")
+ assert sorted(self.space.listview_str(w_l)) == ["a", "b"]
class AppTest_DictObject:
def setup_class(cls):
@@ -793,7 +832,9 @@
return x == y
eq_w = eq
def newlist(self, l):
- return []
+ return l
+ def newlist_str(self, l):
+ return l
DictObjectCls = W_DictMultiObject
def type(self, w_obj):
if isinstance(w_obj, FakeString):
@@ -933,7 +974,7 @@
def test_keys(self):
self.fill_impl()
- keys = self.impl.keys()
+ keys = self.impl.w_keys() # wrapped lists = lists in the fake space
keys.sort()
assert keys == [self.string, self.string2]
self.check_not_devolved()
@@ -1011,8 +1052,8 @@
d.setitem("s", 12)
d.delitem(F())
- assert "s" not in d.keys()
- assert F() not in d.keys()
+ assert "s" not in d.w_keys()
+ assert F() not in d.w_keys()
class TestStrDictImplementation(BaseTestRDictImplementation):
StrategyClass = StringDictStrategy
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
@@ -486,6 +486,14 @@
list.__init__(l, ['a', 'b', 'c'])
assert l is l0
assert l == ['a', 'b', 'c']
+ list.__init__(l)
+ assert l == []
+
+ def test_explicit_new_init_more_cases(self):
+ for assignment in [[], (), [3], ["foo"]]:
+ l = [1, 2]
+ l.__init__(assignment)
+ assert l == list(assignment)
def test_extend_list(self):
l = l0 = [1]
@@ -1173,6 +1181,20 @@
assert l == []
assert list(g) == []
+ def test_uses_custom_iterator(self):
+ # obscure corner case: space.listview*() must not shortcut subclasses
+ # of dicts, because the OrderedDict in the stdlib relies on this.
+ # we extend the use case to lists and sets, i.e. all types that have
+ # strategies, to avoid surprizes depending on the strategy.
+ for base, arg in [(list, []), (list, [5]), (list, ['x']),
+ (set, []), (set, [5]), (set, ['x']),
+ (dict, []), (dict, [(5,6)]), (dict, [('x',7)])]:
+ print base, arg
+ class SubClass(base):
+ def __iter__(self):
+ return iter("foobar")
+ assert list(SubClass(arg)) == ['f', 'o', 'o', 'b', 'a', 'r']
+
class AppTestForRangeLists(AppTestW_ListObject):
def setup_class(cls):
diff --git a/pypy/objspace/std/test/test_liststrategies.py b/pypy/objspace/std/test/test_liststrategies.py
--- a/pypy/objspace/std/test/test_liststrategies.py
+++ b/pypy/objspace/std/test/test_liststrategies.py
@@ -420,7 +420,7 @@
def test_listview_str(self):
space = self.space
- assert space.listview_str(space.wrap("a")) is None
+ assert space.listview_str(space.wrap(1)) == None
w_l = self.space.newlist([self.space.wrap('a'), self.space.wrap('b')])
assert space.listview_str(w_l) == ["a", "b"]
@@ -463,6 +463,44 @@
w_res = listobject.list_pop__List_ANY(space, w_l, space.w_None) # does not crash
assert space.unwrap(w_res) == 3
+ def test_create_list_from_set(self):
+ from pypy.objspace.std.setobject import W_SetObject
+ from pypy.objspace.std.setobject import _initialize_set
+
+ space = self.space
+ w = space.wrap
+
+ w_l = W_ListObject(space, [space.wrap(1), space.wrap(2), space.wrap(3)])
+
+ w_set = W_SetObject(self.space)
+ _initialize_set(self.space, w_set, w_l)
+ w_set.iter = None # make sure fast path is used
+
+ w_l2 = W_ListObject(space, [])
+ space.call_method(w_l2, "__init__", w_set)
+
+ w_l2.sort(False)
+ assert space.eq_w(w_l, w_l2)
+
+ w_l = W_ListObject(space, [space.wrap("a"), space.wrap("b"), space.wrap("c")])
+ _initialize_set(self.space, w_set, w_l)
+
+ space.call_method(w_l2, "__init__", w_set)
+
+ w_l2.sort(False)
+ assert space.eq_w(w_l, w_l2)
+
+
+ def test_listview_str_list(self):
+ space = self.space
+ w_l = W_ListObject(space, [space.wrap("a"), space.wrap("b")])
+ assert self.space.listview_str(w_l) == ["a", "b"]
+
+ def test_listview_int_list(self):
+ space = self.space
+ w_l = W_ListObject(space, [space.wrap(1), space.wrap(2), space.wrap(3)])
+ assert self.space.listview_int(w_l) == [1, 2, 3]
+
class TestW_ListStrategiesDisabled:
def setup_class(cls):
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
@@ -8,12 +8,14 @@
is not too wrong.
"""
import py.test
-from pypy.objspace.std.setobject import W_SetObject, W_FrozensetObject
+from pypy.objspace.std.setobject import W_SetObject, W_FrozensetObject, IntegerSetStrategy
from pypy.objspace.std.setobject import _initialize_set
-from pypy.objspace.std.setobject import newset, make_setdata_from_w_iterable
+from pypy.objspace.std.setobject import newset
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
+from pypy.objspace.std.listobject import W_ListObject
letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
@@ -29,12 +31,11 @@
self.false = self.space.w_False
def test_and(self):
- s = W_SetObject(self.space, newset(self.space))
+ s = W_SetObject(self.space)
_initialize_set(self.space, s, self.word)
- t0 = W_SetObject(self.space, newset(self.space))
+ t0 = W_SetObject(self.space)
_initialize_set(self.space, t0, self.otherword)
- t1 = W_FrozensetObject(self.space,
- make_setdata_from_w_iterable(self.space, self.otherword))
+ t1 = W_FrozensetObject(self.space, self.otherword)
r0 = and__Set_Set(self.space, s, t0)
r1 = and__Set_Set(self.space, s, t1)
assert eq__Set_Set(self.space, r0, r1) == self.true
@@ -42,9 +43,9 @@
assert eq__Set_Set(self.space, r0, sr) == self.true
def test_compare(self):
- s = W_SetObject(self.space, newset(self.space))
+ s = W_SetObject(self.space)
_initialize_set(self.space, s, self.word)
- t = W_SetObject(self.space, newset(self.space))
+ t = W_SetObject(self.space)
_initialize_set(self.space, t, self.word)
assert self.space.eq_w(s,t)
u = self.space.wrap(set('simsalabim'))
@@ -54,7 +55,247 @@
s = self.space.newset()
assert self.space.str_w(self.space.repr(s)) == 'set([])'
+ def test_intersection_order(self):
+ # theses tests make sure that intersection is done in the correct order
+ # (smallest first)
+ space = self.space
+ a = W_SetObject(self.space)
+ _initialize_set(self.space, a, self.space.wrap("abcdefg"))
+ a.intersect = None
+
+ b = W_SetObject(self.space)
+ _initialize_set(self.space, b, self.space.wrap("abc"))
+
+ result = set_intersection__Set(space, a, [b])
+ assert space.is_true(self.space.eq(result, W_SetObject(space, self.space.wrap("abc"))))
+
+ c = W_SetObject(self.space)
+ _initialize_set(self.space, c, self.space.wrap("e"))
+
+ d = W_SetObject(self.space)
+ _initialize_set(self.space, d, self.space.wrap("ab"))
+
+ # if ordering works correct we should start with set e
+ a.get_storage_copy = None
+ b.get_storage_copy = None
+ d.get_storage_copy = None
+
+ result = set_intersection__Set(space, a, [d,c,b])
+ assert space.is_true(self.space.eq(result, W_SetObject(space, self.space.wrap(""))))
+
+ def test_create_set_from_list(self):
+ from pypy.objspace.std.setobject import ObjectSetStrategy, StringSetStrategy
+ from pypy.objspace.std.floatobject import W_FloatObject
+ from pypy.objspace.std.model import W_Object
+
+ w = self.space.wrap
+ intstr = self.space.fromcache(IntegerSetStrategy)
+ tmp_func = intstr.get_storage_from_list
+ # test if get_storage_from_list is no longer used
+ intstr.get_storage_from_list = None
+
+ w_list = W_ListObject(self.space, [w(1), w(2), w(3)])
+ w_set = W_SetObject(self.space)
+ _initialize_set(self.space, w_set, w_list)
+ assert w_set.strategy is intstr
+ assert intstr.unerase(w_set.sstorage) == {1:None, 2:None, 3:None}
+
+ w_list = W_ListObject(self.space, [w("1"), w("2"), w("3")])
+ w_set = W_SetObject(self.space)
+ _initialize_set(self.space, w_set, w_list)
+ assert w_set.strategy is self.space.fromcache(StringSetStrategy)
+ assert w_set.strategy.unerase(w_set.sstorage) == {"1":None, "2":None, "3":None}
+
+ w_list = W_ListObject(self.space, [w("1"), w(2), w("3")])
+ w_set = W_SetObject(self.space)
+ _initialize_set(self.space, w_set, w_list)
+ assert w_set.strategy is self.space.fromcache(ObjectSetStrategy)
+ for item in w_set.strategy.unerase(w_set.sstorage):
+ assert isinstance(item, W_Object)
+
+ w_list = W_ListObject(self.space, [w(1.0), w(2.0), w(3.0)])
+ w_set = W_SetObject(self.space)
+ _initialize_set(self.space, w_set, w_list)
+ assert w_set.strategy is self.space.fromcache(ObjectSetStrategy)
+ for item in w_set.strategy.unerase(w_set.sstorage):
+ assert isinstance(item, W_FloatObject)
+
+ # changed cached object, need to change it back for other tests to pass
+ intstr.get_storage_from_list = tmp_func
+
+ def test_listview_str_int_on_set(self):
+ w = self.space.wrap
+
+ w_a = W_SetObject(self.space)
+ _initialize_set(self.space, w_a, w("abcdefg"))
+ assert sorted(self.space.listview_str(w_a)) == list("abcdefg")
+ assert self.space.listview_int(w_a) is None
+
+ w_b = W_SetObject(self.space)
+ _initialize_set(self.space, w_b, self.space.newlist([w(1),w(2),w(3),w(4),w(5)]))
+ assert sorted(self.space.listview_int(w_b)) == [1,2,3,4,5]
+ assert self.space.listview_str(w_b) is None
+
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()
+ b.add(4)
+ c = a.union(b)
+ assert c == set([1,2,3,4])
+
+ def test_generator(self):
+ def foo():
+ for i in [1,2,3,4,5]:
+ yield i
+ b = set(foo())
+ assert b == set([1,2,3,4,5])
+
+ a = set(x for x in [1,2,3])
+ assert a == set([1,2,3])
+
+ def test_generator2(self):
+ def foo():
+ for i in [1,2,3]:
+ yield i
+ class A(set):
+ pass
+ a = A([1,2,3,4,5])
+ b = a.difference(foo())
+ assert b == set([4,5])
+
+ def test_or(self):
+ a = set([0,1,2])
+ b = a | set([1,2,3])
+ assert b == set([0,1,2,3])
+
+ # test inplace or
+ a |= set([1,2,3])
+ assert a == b
+
+ def test_clear(self):
+ a = set([1,2,3])
+ a.clear()
+ assert a == set()
+
+ def test_sub(self):
+ a = set([1,2,3,4,5])
+ b = set([2,3,4])
+ a - b == [1,5]
+ a.__sub__(b) == [1,5]
+
+ #inplace sub
+ a = set([1,2,3,4])
+ b = set([1,4])
+ a -= b
+ assert a == set([2,3])
+
+ def test_issubset(self):
+ a = set([1,2,3,4])
+ b = set([2,3])
+ assert b.issubset(a)
+ c = [1,2,3,4]
+ assert b.issubset(c)
+
+ a = set([1,2,3,4])
+ b = set(['1','2'])
+ assert not b.issubset(a)
+
+ def test_issuperset(self):
+ a = set([1,2,3,4])
+ b = set([2,3])
+ assert a.issuperset(b)
+ c = [2,3]
+ assert a.issuperset(c)
+
+ c = [1,1,1,1,1]
+ assert a.issuperset(c)
+ assert set([1,1,1,1,1]).issubset(a)
+
+ a = set([1,2,3])
+ assert a.issuperset(a)
+ assert not a.issuperset(set([1,2,3,4,5]))
+
+ def test_inplace_and(test):
+ a = set([1,2,3,4])
+ b = set([0,2,3,5,6])
+ a &= b
+ assert a == set([2,3])
+
+ def test_discard_remove(self):
+ a = set([1,2,3,4,5])
+ a.remove(1)
+ assert a == set([2,3,4,5])
+ a.discard(2)
+ assert a == set([3,4,5])
+
+ raises(KeyError, "a.remove(6)")
+
+ def test_pop(self):
+ b = set()
+ raises(KeyError, "b.pop()")
+
+ a = set([1,2,3,4,5])
+ for i in xrange(5):
+ a.pop()
+ 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])
+
+ a = set([1,2,3])
+ b = set('abc')
+ c = a.symmetric_difference(b)
+ assert c == set([1,2,3,'a','b','c'])
+
+ 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()
@@ -131,6 +372,8 @@
assert (set('abc') != set('abcd'))
assert (frozenset('abc') != frozenset('abcd'))
assert (frozenset('abc') != set('abcd'))
+ assert set() != set('abc')
+ assert set('abc') != set('abd')
def test_libpython_equality(self):
for thetype in [frozenset, set]:
@@ -178,6 +421,9 @@
s1 = set('abc')
s1.update('d', 'ef', frozenset('g'))
assert s1 == set('abcdefg')
+ s1 = set()
+ s1.update(set('abcd'))
+ assert s1 == set('abcd')
def test_recursive_repr(self):
class A(object):
@@ -330,6 +576,7 @@
assert not set([1,2,5]).isdisjoint(frozenset([4,5,6]))
assert not set([1,2,5]).isdisjoint([4,5,6])
assert not set([1,2,5]).isdisjoint((4,5,6))
+ assert set([1,2,3]).isdisjoint(set([3.5,4.0]))
def test_intersection(self):
assert set([1,2,3]).intersection(set([2,3,4])) == set([2,3])
@@ -347,6 +594,35 @@
assert s.intersection() == s
assert s.intersection() is not s
+ def test_intersection_swap(self):
+ s1 = s3 = set([1,2,3,4,5])
+ s2 = set([2,3,6,7])
+ s1 &= s2
+ assert s1 == set([2,3])
+ assert s3 == set([2,3])
+
+ def test_intersection_generator(self):
+ def foo():
+ for i in range(5):
+ yield i
+
+ s1 = s2 = set([1,2,3,4,5,6])
+ assert s1.intersection(foo()) == set([1,2,3,4])
+ s1.intersection_update(foo())
+ assert s1 == set([1,2,3,4])
+ assert s2 == set([1,2,3,4])
+
+ def test_intersection_string(self):
+ s = set([1,2,3])
+ o = 'abc'
+ assert s.intersection(o) == set()
+
+ def test_intersection_float(self):
+ a = set([1,2,3])
+ b = set([3.0,4.0,5.0])
+ c = a.intersection(b)
+ assert c == set([3.0])
+
def test_difference(self):
assert set([1,2,3]).difference(set([2,3,4])) == set([1])
assert set([1,2,3]).difference(frozenset([2,3,4])) == set([1])
@@ -361,6 +637,9 @@
s = set([1,2,3])
assert s.difference() == s
assert s.difference() is not s
+ assert set([1,2,3]).difference(set([2,3,4,'5'])) == set([1])
+ assert set([1,2,3,'5']).difference(set([2,3,4])) == set([1,'5'])
+ assert set().difference(set([1,2,3])) == set()
def test_intersection_update(self):
s = set([1,2,3,4,7])
@@ -381,3 +660,250 @@
assert s == set([2,3])
s.difference_update(s)
assert s == set([])
+
+ def test_empty_empty(self):
+ assert set() == set([])
+
+ def test_empty_difference(self):
+ e = set()
+ x = set([1,2,3])
+ assert e.difference(x) == set()
+ assert x.difference(e) == x
+
+ e.difference_update(x)
+ assert e == set()
+ x.difference_update(e)
+ assert x == set([1,2,3])
+
+ assert e.symmetric_difference(x) == x
+ assert x.symmetric_difference(e) == x
+
+ e.symmetric_difference_update(e)
+ assert e == e
+ e.symmetric_difference_update(x)
+ assert e == x
+
+ x.symmetric_difference_update(set())
+ assert x == set([1,2,3])
+
+ def test_fastpath_with_strategies(self):
+ a = set([1,2,3])
+ b = set(["a","b","c"])
+ assert a.difference(b) == a
+ assert b.difference(a) == b
+
+ a = set([1,2,3])
+ b = set(["a","b","c"])
+ assert a.intersection(b) == set()
+ assert b.intersection(a) == set()
+
+ a = set([1,2,3])
+ b = set(["a","b","c"])
+ assert not a.issubset(b)
+ assert not b.issubset(a)
+
+ a = set([1,2,3])
+ b = set(["a","b","c"])
+ assert a.isdisjoint(b)
+ assert b.isdisjoint(a)
+
+ def test_empty_intersect(self):
+ e = set()
+ x = set([1,2,3])
+ assert e.intersection(x) == e
+ assert x.intersection(e) == e
+ assert e & x == e
+ assert x & e == e
+
+ e.intersection_update(x)
+ assert e == set()
+ e &= x
+ assert e == set()
+ x.intersection_update(e)
+ assert x == set()
+
+ def test_empty_issuper(self):
+ e = set()
+ x = set([1,2,3])
+ assert e.issuperset(e) == True
+ assert e.issuperset(x) == False
+ assert x.issuperset(e) == True
+
+ assert e.issuperset(set())
+ assert e.issuperset([])
+
+ def test_empty_issubset(self):
+ e = set()
+ x = set([1,2,3])
+ assert e.issubset(e) == True
+ assert e.issubset(x) == True
+ assert x.issubset(e) == False
+ assert e.issubset([])
+
+ def test_empty_isdisjoint(self):
+ e = set()
+ x = set([1,2,3])
+ assert e.isdisjoint(e) == True
+ assert e.isdisjoint(x) == True
+ assert x.isdisjoint(e) == True
+
+ def test_empty_unhashable(self):
+ s = set()
+ raises(TypeError, s.difference, [[]])
+ raises(TypeError, s.difference_update, [[]])
+ raises(TypeError, s.intersection, [[]])
+ raises(TypeError, s.intersection_update, [[]])
+ raises(TypeError, s.symmetric_difference, [[]])
+ raises(TypeError, s.symmetric_difference_update, [[]])
+ raises(TypeError, s.update, [[]])
+
+ def test_super_with_generator(self):
+ def foo():
+ for i in [1,2,3]:
+ yield i
+ set([1,2,3,4,5]).issuperset(foo())
+
+ def test_isdisjoint_with_generator(self):
+ def foo():
+ for i in [1,2,3]:
+ yield i
+ set([1,2,3,4,5]).isdisjoint(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_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]))
+
+ def test_create_set_from_set(self):
+ # no sharing
+ x = set([1,2,3])
+ y = set(x)
+ a = x.pop()
+ assert y == set([1,2,3])
+ assert len(x) == 2
+ assert x.union(set([a])) == y
+
+ def test_never_change_frozenset(self):
+ a = frozenset([1,2])
+ b = a.copy()
+ assert a is b
+
+ a = frozenset([1,2])
+ b = a.union(set([3,4]))
+ assert b == set([1,2,3,4])
+ assert a == set([1,2])
+
+ a = frozenset()
+ b = a.union(set([3,4]))
+ assert b == set([3,4])
+ assert a == set()
+
+ a = frozenset([1,2])#multiple
+ b = a.union(set([3,4]),[5,6])
+ assert b == set([1,2,3,4,5,6])
+ assert a == set([1,2])
+
+ a = frozenset([1,2,3])
+ b = a.difference(set([3,4,5]))
+ assert b == set([1,2])
+ assert a == set([1,2,3])
+
+ a = frozenset([1,2,3])#multiple
+ b = a.difference(set([3]), [2])
+ assert b == set([1])
+ assert a == set([1,2,3])
+
+ a = frozenset([1,2,3])
+ b = a.symmetric_difference(set([3,4,5]))
+ assert b == set([1,2,4,5])
+ assert a == set([1,2,3])
+
+ a = frozenset([1,2,3])
+ b = a.intersection(set([3,4,5]))
+ assert b == set([3])
+ assert a == set([1,2,3])
+
+ a = frozenset([1,2,3])#multiple
+ b = a.intersection(set([2,3,4]), [2])
+ assert b == set([2])
+ assert a == set([1,2,3])
+
+ raises(AttributeError, "frozenset().update()")
+ raises(AttributeError, "frozenset().difference_update()")
+ raises(AttributeError, "frozenset().symmetric_difference_update()")
+ raises(AttributeError, "frozenset().intersection_update()")
+
+ def test_intersection_obj(self):
+ class Obj:
+ def __getitem__(self, i):
+ return [5, 3, 4][i]
+ s = set([10,3,2]).intersection(Obj())
+ assert list(s) == [3]
diff --git a/pypy/objspace/std/test/test_setstrategies.py b/pypy/objspace/std/test/test_setstrategies.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/test/test_setstrategies.py
@@ -0,0 +1,107 @@
+from pypy.objspace.std.setobject import W_SetObject
+from pypy.objspace.std.setobject import IntegerSetStrategy, ObjectSetStrategy, EmptySetStrategy
+from pypy.objspace.std.listobject import W_ListObject
+
+class TestW_SetStrategies:
+
+ def wrapped(self, l):
+ return W_ListObject(self.space, [self.space.wrap(x) for x in l])
+
+ def test_from_list(self):
+ s = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+ assert s.strategy is self.space.fromcache(IntegerSetStrategy)
+
+ s = W_SetObject(self.space, self.wrapped([1,"two",3,"four",5]))
+ assert s.strategy is self.space.fromcache(ObjectSetStrategy)
+
+ s = W_SetObject(self.space)
+ assert s.strategy is self.space.fromcache(EmptySetStrategy)
+
+ s = W_SetObject(self.space, self.wrapped([]))
+ assert s.strategy is self.space.fromcache(EmptySetStrategy)
+
+ def test_switch_to_object(self):
+ s = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+ s.add(self.space.wrap("six"))
+ assert s.strategy is self.space.fromcache(ObjectSetStrategy)
+
+ s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+ s2 = W_SetObject(self.space, self.wrapped(["six", "seven"]))
+ s1.update(s2)
+ assert s1.strategy is self.space.fromcache(ObjectSetStrategy)
+
+ def test_symmetric_difference(self):
+ s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+ s2 = W_SetObject(self.space, self.wrapped(["six", "seven"]))
+ s1.symmetric_difference_update(s2)
+ assert s1.strategy is self.space.fromcache(ObjectSetStrategy)
+
+ def test_intersection(self):
+ s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+ s2 = W_SetObject(self.space, self.wrapped([4,5, "six", "seven"]))
+ s3 = s1.intersect(s2)
+ skip("for now intersection with ObjectStrategy always results in another ObjectStrategy")
+ assert s3.strategy is self.space.fromcache(IntegerSetStrategy)
+
+ def test_clear(self):
+ s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+ s1.clear()
+ assert s1.strategy is self.space.fromcache(EmptySetStrategy)
+
+ def test_remove(self):
+ from pypy.objspace.std.setobject import set_remove__Set_ANY
+ s1 = W_SetObject(self.space, self.wrapped([1]))
+ set_remove__Set_ANY(self.space, s1, self.space.wrap(1))
+ assert s1.strategy is self.space.fromcache(EmptySetStrategy)
+
+ def test_union(self):
+ from pypy.objspace.std.setobject import set_union__Set
+ s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+ s2 = W_SetObject(self.space, self.wrapped([4,5,6,7]))
+ s3 = W_SetObject(self.space, self.wrapped([4,'5','6',7]))
+ s4 = set_union__Set(self.space, s1, [s2])
+ s5 = set_union__Set(self.space, s1, [s3])
+ assert s4.strategy is self.space.fromcache(IntegerSetStrategy)
+ assert s5.strategy is self.space.fromcache(ObjectSetStrategy)
+
+ def test_discard(self):
+ 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
+
+ from pypy.objspace.std.setobject import set_discard__Set_ANY
+
+ s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+ set_discard__Set_ANY(self.space, s1, self.space.wrap("five"))
+ skip("currently not supported")
+ assert s1.strategy is self.space.fromcache(IntegerSetStrategy)
+
+ set_discard__Set_ANY(self.space, s1, self.space.wrap(FakeInt(5)))
+ assert s1.strategy is self.space.fromcache(ObjectSetStrategy)
+
+ def test_has_key(self):
+ 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
+
+ from pypy.objspace.std.setobject import set_discard__Set_ANY
+
+ s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
+ assert not s1.has_key(self.space.wrap("five"))
+ skip("currently not supported")
+ assert s1.strategy is self.space.fromcache(IntegerSetStrategy)
+
+ assert s1.has_key(self.space.wrap(FakeInt(2)))
+ assert s1.strategy is self.space.fromcache(ObjectSetStrategy)
diff --git a/pypy/objspace/std/test/test_stringobject.py b/pypy/objspace/std/test/test_stringobject.py
--- a/pypy/objspace/std/test/test_stringobject.py
+++ b/pypy/objspace/std/test/test_stringobject.py
@@ -85,6 +85,10 @@
w_slice = space.newslice(w(1), w_None, w(2))
assert self.space.eq_w(space.getitem(w_str, w_slice), w('el'))
+ def test_listview_str(self):
+ w_str = self.space.wrap('abcd')
+ assert self.space.listview_str(w_str) == list("abcd")
+
class AppTestStringObject:
def test_format_wrongchar(self):
More information about the pypy-commit
mailing list