[pypy-svn] r78301 - in pypy/trunk/pypy: interpreter objspace/std objspace/std/test

arigo at codespeak.net arigo at codespeak.net
Tue Oct 26 17:05:51 CEST 2010


Author: arigo
Date: Tue Oct 26 17:05:48 2010
New Revision: 78301

Modified:
   pypy/trunk/pypy/interpreter/baseobjspace.py
   pypy/trunk/pypy/objspace/std/dictmultiobject.py
   pypy/trunk/pypy/objspace/std/dicttype.py
   pypy/trunk/pypy/objspace/std/frozensettype.py
   pypy/trunk/pypy/objspace/std/setobject.py
   pypy/trunk/pypy/objspace/std/settype.py
   pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py
   pypy/trunk/pypy/objspace/std/test/test_setobject.py
Log:
Merge branch/set-object-cleanup.

General clean-up of setobject.py, reducing the number of copies
of the whole data that we need.

In dicttype.py, remove some very old app-level helpers and implement them
at interp-level.


Modified: pypy/trunk/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/trunk/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/trunk/pypy/interpreter/baseobjspace.py	Tue Oct 26 17:05:48 2010
@@ -739,7 +739,7 @@
 
     def unpackiterable(self, w_iterable, expected_length=-1):
         """Unpack an iterable object into a real (interpreter-level) list.
-        Raise a real (subclass of) ValueError if the length is wrong."""
+        Raise an OperationError(w_ValueError) if the length is wrong."""
         w_iterator = self.iter(w_iterable)
         items = []
         while True:

Modified: pypy/trunk/pypy/objspace/std/dictmultiobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/dictmultiobject.py	(original)
+++ pypy/trunk/pypy/objspace/std/dictmultiobject.py	Tue Oct 26 17:05:48 2010
@@ -641,30 +641,50 @@
 init_signature = Signature(['seq_or_map'], None, 'kwargs')
 init_defaults = [None]
 
-def init__DictMulti(space, w_dict, __args__):
-    w_src, w_kwds = __args__.parse_obj(
-            None, 'dict',
-            init_signature, # signature
-            init_defaults)                           # default argument
-    if w_src is None:
-        pass
-    elif space.findattr(w_src, space.wrap("keys")) is None:
-        list_of_w_pairs = space.listview(w_src)
-        for w_pair in list_of_w_pairs:
+def update1(space, w_dict, w_data):
+    if space.findattr(w_data, space.wrap("keys")) is None:
+        # no 'keys' method, so we assume it is a sequence of pairs
+        for w_pair in space.listview(w_data):
             pair = space.fixedview(w_pair)
-            if len(pair)!=2:
+            if len(pair) != 2:
                 raise OperationError(space.w_ValueError,
-                             space.wrap("dict() takes a sequence of pairs"))
-            w_k, w_v = pair
-            w_dict.setitem(w_k, w_v)
+                             space.wrap("sequence of pairs expected"))
+            w_key, w_value = pair
+            w_dict.setitem(w_key, w_value)
     else:
-        if space.is_true(w_src):
-            from pypy.objspace.std.dicttype import update1
-            update1(space, w_dict, w_src)
+        if isinstance(w_data, W_DictMultiObject):    # optimization case only
+            update1_dict_dict(space, w_dict, w_data)
+        else:
+            # general case -- "for k in o.keys(): dict.__setitem__(d, k, o[k])"
+            w_keys = space.call_method(w_data, "keys")
+            for w_key in space.listview(w_keys):
+                w_value = space.getitem(w_data, w_key)
+                w_dict.setitem(w_key, w_value)
+
+def update1_dict_dict(space, w_dict, w_data):
+    iterator = w_data.iter()
+    while 1:
+        w_key, w_value = iterator.next()
+        if w_key is None:
+            break
+        w_dict.setitem(w_key, w_value)
+
+def init_or_update(space, w_dict, __args__, funcname):
+    w_src, w_kwds = __args__.parse_obj(
+            None, funcname,
+            init_signature, # signature
+            init_defaults)  # default argument
+    if w_src is not None:
+        update1(space, w_dict, w_src)
     if space.is_true(w_kwds):
-        from pypy.objspace.std.dicttype import update1
         update1(space, w_dict, w_kwds)
 
+def init__DictMulti(space, w_dict, __args__):
+    init_or_update(space, w_dict, __args__, 'dict')
+
+def dict_update__DictMulti(space, w_dict, __args__):
+    init_or_update(space, w_dict, __args__, 'dict.update')
+
 def getitem__DictMulti_ANY(space, w_dict, w_key):
     w_value = w_dict.getitem(w_key)
     if w_value is not None:
@@ -758,9 +778,8 @@
     return w_res
 
 def dict_copy__DictMulti(space, w_self):
-    from pypy.objspace.std.dicttype import update1
     w_new = W_DictMultiObject.allocate_and_init_instance(space)
-    update1(space, w_new, w_self)
+    update1_dict_dict(space, w_new, w_self)
     return w_new
 
 def dict_items__DictMulti(space, w_self):
@@ -791,6 +810,15 @@
     else:
         return w_default
 
+def dict_setdefault__DictMulti_ANY_ANY(space, w_dict, w_key, w_default):
+    # XXX should be more efficient, with only one dict lookup
+    w_value = w_dict.getitem(w_key)
+    if w_value is not None:
+        return w_value
+    else:
+        w_dict.setitem(w_key, w_default)
+        return w_default
+
 def dict_pop__DictMulti_ANY(space, w_dict, w_key, w_defaults):
     defaults = space.listview(w_defaults)
     len_defaults = len(defaults)
@@ -808,6 +836,19 @@
         w_dict.delitem(w_key)
         return w_item
 
+def dict_popitem__DictMulti(space, w_dict):
+    # XXX should somehow use the same trick as CPython: saving the index
+    # of the last popped item in the hash table, so that the next call to
+    # popitem() can be more efficient, instead of always starting from the
+    # beginning of the hash table.
+    iterator = w_dict.iter()
+    w_key, w_value = iterator.next()
+    if w_key is None:
+        raise OperationError(space.w_KeyError,
+                             space.wrap("popitem(): dictionary is empty"))
+    w_dict.delitem(w_key)
+    return space.newtuple([w_key, w_value])
+
 app = gateway.applevel('''
     def dictrepr(currently_in_repr, d):
         # Now we only handle one implementation of dicts, this one.

Modified: pypy/trunk/pypy/objspace/std/dicttype.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/dicttype.py	(original)
+++ pypy/trunk/pypy/objspace/std/dicttype.py	Tue Oct 26 17:05:48 2010
@@ -53,106 +53,21 @@
 # This can return when multimethods have been fixed
 #dict_str        = StdObjSpace.str
 
-# default application-level implementations for some operations
-# most of these (notably not popitem and update*) are overwritten
-# in dictmultiobject
-# gateway is imported in the stdtypedef module
-app = gateway.applevel('''
-
-    # in the following functions we use dict.__setitem__ instead of
-    # d[k]=...  because when a subclass of dict override __setitem__,
-    # CPython does not call it when doing builtin operations.  The
-    # same for other operations.
-
-    def update1(d, o):
-        if hasattr(o, 'keys'):
-            for k in o.keys():
-                dict.__setitem__(d, k, o[k])
-        else:
-            for k,v in o:
-                dict.__setitem__(d, k, v)
-
-    def update(d, *args, **kwargs):
-        len_args = len(args)
-        if len_args == 1:
-            update1(d, args[0])
-        elif len_args > 1:
-            raise TypeError("update takes at most 1 (non-keyword) argument")
-        if kwargs:
-            update1(d, kwargs)
-
-    def popitem(d):
-        for k in dict.iterkeys(d):
-            break
-        else:
-            raise KeyError("popitem(): dictionary is empty")
-        v = dict.__getitem__(d, k)
-        dict.__delitem__(d, k)
-        return k, v
-
-    def get(d, k, v=None):
-        if k in d:
-            return dict.__getitem__(d, k)
-        else:
-            return v
-
-    def setdefault(d, k, v=None):
-        if k in d:
-            return dict.__getitem__(d, k)
-        else:
-            dict.__setitem__(d, k, v)
-            return v
-
-    def pop(d, k, defaults):     # XXX defaults is actually *defaults
-        if len(defaults) > 1:
-            raise TypeError, "pop expected at most 2 arguments, got %d" % (
-                1 + len(defaults))
-        try:
-            v = dict.__getitem__(d, k)
-            dict.__delitem__(d, k)
-        except KeyError, e:
-            if defaults:
-                return defaults[0]
-            else:
-                raise e
-        return v
-
-    def iteritems(d):
-        return iter(dict.items(d))
-
-    def iterkeys(d):
-        return iter(dict.keys(d))
-
-    def itervalues(d):
-        return iter(dict.values(d))
-''', filename=__file__)
-
-dict_update__ANY             = app.interphook("update")
-dict_popitem__ANY            = app.interphook("popitem")
-dict_get__ANY_ANY_ANY        = app.interphook("get")
-dict_setdefault__ANY_ANY_ANY = app.interphook("setdefault")
-dict_pop__ANY_ANY            = app.interphook("pop")
-dict_iteritems__ANY          = app.interphook("iteritems")
-dict_iterkeys__ANY           = app.interphook("iterkeys")
-dict_itervalues__ANY         = app.interphook("itervalues")
-update1                      = app.interphook("update1")
-
 register_all(vars(), globals())
 
 @gateway.unwrap_spec(ObjSpace, W_Root, W_Root, W_Root)
 def descr_fromkeys(space, w_type, w_keys, w_fill=None):
+    from pypy.objspace.std.dictmultiobject import W_DictMultiObject
     if w_fill is None:
         w_fill = space.w_None
-    w_dict = space.call_function(w_type)
-    w_iter = space.iter(w_keys)
-    while True:
-        try:
-            w_key = space.next(w_iter)
-        except OperationError, e:
-            if not e.match(space, space.w_StopIteration):
-                raise
-            break
-        space.setitem(w_dict, w_key, w_fill)
+    if w_type is 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)
+    else:
+        w_dict = space.call_function(w_type)
+        for w_key in space.listview(w_keys):
+            space.setitem(w_dict, w_key, w_fill)
     return w_dict
 
 

Modified: pypy/trunk/pypy/objspace/std/frozensettype.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/frozensettype.py	(original)
+++ pypy/trunk/pypy/objspace/std/frozensettype.py	Tue Oct 26 17:05:48 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/trunk/pypy/objspace/std/setobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/setobject.py	(original)
+++ pypy/trunk/pypy/objspace/std/setobject.py	Tue Oct 26 17:05:48 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.listview(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/trunk/pypy/objspace/std/settype.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/settype.py	(original)
+++ pypy/trunk/pypy/objspace/std/settype.py	Tue Oct 26 17:05:48 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/trunk/pypy/objspace/std/test/test_dictmultiobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py	(original)
+++ pypy/trunk/pypy/objspace/std/test/test_dictmultiobject.py	Tue Oct 26 17:05:48 2010
@@ -238,6 +238,7 @@
         it1 = d.popitem()
         assert len(d) == 0
         assert (it!=it1) and (it1==(1,2) or it1==(3,4))
+        raises(KeyError, d.popitem)
     
     def test_setdefault(self):
         d = {1:2, 3:4}
@@ -446,7 +447,9 @@
         d1 = {}
         d2 = D(a='foo')
         d1.update(d2)
-        assert d1['a'] == 42 # fails on CPython, d1['a'] == 'foo'
+        assert d1['a'] == 'foo'
+        # a bit of an obscure case: now (from r78295) we get the same result
+        # as CPython does
 
     def test_index_keyerror_unpacking(self):
         d = {}

Modified: pypy/trunk/pypy/objspace/std/test/test_setobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/test/test_setobject.py	(original)
+++ pypy/trunk/pypy/objspace/std/test/test_setobject.py	Tue Oct 26 17:05:48 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'))
@@ -56,6 +57,11 @@
         b = a | set('abc')
         assert type(b) is subset
 
+    def test_union(self):
+        a = set([4, 5])
+        b = a.union([5, 7])
+        assert sorted(b) == [4, 5, 7]
+
     def test_compare(self):
         raises(TypeError, cmp, set('abc'), set('abd'))
         assert set('abc') != 'abc'



More information about the Pypy-commit mailing list