[pypy-svn] r24976 - in pypy/dist/pypy/objspace/std: . test

stephan at codespeak.net stephan at codespeak.net
Fri Mar 24 19:51:29 CET 2006


Author: stephan
Date: Fri Mar 24 19:51:26 2006
New Revision: 24976

Added:
   pypy/dist/pypy/objspace/std/setobject.py
   pypy/dist/pypy/objspace/std/settype.py
Modified:
   pypy/dist/pypy/objspace/std/model.py
   pypy/dist/pypy/objspace/std/objspace.py
   pypy/dist/pypy/objspace/std/test/helper.py
Log:
initial checkin of set/frozenset implementation for std objspace.
Since there are no tests yet (yes, I know), the WITHSET switch needs
to be set to 'True' in order to use native sets in pypy.


Modified: pypy/dist/pypy/objspace/std/model.py
==============================================================================
--- pypy/dist/pypy/objspace/std/model.py	(original)
+++ pypy/dist/pypy/objspace/std/model.py	Fri Mar 24 19:51:26 2006
@@ -9,6 +9,7 @@
 import pypy.interpreter.special
 
 WITHCOMPLEX = False
+WITHSET = False
 
 class StdTypeModel:
 
@@ -22,6 +23,9 @@
             from pypy.objspace.std.floattype  import float_typedef
             if WITHCOMPLEX:
                 from pypy.objspace.std.complextype  import complex_typedef
+            if WITHSET:
+                from pypy.objspace.std.settype import set_typedef
+                from pypy.objspace.std.settype import frozenset_typedef
             from pypy.objspace.std.tupletype  import tuple_typedef
             from pypy.objspace.std.listtype   import list_typedef
             from pypy.objspace.std.dicttype   import dict_typedef
@@ -46,6 +50,8 @@
         from pypy.objspace.std import floatobject
         if WITHCOMPLEX:
             from pypy.objspace.std import complexobject
+        if WITHSET:
+            from pypy.objspace.std import setobject
         from pypy.objspace.std import tupleobject
         from pypy.objspace.std import listobject
         from pypy.objspace.std import dictobject
@@ -68,7 +74,6 @@
             boolobject.W_BoolObject: [],
             intobject.W_IntObject: [],
             floatobject.W_FloatObject: [],
-            #complexobject.W_ComplexObject: [],
             tupleobject.W_TupleObject: [],
             listobject.W_ListObject: [],
             dictobject.W_DictObject: [],
@@ -87,6 +92,9 @@
             }
         if WITHCOMPLEX:
             self.typeorder[complexobject.W_ComplexObject] = []
+        if WITHSET:
+            self.typeorder[setobject.W_SetObject] = []
+            self.typeorder[setobject.W_FrozensetObject] = []
         for type in self.typeorder:
             self.typeorder[type].append((type, None))
 

Modified: pypy/dist/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/std/objspace.py	(original)
+++ pypy/dist/pypy/objspace/std/objspace.py	Fri Mar 24 19:51:26 2006
@@ -6,7 +6,8 @@
 from pypy.interpreter.gateway import PyPyCacheDir
 from pypy.tool.cache import Cache 
 from pypy.tool.sourcetools import func_with_new_name
-from pypy.objspace.std.model import W_Object, UnwrapError, WITHCOMPLEX
+from pypy.objspace.std.model import W_Object, UnwrapError
+from pypy.objspace.std.model import WITHCOMPLEX, WITHSET
 from pypy.objspace.std.model import W_ANY, StdObjSpaceMultiMethod, StdTypeModel
 from pypy.objspace.std.multimethod import FailedToImplement
 from pypy.objspace.descroperation import DescrOperation
@@ -16,6 +17,19 @@
 import os
 import __builtin__
 
+#check for sets
+try:
+    s = set()
+    del s
+except NameError:
+    try:
+        from sets import Set as set
+        from sets import ImmutableSet as frozenset
+    except ImportError:
+        class DummySet(object):pass
+        set = DummySet
+        frozenset = DummySet
+
 _registered_implementations = {}
 def registerimplementation(implcls):
     # hint to objspace.std.model to register the implementation class
