Author: Philip Jenvey <[email protected]>
Branch: 
Changeset: r64287:4f5876e9b069
Date: 2013-05-18 13:47 -0700
http://bitbucket.org/pypy/pypy/changeset/4f5876e9b069/

Log:    dictview fixes: o add missing right hand set like ops + tests o
        guard the comparisons w/ set like type checks o CPython viewvalues
        lacks __eq__ (though it likely shouldn't), kill it for now since
        it's tailored to SetLikeDictView/sets comparisons anyway

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
@@ -9,7 +9,7 @@
 from rpython.rlib import jit, rerased
 from rpython.rlib.debug import mark_dict_non_null
 from rpython.rlib.objectmodel import newlist_hint, r_dict, specialize
-from rpython.tool.sourcetools import func_with_new_name
+from rpython.tool.sourcetools import func_renamer, func_with_new_name
 
 
 UNROLL_CUTOFF = 5
@@ -1254,47 +1254,87 @@
         return space.wrap("%s(%s)" % (space.type(self).getname(space),
                                       space.str_w(w_repr)))
 
-    def descr_eq(self, space, w_otherview):
-        if not space.eq_w(space.len(self), space.len(w_otherview)):
-            return space.w_False
-
-        w_iter = space.iter(self)
-        while True:
-            try:
-                w_item = space.next(w_iter)
-            except OperationError, e:
-                if not e.match(space, space.w_StopIteration):
-                    raise
-                break
-            if not space.is_true(space.contains(w_otherview, w_item)):
-                return space.w_False
-        return space.w_True
-
     def descr_len(self, space):
         return space.len(self.w_dict)
 
+def _all_contained_in(space, w_dictview, w_other):
+    w_iter = space.iter(w_dictview)
+    while True:
+        try:
+            w_item = space.next(w_iter)
+        except OperationError, e:
+            if not e.match(space, space.w_StopIteration):
+                raise
+            break
+        if not space.is_true(space.contains(w_other, w_item)):
+            return space.w_False
+    return space.w_True
+
+def _is_set_like(w_other):
+    from pypy.objspace.std.setobject import W_BaseSetObject
+    return (isinstance(w_other, W_BaseSetObject) or
+            isinstance(w_other, SetLikeDictView))
+
 class SetLikeDictView(object):
     _mixin_ = True
 
-    def descr_sub(self, space, w_otherview):
-        w_set = space.call_function(space.w_set, self)
-        space.call_method(w_set, "difference_update", w_otherview)
-        return w_set
+    def descr_eq(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) == space.len_w(w_other):
+            return _all_contained_in(space, self, w_other)
+        return space.w_False
 
-    def descr_and(self, space, w_otherview):
-        w_set = space.call_function(space.w_set, self)
-        space.call_method(w_set, "intersection_update", w_otherview)
-        return w_set
+    def descr_ne(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        return space.not_(space.eq(self, w_other))
 
-    def descr_or(self, space, w_otherview):
-        w_set = space.call_function(space.w_set, self)
-        space.call_method(w_set, "update", w_otherview)
-        return w_set
+    def descr_lt(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) < space.len_w(w_other):
+            return _all_contained_in(space, self, w_other)
+        return space.w_False
 
-    def descr_xor(self, space, w_otherview):
-        w_set = space.call_function(space.w_set, self)
-        space.call_method(w_set, "symmetric_difference_update", w_otherview)
-        return w_set
+    def descr_le(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) <= space.len_w(w_other):
+            return _all_contained_in(space, self, w_other)
+        return space.w_False
+
+    def descr_gt(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) > space.len_w(w_other):
+            return _all_contained_in(space, w_other, self)
+        return space.w_False
+
+    def descr_ge(self, space, w_other):
+        if not _is_set_like(w_other):
+            return space.w_NotImplemented
+        if space.len_w(self) >= space.len_w(w_other):
+            return _all_contained_in(space, w_other, self)
+        return space.w_False
+
+    def _as_set_op(name, methname):
+        @func_renamer('descr_' + name)
+        def op(self, space, w_other):
+            w_set = space.call_function(space.w_set, self)
+            space.call_method(w_set, methname, w_other)
+            return w_set
+        @func_renamer('descr_r' + name)
+        def rop(self, space, w_other):
+            w_set = space.call_function(space.w_set, w_other)
+            space.call_method(w_set, methname, self)
+            return w_set
+        return op, rop
+
+    descr_sub, descr_rsub = _as_set_op('sub', 'difference_update')
+    descr_and, descr_rand = _as_set_op('and', 'intersection_update')
+    descr_or, descr_ror = _as_set_op('or', 'update')
+    descr_xor, descr_rxor = _as_set_op('xor', 'symmetric_difference_update')
 
 class W_DictViewItemsObject(W_DictViewObject, SetLikeDictView):
     def descr_iter(self, space):
@@ -1311,31 +1351,52 @@
 W_DictViewItemsObject.typedef = StdTypeDef(
     "dict_items",
     __repr__ = interp2app(W_DictViewItemsObject.descr_repr),
-    __eq__ = interp2app(W_DictViewItemsObject.descr_eq),
     __len__ = interp2app(W_DictViewItemsObject.descr_len),
     __iter__ = interp2app(W_DictViewItemsObject.descr_iter),
+
+    __eq__ = interp2app(W_DictViewItemsObject.descr_eq),
+    __ne__ = interp2app(W_DictViewItemsObject.descr_ne),
+    __lt__ = interp2app(W_DictViewItemsObject.descr_lt),
+    __le__ = interp2app(W_DictViewItemsObject.descr_le),
+    __gt__ = interp2app(W_DictViewItemsObject.descr_gt),
+    __ge__ = interp2app(W_DictViewItemsObject.descr_ge),
+
     __sub__ = interp2app(W_DictViewItemsObject.descr_sub),
+    __rsub__ = interp2app(W_DictViewItemsObject.descr_rsub),
     __and__ = interp2app(W_DictViewItemsObject.descr_and),
+    __rand__ = interp2app(W_DictViewItemsObject.descr_rand),
     __or__ = interp2app(W_DictViewItemsObject.descr_or),
-    __xor__ = interp2app(W_DictViewItemsObject.descr_xor)
+    __ror__ = interp2app(W_DictViewItemsObject.descr_ror),
+    __xor__ = interp2app(W_DictViewItemsObject.descr_xor),
+    __rxor__ = interp2app(W_DictViewItemsObject.descr_rxor),
     )
 
 W_DictViewKeysObject.typedef = StdTypeDef(
     "dict_keys",
     __repr__ = interp2app(W_DictViewKeysObject.descr_repr),
-    __eq__ = interp2app(W_DictViewKeysObject.descr_eq),
     __len__ = interp2app(W_DictViewKeysObject.descr_len),
     __iter__ = interp2app(W_DictViewKeysObject.descr_iter),
+
+    __eq__ = interp2app(W_DictViewKeysObject.descr_eq),
+    __ne__ = interp2app(W_DictViewKeysObject.descr_ne),
+    __lt__ = interp2app(W_DictViewKeysObject.descr_lt),
+    __le__ = interp2app(W_DictViewKeysObject.descr_le),
+    __gt__ = interp2app(W_DictViewKeysObject.descr_gt),
+    __ge__ = interp2app(W_DictViewKeysObject.descr_ge),
+
     __sub__ = interp2app(W_DictViewKeysObject.descr_sub),
+    __rsub__ = interp2app(W_DictViewKeysObject.descr_rsub),
     __and__ = interp2app(W_DictViewKeysObject.descr_and),
+    __rand__ = interp2app(W_DictViewKeysObject.descr_rand),
     __or__ = interp2app(W_DictViewKeysObject.descr_or),
-    __xor__ = interp2app(W_DictViewKeysObject.descr_xor)
+    __ror__ = interp2app(W_DictViewKeysObject.descr_ror),
+    __xor__ = interp2app(W_DictViewKeysObject.descr_xor),
+    __rxor__ = interp2app(W_DictViewKeysObject.descr_rxor),
     )
 
 W_DictViewValuesObject.typedef = StdTypeDef(
     "dict_values",
     __repr__ = interp2app(W_DictViewValuesObject.descr_repr),
-    __eq__ = interp2app(W_DictViewValuesObject.descr_eq),
     __len__ = interp2app(W_DictViewValuesObject.descr_len),
     __iter__ = interp2app(W_DictViewValuesObject.descr_iter),
     )
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
@@ -696,6 +696,7 @@
         assert d.viewkeys() == e.viewkeys()
         del e["a"]
         assert d.viewkeys() != e.viewkeys()
+        assert not d.viewkeys() == 42
 
     def test_dict_items(self):
         d = {1: 10, "a": "ABC"}
@@ -720,6 +721,7 @@
         assert d.viewitems() == e.viewitems()
         e["a"] = "def"
         assert d.viewitems() != e.viewitems()
+        assert not d.viewitems() == 42
 
     def test_dict_mixed_keys_items(self):
         d = {(1, 1): 11, (2, 2): 22}
@@ -732,6 +734,7 @@
         values = d.viewvalues()
         assert set(values) == set([10, "ABC"])
         assert len(values) == 2
+        assert not values == 42
 
     def test_dict_repr(self):
         d = {1: 10, "a": "ABC"}
@@ -813,6 +816,109 @@
         assert d1.viewitems() - d2.viewitems() == set([('a', 1)])
         assert d1.viewitems() - d3.viewitems() == set([('a', 1), ('b', 2)])
 
+    def test_keys_set_operations_any_type(self):
+        d = {1: u'a', 2: u'b', 3: u'c'}
+        assert d.viewkeys() & set([1]) == set([1])
+        assert d.viewkeys() & {1: u'foo'} == set([1])
+        assert d.viewkeys() & [1, 2] == set([1, 2])
+        #
+        assert set([1]) & d.viewkeys() == set([1])
+        assert {1: u'foo'} & d.viewkeys() == set([1])
+        assert [1, 2] & d.viewkeys() == set([1, 2])
+        #
+        assert d.viewkeys() - set([1]) == set([2, 3])
+        assert set([1, 4]) - d.viewkeys() == set([4])
+        #
+        assert d.viewkeys() == set([1, 2, 3])
+        # XXX: The following 4 commented out are CPython 2.7 bugs
+        #assert set([1, 2, 3]) == d.viewkeys()
+        assert d.viewkeys() == frozenset(set([1, 2, 3]))
+        #assert frozenset(set([1, 2, 3])) == d.viewkeys()
+        assert not d.viewkeys() != set([1, 2, 3])
+        #assert not set([1, 2, 3]) != d.viewkeys()
+        assert not d.viewkeys() != frozenset(set([1, 2, 3]))
+        #assert not frozenset(set([1, 2, 3])) != d.viewkeys()
+
+    def test_items_set_operations_any_type(self):
+        d = {1: u'a', 2: u'b', 3: u'c'}
+        assert d.viewitems() & set([(1, u'a')]) == set([(1, u'a')])
+        assert d.viewitems() & {(1, u'a'): u'foo'} == set([(1, u'a')])
+        assert d.viewitems() & [(1, u'a'), (2, u'b')] == set([(1, u'a'), (2, 
u'b')])
+        #
+        assert set([(1, u'a')]) & d.viewitems() == set([(1, u'a')])
+        assert {(1, u'a'): u'foo'} & d.viewitems() == set([(1, u'a')])
+        assert [(1, u'a'), (2, u'b')] & d.viewitems() == set([(1, u'a'), (2, 
u'b')])
+        #
+        assert d.viewitems() - set([(1, u'a')]) == set([(2, u'b'), (3, u'c')])
+        assert set([(1, u'a'), 4]) - d.viewitems() == set([4])
+        #
+        assert d.viewitems() == set([(1, u'a'), (2, u'b'), (3, u'c')])
+        # XXX: The following 4 commented out are CPython 2.7 bugs
+        #assert set([(1, u'a'), (2, u'b'), (3, u'c')]) == d.viewitems()
+        assert d.viewitems() == frozenset(set([(1, u'a'), (2, u'b'), (3, 
u'c')]))
+        #assert frozenset(set([(1, u'a'), (2, u'b'), (3, u'c')])) == 
d.viewitems()
+        assert not d.viewitems() != set([(1, u'a'), (2, u'b'), (3, u'c')])
+        #assert not set([(1, u'a'), (2, u'b'), (3, u'c')]) != d.viewitems()
+        assert not d.viewitems() != frozenset(set([(1, u'a'), (2, u'b'), (3, 
u'c')]))
+        #assert not frozenset(set([(1, u'a'), (2, u'b'), (3, u'c')])) != 
d.viewitems()
+
+    def test_dictviewset_unhashable_values(self):
+        class C:
+            def __eq__(self, other):
+                return True
+        d = {1: C()}
+        assert d.viewitems() <= d.viewitems()
+
+    def test_compare_keys_and_items(self):
+        d1 = {1: 2}
+        d2 = {(1, 2): 'foo'}
+        assert d1.viewitems() == d2.viewkeys()
+
+    def test_keys_items_contained(self):
+        def helper(fn):
+            empty = fn(dict())
+            empty2 = fn(dict())
+            smaller = fn({1:1, 2:2})
+            larger = fn({1:1, 2:2, 3:3})
+            larger2 = fn({1:1, 2:2, 3:3})
+            larger3 = fn({4:1, 2:2, 3:3})
+
+            assert smaller <  larger
+            assert smaller <= larger
+            assert larger >  smaller
+            assert larger >= smaller
+
+            assert not smaller >= larger
+            assert not smaller >  larger
+            assert not larger  <= smaller
+            assert not larger  <  smaller
+
+            assert not smaller <  larger3
+            assert not smaller <= larger3
+            assert not larger3 >  smaller
+            assert not larger3 >= smaller
+
+            # Inequality strictness
+            assert larger2 >= larger
+            assert larger2 <= larger
+            assert not larger2 > larger
+            assert not larger2 < larger
+
+            assert larger == larger2
+            assert smaller != larger
+
+            # There is an optimization on the zero-element case.
+            assert empty == empty2
+            assert not empty != empty2
+            assert not empty == smaller
+            assert empty != smaller
+
+            # With the same size, an elementwise compare happens
+            assert larger != larger3
+            assert not larger == larger3
+
+        helper(lambda x: x.viewkeys())
+        helper(lambda x: x.viewitems())
 
 class AppTestStrategies(object):
     def setup_class(cls):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to