[pypy-svn] r78288 - in pypy/branch/set-object-cleanup/pypy/objspace/std: . test

arigo at codespeak.net arigo at codespeak.net
Tue Oct 26 13:41:10 CEST 2010


Author: arigo
Date: Tue Oct 26 13:41:08 2010
New Revision: 78288

Modified:
   pypy/branch/set-object-cleanup/pypy/objspace/std/frozensettype.py
   pypy/branch/set-object-cleanup/pypy/objspace/std/setobject.py
   pypy/branch/set-object-cleanup/pypy/objspace/std/settype.py
   pypy/branch/set-object-cleanup/pypy/objspace/std/test/test_setobject.py
Log:
Rewrite a bit sets.  Tests pass, whatever that means.


Modified: pypy/branch/set-object-cleanup/pypy/objspace/std/frozensettype.py
==============================================================================
--- pypy/branch/set-object-cleanup/pypy/objspace/std/frozensettype.py	(original)
+++ pypy/branch/set-object-cleanup/pypy/objspace/std/frozensettype.py	Tue Oct 26 13:41:08 2010
@@ -39,13 +39,13 @@
 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 _is_frozenset_exact
+    from pypy.objspace.std.setobject import make_setdata_from_w_iterable
     if (space.is_w(w_frozensettype, space.w_frozenset) and
-        _is_frozenset_exact(w_iterable)):
+        w_iterable is not None and type(w_iterable) is W_FrozensetObject):
         return w_iterable
     w_obj = space.allocate_instance(W_FrozensetObject, w_frozensettype)
-    W_FrozensetObject.__init__(w_obj, space, None)
-
+    data = make_setdata_from_w_iterable(space, w_iterable)
+    W_FrozensetObject.__init__(w_obj, space, data)
     return w_obj
 
 frozenset_typedef = StdTypeDef("frozenset",

Modified: pypy/branch/set-object-cleanup/pypy/objspace/std/setobject.py
==============================================================================
--- pypy/branch/set-object-cleanup/pypy/objspace/std/setobject.py	(original)
+++ pypy/branch/set-object-cleanup/pypy/objspace/std/setobject.py	Tue Oct 26 13:41:08 2010
@@ -21,11 +21,10 @@
         return False
 
 
-    def __init__(w_self, space, setdata=None):
-        if setdata is None:
-            w_self.setdata = r_dict(space.eq_w, space.hash_w)
-        else:
-            w_self.setdata = setdata.copy()
+    def __init__(w_self, space, setdata):
+        """Initialize the set by taking ownership of 'setdata'."""
+        assert setdata is not None
+        w_self.setdata = setdata
 
     def __repr__(w_self):
         """representation for debugging purposes"""
@@ -33,6 +32,7 @@
         return "<%s(%s)>" % (w_self.__class__.__name__, ', '.join(reprlist))
 
     def _newobj(w_self, space, rdict_w=None):
+        """Make a new set or frozenset by taking ownership of 'rdict_w'."""
         #return space.call(space.type(w_self),W_SetIterObject(rdict_w))
         objtype = type(w_self)
         if objtype is W_SetObject:
@@ -55,10 +55,7 @@
 
 class W_FrozensetObject(W_BaseSetObject):
     from pypy.objspace.std.frozensettype import frozenset_typedef as typedef
-
-    def __init__(w_self, space, setdata):
-        W_BaseSetObject.__init__(w_self, space, setdata)
-        w_self.hash = -1
+    hash = 0
 
 registerimplementation(W_BaseSetObject)
 registerimplementation(W_SetObject)
@@ -109,8 +106,14 @@
 
 # some helper functions
 
+def newset(space):
+    return r_dict(space.eq_w, space.hash_w)
+
 def make_setdata_from_w_iterable(space, w_iterable=None):
-    data = r_dict(space.eq_w, space.hash_w)
+    """Return a new r_dict with the content of w_iterable."""
+    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
@@ -119,7 +122,7 @@
 def _initialize_set(space, w_obj, w_iterable=None):
     w_obj.setdata.clear()
     if w_iterable is not None:
-        w_obj.setdata.update(make_setdata_from_w_iterable(space, w_iterable))
+        w_obj.setdata = 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)):
@@ -130,12 +133,6 @@
 
 # helper functions for set operation on dicts
 
-def _is_frozenset_exact(w_obj):
-    if (w_obj is not None) and (type(w_obj) is W_FrozensetObject):
-        return True
-    else:
-        return False
-
 def _is_eq(ld, rd):
     if len(ld) != len(rd):
         return False