@@ -285,15 +299,25 @@
                 return self.call_function(c,
                                           self.wrap(x.real), 
                                           self.wrap(x.imag))
-
         # SD disable for native complex
         #if isinstance(x, complex):
             # XXX is this right?   YYY no, this is wrong right now  (CT)
             # ZZZ hum, seems necessary for complex literals in co_consts (AR)
-            c = self.builtin.get('complex') 
+            # c = self.builtin.get('complex') 
         #    return self.call_function(c,
         #                              self.wrap(x.real), 
         #                              self.wrap(x.imag))
+
+        if isinstance(x, set):
+            if WITHSET:
+                wrappeditems = [self.wrap(item) for item in x]
+                return W_SetObject(self, wrappeditems)
+
+        if isinstance(x, frozenset):
+            if WITHSET:
+                wrappeditems = [self.wrap(item) for item in x]
+                return W_FrozensetObject(self, wrappeditems)
+
         if x is __builtin__.Ellipsis:
             # '__builtin__.Ellipsis' avoids confusion with special.Ellipsis
             return self.w_Ellipsis
@@ -340,6 +364,13 @@
         def newcomplex(self, realval, imagval):
             return W_ComplexObject(self, realval, imagval)
 
+    if WITHSET:
+        def newset(self, list_w):
+            return W_SetObject(self, list_w)
+
+        def newfrozenset(self, list_w):
+            return W_FrozensetObject(self, list_w)
+
     def newlong(self, val): # val is an int
         return W_LongObject.fromint(self, val)
 

