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