@@ -144,66 +141,41 @@
             return False
     return True
 
-def _union_dict(ldict, rdict, isupdate):
-    if isupdate:
-        ld = ldict
-    else:
-        ld = ldict.copy()
-    ld.update(rdict)
-    return ld, rdict
-
-def _difference_dict(ldict, rdict, isupdate):
-    if isupdate:
-        ld = ldict
-    else:
-        ld = ldict.copy()
-    del_list_w = []
+def _difference_dict(space, ld, rd):
+    result = newset(space)
     for w_key in ld:
-        if w_key in rdict:
-            del_list_w.append(w_key)
-    for w_key in del_list_w:
-        del ld[w_key]
-
-    return ld, rdict
-
-def _intersection_dict(ldict, rdict, isupdate):
-    if isupdate:
-        ld = ldict
-    else:
-        ld = ldict.copy()
-    del_list_w = []
-    for w_key in ld:
-        if w_key not in rdict:
-            del_list_w.append(w_key)
-
-    for w_key in del_list_w:
-        del ld[w_key]
-
-    return ld, rdict
-
+        if w_key not in rd:
+            result[w_key] = None
+    return result
 
-def _symmetric_difference_dict(ldict, rdict, isupdate):
-    if isupdate:
-        ld = ldict
+def _difference_dict_update(space, ld, rd):
+    if ld is rd:
+        ld.clear()     # for the case 'a.difference_update(a)'
     else:
-        ld = ldict.copy()
-    del_list_w = []
-    add_list_w = []
+        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 rdict:
-            del_list_w.append(w_key)
+        if w_key in rd:
+            result[w_key] = None
+    return result
 
-    for w_key in rdict:
+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:
-            add_list_w.append(w_key)
-
-    for w_key in del_list_w:
-        del ld[w_key]
-
-    for w_key in add_list_w:
-        ld[w_key] = None
-
-    return ld, rdict
+            result[w_key] = None
+    return result
 
 def _issubset_dict(ldict, rdict):
     if len(ldict) > len(rdict):
@@ -220,14 +192,13 @@
 def set_update__Set_BaseSet(space, w_left, w_other):
     # optimization only (the general case works too)
     ld, rd = w_left.setdata, w_other.setdata
-    new_ld, rd = _union_dict(ld, rd, True)
-    return space.w_None
+    ld.update(rd)
 
 def set_update__Set_ANY(space, w_left, w_other):
     """Update a set with the union of itself and another."""
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _union_dict(ld, rd, True)
-    return space.w_None
+    ld = w_left.setdata
+    for w_item in space.listview(w_other):
+        ld[w_item] = None
 
 def inplace_or__Set_Set(space, w_left, w_other):
     set_update__Set_BaseSet(space, w_left, w_other)