Added: pypy/dist/pypy/objspace/std/setobject.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/std/setobject.py	Fri Mar 24 19:51:26 2006
@@ -0,0 +1,161 @@
+from pypy.objspace.std.objspace import W_Object, OperationError
+from pypy.objspace.std.objspace import registerimplementation, register_all
+from pypy.objspace.std.model import WITHSET
+from pypy.objspace.std.stdtypedef import StdObjSpaceMultiMethod
+from pypy.rpython.objectmodel import r_dict
+from pypy.interpreter import gateway
+
+def _set_init(w_self, space, wrappeditems):
+    W_Object.__init__(w_self, space)
+    w_self.data = data = r_dict(space.eq_w, space.hash_w)
+    if space.is_true(space.isinstance(wrappeditems, space.w_frozenset)):
+        data.update(wrappeditems.data)
+    elif space.is_true(space.isinstance(wrappeditems, space.w_set)):
+        data.update(wrappeditems.data)
+    else:
+        iterable_w = space.unpackiterable(wrappeditems)
+        for w_item in iterable_w:
+            w_self.data[w_item] = space.w_True
+
+
+class W_SetObject(W_Object):
+    from pypy.objspace.std.settype import set_typedef as typedef
+
+    def __init__(w_self, space, wrappeditems):
+        _set_init(w_self, space, wrappeditems)
+
+    def __repr__(w_self):
+        """representation for debugging purposes"""
+        reprlist = [repr(w_item) for w_item in w_self.data.keys()]
+        return "<%s(%s)>" % (w_self.__class__.__name__, ', '.join(reprlist))
+
+class W_FrozensetObject(W_Object):
+    from pypy.objspace.std.settype import frozenset_typedef as typedef
+
+    def __init__(w_self, space, wrappeditems):
+        _set_init(w_self, space, wrappeditems)
+
+registerimplementation(W_SetObject)
+registerimplementation(W_FrozensetObject)
+
+app = gateway.applevel("""
+    def and__Set_Set(s, o):
+        return s.intersection(o)
+
+    def ne__Set_Set(s, o):
+        return not s == o
+
+    def ge__Set_Set(s, o):
+        return s.issuperset(o)
+
+    def gt__Set_Set(s, o):
+        return s != o and s.issuperset(o)
+
+    def le__Set_Set(s, o):
+        return s.issubset(o)
+
+    def lt__Set_Set(s, o):
+        return s != o and s.issubset(o)
+
+    def cmp__Set_Set(s, o):
+        raise TypeError('cannot compare sets using cmp()')
+
+    def or__Set_Set(s, o):
+        return s.union(o)
+
+    def xor__Set_Set(s, o):
+        return s.symmetric_difference(o)
+
+    def repr__Set(s):
+        return 'set(%s)' % [x for x in s]
+
+    def repr__Frozenset(s):
+        return 'frozenset(%s)' % [x for x in s]
+
+    def sub__Set_Set(s, o):
+        return s.difference(o)
+
+    def isub__Set_Set(s, o):
+        s.difference_update(o)
+        return s
+
+    def ior__Set_Set(s, o):
+        s.update(o)
+        return s
+
+    def iand__Set_Set(s, o):
+        s.intersection_update(o)
+        return s
+
+    def ixor__Set_Set(s, o):
+        s.symmetric_difference_update(o)
+        return s
+
+""", filename=__file__)
+
+and__Set_Set = app.interphook("and__Set_Set")
+and__Set_Frozenset = and__Set_Set
+and__Frozenset_Set = and__Set_Set
+and__Frozenset_Frozenset = and__Set_Set
+
+ne__Set_Set = app.interphook("ne__Set_Set")
+ne__Set_Frozenset = ne__Set_Set
+ne__Frozenset_Set = ne__Set_Set
+ne__Frozenset_Frozenset = ne__Set_Set
+
+ge__Set_Set = app.interphook("ge__Set_Set")
+ge__Set_Frozenset = ge__Set_Set
+ge__Frozenset_Set = ge__Set_Set
+ge__Frozenset_Frozenset = ge__Set_Set
+
+le__Set_Set = app.interphook("le__Set_Set")
+le__Set_Frozenset = le__Set_Set
+le__Frozenset_Set = le__Set_Set
+le__Frozenset_Frozenset = le__Set_Set
+
+gt__Set_Set = app.interphook("gt__Set_Set")
+gt__Set_Frozenset = gt__Set_Set
+gt__Frozenset_Set = gt__Set_Set
+gt__Frozenset_Frozenset = gt__Set_Set
+
+lt__Set_Set = app.interphook("lt__Set_Set")
+lt__Set_Frozenset = lt__Set_Set
+lt__Frozenset_Set = lt__Set_Set
+lt__Frozenset_Frozenset = lt__Set_Set
+
+cmp__Set_Set = app.interphook("cmp__Set_Set")
+cmp__Set_Frozenset = cmp__Set_Set
+cmp__Frozenset_Frozenset = cmp__Set_Set
+cmp__Frozenset_Set = cmp__Set_Set
+
+or__Set_Set = app.interphook("or__Set_Set")
+or__Set_Frozenset = or__Set_Set
+or__Frozenset_Set = or__Set_Set
+or__Frozenset_Frozenset = or__Set_Set
+
+xor__Set_Set = app.interphook("xor__Set_Set")
+xor__Set_Frozenset = xor__Set_Set
+xor__Frozenset_Set = xor__Set_Set
+xor__Frozenset_Frozenset = xor__Set_Set
+
+repr__Set = app.interphook('repr__Set')
+repr__Frozenset = app.interphook('repr__Frozenset')
+
+sub__Set_Set = app.interphook('sub__Set_Set')
+sub__Set_Frozenset = sub__Set_Set
+sub__Frozenset_Set = sub__Set_Set
+sub__Frozenset_Frozenset = sub__Set_Set
+
+inplace_sub__Set_Set = app.interphook('isub__Set_Set')
+inplace_sub__Set_Frozenset = inplace_sub__Set_Set
+
+inplace_or__Set_Set = app.interphook('ior__Set_Set')
+inplace_or__Set_Frozenset = inplace_or__Set_Set
+
+inplace_and__Set_Set = app.interphook('iand__Set_Set')
+inplace_and__Set_Frozenset = inplace_and__Set_Set
+
+inplace_xor__Set_Set = app.interphook('ixor__Set_Set')
+inplace_xor__Set_Frozenset = inplace_xor__Set_Set
+
+register_all(vars())

