[pypy-svn] r58779 - in pypy/branch/2.5-merge/pypy/objspace/std: . test
iko at codespeak.net
iko at codespeak.net
Tue Oct 7 18:01:06 CEST 2008
Author: iko
Date: Tue Oct 7 18:01:04 2008
New Revision: 58779
Modified:
pypy/branch/2.5-merge/pypy/objspace/std/setobject.py
pypy/branch/2.5-merge/pypy/objspace/std/test/test_set.py
Log:
(iko, cfbolz)
Fix set autoconversion to frozenset
Modified: pypy/branch/2.5-merge/pypy/objspace/std/setobject.py
==============================================================================
--- pypy/branch/2.5-merge/pypy/objspace/std/setobject.py (original)
+++ pypy/branch/2.5-merge/pypy/objspace/std/setobject.py Tue Oct 7 18:01:04 2008
@@ -113,6 +113,12 @@
if w_iterable is not None:
w_obj.setdata.update(make_setdata_from_w_iterable(space, w_iterable))
+def _convert_set_to_frozenset(space, w_obj):
+ if space.is_true(space.isinstance(w_obj, space.w_set)):
+ return space.newfrozenset(make_setdata_from_w_iterable(space, w_obj))
+ else:
+ return None
+
# helper functions for set operation on dicts
def _is_frozenset_exact(w_obj):
@@ -303,25 +309,18 @@
ne__Frozenset_ANY = ne__Set_ANY
-def contains__Set_Set(space, w_left, w_other):
- # optimization only (for the case __Set_settypedef)
- w_f = space.newfrozenset(w_other.setdata)
- return space.newbool(w_f in w_left.setdata)
-
-contains__Frozenset_Set = contains__Set_Set
-
-def contains__Set_settypedef(space, w_left, w_other):
- # This is the general case to handle 'set in set' or 'set in
- # frozenset'. We need this in case w_other is of type 'set' but the
- # case 'contains__Set_Set' is not selected by the multimethod logic,
- # which can occur (see test_builtinshortcut).
- w_f = space.newfrozenset(make_setdata_from_w_iterable(space, w_other))
- return space.newbool(w_f in w_left.setdata)
-
-contains__Frozenset_settypedef = contains__Set_settypedef
-
def contains__Set_ANY(space, w_left, w_other):
- return space.newbool(w_other in w_left.setdata)
+ try:
+ return space.newbool(w_other in w_left.setdata)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+
+ w_f = _convert_set_to_frozenset(space, w_other)
+ if w_f is not None:
+ return space.newbool(w_f in w_left.setdata)
+ else:
+ return space.w_False
contains__Frozenset_ANY = contains__Set_ANY
@@ -422,42 +421,43 @@
gt__Frozenset_Set = gt__Set_Set
gt__Frozenset_Frozenset = gt__Set_Set
+def _discard_from_set(space, w_left, w_item):
+ """
+ Discard an element from a set, with automatic conversion to
+ frozenset if the argument is a set.
-def set_discard__Set_Set(space, w_left, w_item):
- # optimization only (the general case is set_discard__Set_settypedef)
- w_f = space.newfrozenset(w_item.setdata)
- if w_f in w_left.setdata:
- del w_left.setdata[w_f]
-
-def set_discard__Set_settypedef(space, w_left, w_item):
- w_f = space.newfrozenset(make_setdata_from_w_iterable(space, w_item))
- if w_f in w_left.setdata:
- del w_left.setdata[w_f]
-
-def set_discard__Set_ANY(space, w_left, w_item):
- if w_item in w_left.setdata:
- del w_left.setdata[w_item]
-
-def set_remove__Set_Set(space, w_left, w_item):
- # optimization only (the general case is set_remove__Set_settypedef)
- w_f = space.newfrozenset(w_item.setdata)
+ Returns None if successfully removed, otherwise the object that
+ wasn't there is returned.
+ """
try:
- del w_left.setdata[w_f]
+ del w_left.setdata[w_item]
+ return None
except KeyError:
- raise OperationError(space.w_KeyError, w_item)
-
-def set_remove__Set_settypedef(space, w_left, w_item):
- w_f = space.newfrozenset(make_setdata_from_w_iterable(space, w_item))
+ return 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:
+ return w_item
try:
del w_left.setdata[w_f]
+ return None
except KeyError:
- raise OperationError(space.w_KeyError, w_item)
+ return w_f
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ return w_f
+
+def set_discard__Set_ANY(space, w_left, w_item):
+ _discard_from_set(space, w_left, w_item)
def set_remove__Set_ANY(space, w_left, w_item):
- try:
- del w_left.setdata[w_item]
- except KeyError:
- raise OperationError(space.w_KeyError, w_item)
+ w_f = _discard_from_set(space, w_left, w_item)
+ if w_f is not None:
+ raise OperationError(space.w_KeyError, w_f)
def hash__Frozenset(space, w_set):
multi = r_uint(1822399083) + r_uint(1822399083) + 1
Modified: pypy/branch/2.5-merge/pypy/objspace/std/test/test_set.py
==============================================================================
--- pypy/branch/2.5-merge/pypy/objspace/std/test/test_set.py (original)
+++ pypy/branch/2.5-merge/pypy/objspace/std/test/test_set.py Tue Oct 7 18:01:04 2008
@@ -105,3 +105,41 @@
f.add(s)
f.discard(s)
+ def test_autoconvert_to_frozen__contains(self):
+ s = set([frozenset([1,2])])
+
+ assert set([1,2]) in s
+
+ def test_autoconvert_to_frozen_remove(self):
+ s = set([frozenset([1,2])])
+
+ s.remove(set([1,2]))
+ assert len(s) == 0
+ raises(KeyError, s.remove, set([1,2]))
+
+ def test_autoconvert_to_frozen_discard(self):
+ s = set([frozenset([1,2])])
+
+ s.discard(set([1,2]))
+ assert len(s) == 0
+ s.discard(set([1,2]))
+
+ def test_autoconvert_to_frozen_onlyon_type_error(self):
+ class A(set):
+ def __hash__(self):
+ return id(self)
+
+ s = A([1, 2, 3])
+ s2 = set([2, 3, s])
+ assert A() not in s2
+ s2.add(frozenset())
+ assert A() not in s2
+ raises(KeyError, s2.remove, A())
+
+ def test_autoconvert_key_error(self):
+ s = set([frozenset([1, 2]), frozenset([3, 4])])
+ try:
+ s.remove(set([2, 3]))
+ except KeyError, e:
+ assert isinstance(e.args[0], frozenset)
+ assert e.args[0] == frozenset([2, 3])
More information about the Pypy-commit
mailing list