@@ -241,25 +212,23 @@
     This has no effect if the element is already present.
     """
     w_left.setdata[w_other] = None
-    return space.w_None
 
 def set_copy__Set(space, w_set):
-    return w_set._newobj(space,w_set.setdata)
+    return w_set._newobj(space, w_set.setdata.copy())
 
 def frozenset_copy__Frozenset(space, w_left):
-    if _is_frozenset_exact(w_left):
+    if type(w_left) is W_FrozensetObject:
         return w_left
     else:
-        return set_copy__Set(space,w_left)
+        return set_copy__Set(space, w_left)
 
 def set_clear__Set(space, w_left):
     w_left.setdata.clear()
-    return space.w_None
 
 def set_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, rd = _difference_dict(ld, rd, False)
+    new_ld = _difference_dict(space, ld, rd)
     return w_left._newobj(space, new_ld)
 
 set_difference__Set_Frozenset = set_difference__Set_Set
@@ -272,7 +241,7 @@
 
 def set_difference__Set_ANY(space, w_left, w_other):
     ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _difference_dict(ld, rd, False)
+    new_ld = _difference_dict(space, ld, rd)
     return w_left._newobj(space, new_ld)
 
 frozenset_difference__Frozenset_ANY = set_difference__Set_ANY
@@ -281,15 +250,17 @@
 def set_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, rd = _difference_dict(ld, rd, True)
-    return space.w_None
+    _difference_dict_update(space, ld, rd)
 
 set_difference_update__Set_Frozenset = set_difference_update__Set_Set
 
 def set_difference_update__Set_ANY(space, w_left, w_other):
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _difference_dict(ld, rd, True)
-    return space.w_None
+    ld = w_left.setdata
+    for w_key in space.listview(w_other):
+        try:
+            del ld[w_key]
+        except KeyError:
+            pass
 
 def inplace_sub__Set_Set(space, w_left, w_other):
     set_difference_update__Set_Set(space, w_left, w_other)
@@ -467,7 +438,7 @@
 
 def hash__Frozenset(space, w_set):
     multi = r_uint(1822399083) + r_uint(1822399083) + 1
-    if w_set.hash != -1:
+    if w_set.hash != 0:
         return space.wrap(w_set.hash)
     hash = 1927868237
     hash *= (len(w_set.setdata) + 1)
@@ -476,7 +447,7 @@
         value = ((h ^ (h << 16) ^ 89869747)  * multi)
         hash = intmask(hash ^ value)
     hash = hash * 69069 + 907133923
-    if hash == -1:
+    if hash == 0:
         hash = 590923713
     hash = intmask(hash)
     w_set.hash = hash
@@ -484,29 +455,31 @@
     return space.wrap(hash)
 
 def set_pop__Set(space, w_left):
-    if len(w_left.setdata) == 0:
+    for w_key in w_left.setdata:
+        break
+    else:
         raise OperationError(space.w_KeyError,
                                 space.wrap('pop from an empty set'))
-    w_keys = w_left.setdata.keys()
-    w_value = w_keys[0]
-    del w_left.setdata[w_value]
-
-    return w_value
+    del w_left.setdata[w_key]
+    return w_key
 
 def set_intersection__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
     ld, rd = w_left.setdata, w_other.setdata
-    new_ld, rd = _intersection_dict(ld, rd, False)
-    return w_left._newobj(space,new_ld)
+    new_ld = _intersection_dict(space, ld, rd)
+    return w_left._newobj(space, new_ld)
 
 set_intersection__Set_Frozenset = set_intersection__Set_Set
 set_intersection__Frozenset_Frozenset = set_intersection__Set_Set
 set_intersection__Frozenset_Set = set_intersection__Set_Set
 
 def set_intersection__Set_ANY(space, w_left, w_other):
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _intersection_dict(ld, rd, False)
-    return w_left._newobj(space,new_ld)
+    result = newset(space)
+    ld = w_left.setdata
+    for w_key in space.listview(w_other):
+        if w_key in ld:
+            result[w_key] = None
+    return w_left._newobj(space, result)
 
 frozenset_intersection__Frozenset_ANY = set_intersection__Set_ANY
 
@@ -518,15 +491,18 @@
 def set_intersection_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, rd = _intersection_dict(ld, rd, True)
-    return space.w_None
+    new_ld = _intersection_dict(space, ld, rd)
+    w_left.setdata = new_ld
 
 set_intersection_update__Set_Frozenset = set_intersection_update__Set_Set
 
 def set_intersection_update__Set_ANY(space, w_left, w_other):
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _intersection_dict(ld, rd, True)
-    return space.w_None
+    result = newset(space)
+    ld = w_left.setdata
+    for w_key in space.listview(w_other):
+        if w_key in ld:
+            result[w_key] = None
+    w_left.setdata = result
 
 def inplace_and__Set_Set(space, w_left, w_other):
     set_intersection_update__Set_Set(space, w_left, w_other)
@@ -537,7 +513,7 @@
 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, rd = _symmetric_difference_dict(ld, rd, False)
+    new_ld = _symmetric_difference_dict(space, ld, rd)
     return w_left._newobj(space, new_ld)
 
 set_symmetric_difference__Set_Frozenset = set_symmetric_difference__Set_Set
@@ -553,7 +529,7 @@
 
 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, rd = _symmetric_difference_dict(ld, rd, False)
+    new_ld = _symmetric_difference_dict(space, ld, rd)
     return w_left._newobj(space, new_ld)
 
 frozenset_symmetric_difference__Frozenset_ANY = \
@@ -562,16 +538,16 @@
 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, rd = _symmetric_difference_dict(ld, rd, True)
-    return space.w_None
+    new_ld = _symmetric_difference_dict(space, ld, rd)
+    w_left.setdata = new_ld
 
 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, rd = _symmetric_difference_dict(ld, rd, True)
-    return space.w_None
+    new_ld = _symmetric_difference_dict(space, ld, rd)
+    w_left.setdata = new_ld
 
 def inplace_xor__Set_Set(space, w_left, w_other):
     set_symmetric_difference_update__Set_Set(space, w_left, w_other)
@@ -582,8 +558,9 @@
 def set_union__Set_Set(space, w_left, w_other):
     # optimization only (the general case works too)
     ld, rd = w_left.setdata, w_other.setdata
-    new_ld, rd = _union_dict(ld, rd, False)
-    return w_left._newobj(space, new_ld)
+    result = ld.copy()
+    result.update(rd)
+    return w_left._newobj(space, result)
 
 set_union__Set_Frozenset = set_union__Set_Set
 set_union__Frozenset_Set = set_union__Set_Set
@@ -595,9 +572,11 @@
 
 
 def set_union__Set_ANY(space, w_left, w_other):
-    ld, rd = w_left.setdata, make_setdata_from_w_iterable(space, w_other)
-    new_ld, rd = _union_dict(ld, rd, False)
-    return w_left._newobj(space, new_ld)
+    ld = w_left.setdata()
+    result = ld.copy()
+    for w_key in space.viewlist(w_other):
+        result[w_key] = None
+    return w_left._newobj(space, result)
 
 frozenset_union__Frozenset_ANY = set_union__Set_ANY
 
@@ -629,15 +608,6 @@
             init_defaults)
     _initialize_set(space, w_set, w_iterable)
 
-def init__Frozenset(space, w_set, __args__):
-    w_iterable, = __args__.parse_obj(
-            None, 'set',
-            init_signature,
-            init_defaults)
-    if w_set.hash == -1:
-        _initialize_set(space, w_set, w_iterable)
-        hash__Frozenset(space, w_set)
-
 app = gateway.applevel("""
     def setrepr(currently_in_repr, s):
         'The app-level part of repr().'