Added: pypy/dist/pypy/objspace/std/settype.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/std/settype.py	Fri Mar 24 19:51:26 2006
@@ -0,0 +1,310 @@
+from pypy.interpreter.error import OperationError
+from pypy.objspace.std.objspace import register_all
+from pypy.objspace.std.stdtypedef import StdTypeDef, newmethod
+from pypy.objspace.std.stdtypedef import StdObjSpaceMultiMethod
+from pypy.interpreter.gateway import NoneNotWrapped
+from pypy.interpreter import gateway
+from pypy.objspace.std.model import WITHSET
+
+def descr__set__new__(space, w_settype, w_iterable=NoneNotWrapped):
+    from pypy.objspace.std.setobject import W_SetObject
+    if w_iterable is None:
+        w_iterable = space.newtuple([])
+    elif (space.is_w(w_settype, space.w_set) and
+            space.is_w(space.type(w_iterable), space.w_set)):
+        return w_iterable
+    w_obj = space.allocate_instance(W_SetObject, w_settype)
+    W_SetObject.__init__(w_obj, space, w_iterable)
+
+    return w_obj
+
+def descr__frozenset__new__(space, w_frozensettype, w_iterable=NoneNotWrapped):
+    from pypy.objspace.std.setobject import W_FrozensetObject
+    if w_iterable is None:
+        w_iterable = space.newtuple([])
+    elif (space.is_w(w_frozensettype, space.w_frozenset) and
+            space.is_w(space.type(w_iterable), space.w_frozenset)):
+        return w_iterable
+    w_obj = space.allocate_instance(W_FrozensetObject, w_frozensettype)
+    W_FrozensetObject.__init__(w_obj, space, w_iterable)
+
+    return w_obj
+
+# some helper functions
+
+def _extract_data_dict(space, w_left, w_right):
+    assert (space.is_true(space.isinstance(w_left, space.w_set)) or 
+        space.is_true(space.isinstance(w_left, space.w_frozenset)))
+    if not (space.is_true(space.isinstance(w_right, space.w_set)) or 
+            space.is_true(space.isinstance(w_right, space.w_frozenset))):
+        w_right = space.newset(w_right)
+
+    return w_left.data, w_right.data
+
+def _dict_to_set(space, rpdict):
+    return space.newset(space.newtuple(rpdict.keys()))
+
+def _dict_to_frozenset(space, rpdict):
+    return space.newfrozenset(space.newtuple(rpdict.keys()))
+
+# helper functions for set operation on dicts
+
+def _union_dict(space, ldict, rdict, isupdate):
+    if isupdate:
+        ld = ldict
+    else:
+        ld = ldict.copy()
+    ld.update(rdict)
+    return ld, rdict
+
+def _difference_dict(space, ldict, rdict, isupdate):
+    if isupdate:
+        ld = ldict
+    else:
+        ld = ldict.copy()
+    del_list_w = []
+    for w_key in ld.iterkeys():
+        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(space, ldict, rdict, isupdate):
+    if isupdate:
+        ld = ldict
+    else:
+        ld = ldict.copy()
+    del_list_w = []
+    for w_key in ld.iterkeys():
+        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
+
+
+def _symmetric_difference_dict(space, ldict, rdict, isupdate):
+    if isupdate:
+        ld = ldict
+    else:
+        ld = ldict.copy()
+    del_list_w = []
+    add_list_w = []
+    for w_key in ld.iterkeys():
+        if w_key in rdict:
+            del_list_w.append(w_key)
+
+    for w_key in rdict.iterkeys():
+        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] = space.w_True
+
+    return ld, rdict
+
+def descr_update(space, w_self, w_iterable):
+    """Update a set with the union of itself and another."""
+    ld, rd = _extract_data_dict(space, w_self, w_iterable)
+    new_ld, rd = _union_dict(space, ld, rd, True)
+    return space.w_None
+
+def descr_add(space, w_self, w_other):
+    """Add an element to a set.
+
+    This has no effect if the element is already present.
+    """
+
+    w_self.data[w_other] = space.w_True
+
+def descr_copy_s(space, w_self):
+    return space.newset(w_self)
+
+def descr_copy_fs(space, w_self):
+    return space.newfrozenset(w_self)
+
+def descr_clear(space, w_self):
+    w_self.data.clear()
+
+def descr_difference_s(space, w_self, w_other):
+    ld, rd = _extract_data_dict(space, w_self, w_other)
+    new_ld, rd = _difference_dict(space, ld, rd, False)
+    return _dict_to_set(space, new_ld)
+
+def descr_difference_fs(space, w_self, w_other):
+    ld, rd = _extract_data_dict(space, w_self, w_other)
+    new_ld, rd = _difference_dict(space, ld, rd, False)
+    return _dict_to_frozenset(space, new_ld)
+
+
+def descr_difference_update(space, w_self, w_other):
+    ld, rd = _extract_data_dict(space, w_self, w_other)
+    new_ld, rd = _difference_dict(space, ld, rd, True)
+    return space.w_None
+
+def descr__set__eq__(space, w_self, w_other):
+    if space.is_w(w_self, w_other):
+        return space.w_True
+
+    if len(w_self.data) != len(w_other.data):
+        return space.w_False
+
+    for w_key in w_self.data.iterkeys():
+        if w_key not in w_other.data:
+            return space.w_False
+    return space.w_True
+
+def descr__set__contains__(space, w_self, w_other):
+    return space.newbool(w_other in w_self.data)
+
+def descr_issubset(space, w_self, w_other):
+    if space.is_w(w_self, w_other):
+        return space.w_True
+
+    if len(w_self.data) > len(w_other.data):
+        return space.w_False
+
+    for w_key in w_self.data:
+        if w_key not in w_other.data:
+            return space.w_False
+    return space.w_True
+
+def descr_issuperset(space, w_self, w_other):
+    if space.is_w(w_self, w_other):
+        return space.w_True
+
+    if len(w_self.data) < len(w_other.data):
+        return space.w_False
+
+    for w_key in w_other.data:
+        if w_key not in w_self.data:
+            return space.w_False
+    return space.w_True
+
+def descr_discard(space, w_self, w_item):
+    if w_item in w_self.data:
+        del w_self.data[w_item]
+    
+def descr_remove(space, w_self, w_item):
+    try:
+        del w_self.data[w_item]
+    except KeyError:
+        raise OperationError(space.w_KeyError,
+                space.call_method(w_item,'__repr__'))
+
+def descr__set__hash__(space, w_self):
+    raise OperationError(space.w_TypeError,
+            space.wrap('set objects are unhashable'))
+
+def descr_pop(space, w_self):
+    if len(w_self.data) == 0:
+        raise OperationError(space.w_KeyError,
+                                space.wrap('pop from an empty set'))
+    w_keys = w_self.data.keys()
+    w_value = w_keys[0]
+    del w_self.data[w_value]
+
+    return w_value
+
+def descr_intersection_s(space, w_self, w_other):
+    ld, rd = _extract_data_dict(space, w_self, w_other)
+    new_ld, rd = _intersection_dict(space, ld, rd, False)
+    return _dict_to_set(space, new_ld)
+
+def descr_intersection_fs(space, w_self, w_other):
+    ld, rd = _extract_data_dict(space, w_self, w_other)
+    new_ld, rd = _intersection_dict(space, ld, rd, False)
+    return _dict_to_frozenset(space, new_ld)
+
+def descr_intersection_update(space, w_self, w_other):
+    ld, rd = _extract_data_dict(space, w_self, w_other)
+    new_ld, rd = _intersection_dict(space, ld, rd, True)
+    return space.w_None
+
+def descr_symmetric_difference_s(space, w_self, w_other):
+    ld, rd = _extract_data_dict(space, w_self, w_other)
+    new_ld, rd = _symmetric_difference_dict(space, ld, rd, False)
+    return _dict_to_set(space, new_ld)
+
+def descr_symmetric_difference_fs(space, w_self, w_other):
+    ld, rd = _extract_data_dict(space, w_self, w_other)
+    new_ld, rd = _symmetric_difference_dict(space, ld, rd, False)
+    return _dict_to_frozenset(space, new_ld)
+
+def descr_symmetric_difference_update(space, w_self, w_other):
+    ld, rd = _extract_data_dict(space, w_self, w_other)
+    new_ld, rd = _symmetric_difference_dict(space, ld, rd, True)
+    return space.w_None
+
+def descr_union_s(space, w_self, w_other):
+    ld, rd = _extract_data_dict(space, w_self, w_other)
+    new_ld, rd = _union_dict(space, ld, rd, False)
+    return _dict_to_set(space, new_ld)
+
+def descr_union_fs(space, w_self, w_other):
+    ld, rd = _extract_data_dict(space, w_self, w_other)
+    new_ld, rd = _union_dict(space, ld, rd, False)
+    return _dict_to_frozenset(space, new_ld)
+
+def descr__set__len__(space, w_self):
+    return space.newint(len(w_self.data))
+
+def descr__set__iter__(space, w_self):
+    from pypy.objspace.std import iterobject
+    return iterobject.W_SeqIterObject(space, 
+                                        space.newtuple(w_self.data.keys()))
+
+set_typedef = StdTypeDef("set",
+    __doc__ = """set(iterable) --> set object
+
+Build an unordered collection.""",
+    __new__ = newmethod(descr__set__new__),
+    __eq__ = newmethod(descr__set__eq__),
+    __contains__ = newmethod(descr__set__contains__),
+    __len__ = newmethod(descr__set__len__),
+    __iter__ = newmethod(descr__set__iter__),
+    __hash__ = newmethod(descr__set__hash__),
+    add = newmethod(descr_add),
+    clear = newmethod(descr_clear),
+    copy = newmethod(descr_copy_s),
+    difference = newmethod(descr_difference_s),
+    difference_update = newmethod(descr_difference_update),
+    discard = newmethod(descr_discard),
+    intersection = newmethod(descr_intersection_s),
+    intersection_update = newmethod(descr_intersection_update),
+    issubset = newmethod(descr_issubset),
+    issuperset = newmethod(descr_issuperset),
+    pop = newmethod(descr_pop),
+    remove = newmethod(descr_remove),
+    symmetric_difference = newmethod(descr_symmetric_difference_s),
+    symmetric_difference_update = newmethod(descr_symmetric_difference_update),
+    union = newmethod(descr_union_s),
+    update = newmethod(descr_update),
+    )
+
+#set_typedef.registermethods(globals())
+
+frozenset_typedef = StdTypeDef("frozenset",
+    __doc__ = """frozenset(iterable) --> frozenset object
+
+Build an immutable unordered collection.""",
+    __new__ = newmethod(descr__frozenset__new__),
+    __eq__ = newmethod(descr__set__eq__),
+    __contains__ = newmethod(descr__set__contains__),
+    __len__ = newmethod(descr__set__len__),
+    __iter__ = newmethod(descr__set__iter__),
+    copy = newmethod(descr_copy_fs),
+    difference = newmethod(descr_difference_fs),
+    intersection = newmethod(descr_intersection_fs),
+    issubset = newmethod(descr_issubset),
+    issuperset = newmethod(descr_issuperset),
+    symmetric_difference = newmethod(descr_symmetric_difference_fs),
+    union = newmethod(descr_union_fs),
+    )

Modified: pypy/dist/pypy/objspace/std/test/helper.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/helper.py	(original)
+++ pypy/dist/pypy/objspace/std/test/helper.py	Fri Mar 24 19:51:26 2006
@@ -1,5 +1,3 @@
-EPS = 1e-9
-
 def raises(excp, func, *args):
     try:
         func(*args)
@@ -12,6 +10,13 @@
 def assertNotEqual(a, b):
     assert a != b
 
+def assertIs(a, b):
+    assert a is b
+
+# complex specific tests
+
+EPS = 1e-9
+
 def assertAlmostEqual(a, b):
     if isinstance(a, complex):
         if isinstance(b, complex):
@@ -44,8 +49,6 @@
     assertCloseAbs(x.real, y.real, eps)
     assertCloseAbs(x.imag, y.imag, eps)
 
-def assertIs(a, b):
-    assert a is b
 
 def check_div(x, y):
     """Compute complex z=x*y, and check that z/x==y and z/y==x."""



More information about the Pypy-commit mailing list