Modified: pypy/branch/set-object-cleanup/pypy/objspace/std/settype.py
==============================================================================
--- pypy/branch/set-object-cleanup/pypy/objspace/std/settype.py	(original)
+++ pypy/branch/set-object-cleanup/pypy/objspace/std/settype.py	Tue Oct 26 13:41:08 2010
@@ -66,9 +66,9 @@
 register_all(vars(), globals())
 
 def descr__new__(space, w_settype, __args__):
-    from pypy.objspace.std.setobject import W_SetObject
+    from pypy.objspace.std.setobject import W_SetObject, newset
     w_obj = space.allocate_instance(W_SetObject, w_settype)
-    W_SetObject.__init__(w_obj, space, None)
+    W_SetObject.__init__(w_obj, space, newset(space))
     return w_obj
 
 set_typedef = StdTypeDef("set",

Modified: pypy/branch/set-object-cleanup/pypy/objspace/std/test/test_setobject.py
==============================================================================
--- pypy/branch/set-object-cleanup/pypy/objspace/std/test/test_setobject.py	(original)
+++ pypy/branch/set-object-cleanup/pypy/objspace/std/test/test_setobject.py	Tue Oct 26 13:41:08 2010
@@ -10,6 +10,7 @@
 import py.test
 from pypy.objspace.std.setobject import W_SetObject, W_FrozensetObject
 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 set_intersection__Set_Set
 from pypy.objspace.std.setobject import set_intersection__Set_ANY
 from pypy.objspace.std.setobject import eq__Set_Set
@@ -28,12 +29,12 @@
         self.false = self.space.w_False
 
     def test_and(self):
-        s = W_SetObject(self.space, None)
+        s = W_SetObject(self.space, newset(self.space))
         _initialize_set(self.space, s, self.word)
-        t0 = W_SetObject(self.space, None)
+        t0 = W_SetObject(self.space, newset(self.space))
         _initialize_set(self.space, t0, self.otherword)
-        t1 = W_FrozensetObject(self.space, None)
-        _initialize_set(self.space, t1, self.otherword)
+        t1 = W_FrozensetObject(self.space,
+                make_setdata_from_w_iterable(self.space, self.otherword))
         r0 = set_intersection__Set_Set(self.space, s, t0)
         r1 = set_intersection__Set_Set(self.space, s, t1)
         assert eq__Set_Set(self.space, r0, r1) == self.true
@@ -41,9 +42,9 @@
         assert eq__Set_Set(self.space, r0, sr) == self.true
 
     def test_compare(self):
-        s = W_SetObject(self.space, None)
+        s = W_SetObject(self.space, newset(self.space))
         _initialize_set(self.space, s, self.word)
-        t = W_SetObject(self.space, None)
+        t = W_SetObject(self.space, newset(self.space))
         _initialize_set(self.space, t, self.word)
         assert self.space.eq_w(s,t)
         u = self.space.wrap(set('simsalabim'))



More information about the Pypy-commit mailing list