diff options
Diffstat (limited to 'Lib/test/test_dict.py')
-rw-r--r-- | Lib/test/test_dict.py | 223 |
1 files changed, 163 insertions, 60 deletions
diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 0840f59799b..9666f9a31cf 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -1,11 +1,21 @@ import unittest -from test import test_support +from test import support -import UserDict, random, string +import collections, random, string import gc, weakref class DictTest(unittest.TestCase): + + def test_invalid_keyword_arguments(self): + class Custom(dict): + pass + for invalid in {1 : 2}, Custom({1 : 2}): + with self.assertRaises(TypeError): + dict(**invalid) + with self.assertRaises(TypeError): + {}.update(**invalid) + def test_constructor(self): # calling built-in types without argument must return empty self.assertEqual(dict(), {}) @@ -15,7 +25,7 @@ class DictTest(unittest.TestCase): # check literal constructor for different sized dicts # (to exercise the BUILD_MAP oparg). for n in (0, 1, 6, 256, 400): - items = [(''.join(random.sample(string.letters, 8)), i) + items = [(''.join(random.sample(string.ascii_letters, 8)), i) for i in range(n)] random.shuffle(items) formatted_items = ('{!r}: {:d}'.format(k, v) for k, v in items) @@ -30,40 +40,30 @@ class DictTest(unittest.TestCase): def test_keys(self): d = {} - self.assertEqual(d.keys(), []) + self.assertEqual(set(d.keys()), set()) d = {'a': 1, 'b': 2} k = d.keys() - self.assertTrue(d.has_key('a')) - self.assertTrue(d.has_key('b')) - + self.assertIn('a', d) + self.assertIn('b', d) self.assertRaises(TypeError, d.keys, None) + self.assertEqual(repr(dict(a=1).keys()), "dict_keys(['a'])") def test_values(self): d = {} - self.assertEqual(d.values(), []) + self.assertEqual(set(d.values()), set()) d = {1:2} - self.assertEqual(d.values(), [2]) - + self.assertEqual(set(d.values()), {2}) self.assertRaises(TypeError, d.values, None) + self.assertEqual(repr(dict(a=1).values()), "dict_values([1])") def test_items(self): d = {} - self.assertEqual(d.items(), []) + self.assertEqual(set(d.items()), set()) d = {1:2} - self.assertEqual(d.items(), [(1, 2)]) - + self.assertEqual(set(d.items()), {(1, 2)}) self.assertRaises(TypeError, d.items, None) - - def test_has_key(self): - d = {} - self.assertFalse(d.has_key('a')) - d = {'a': 1, 'b': 2} - k = d.keys() - k.sort() - self.assertEqual(k, ['a', 'b']) - - self.assertRaises(TypeError, d.has_key) + self.assertEqual(repr(dict(a=1).items()), "dict_items([('a', 1)])") def test_contains(self): d = {} @@ -166,7 +166,7 @@ class DictTest(unittest.TestCase): self.i = 1 def __iter__(self): return self - def next(self): + def __next__(self): if self.i: self.i = 0 return 'a' @@ -183,7 +183,7 @@ class DictTest(unittest.TestCase): self.i = ord('a') def __iter__(self): return self - def next(self): + def __next__(self): if self.i <= ord('z'): rtn = chr(self.i) self.i += 1 @@ -197,7 +197,7 @@ class DictTest(unittest.TestCase): class badseq(object): def __iter__(self): return self - def next(self): + def __next__(self): raise Exc() self.assertRaises(Exc, {}.update, badseq()) @@ -222,10 +222,10 @@ class DictTest(unittest.TestCase): self.assertIsInstance(dictlike().fromkeys('a'), dictlike) class mydict(dict): def __new__(cls): - return UserDict.UserDict() + return collections.UserDict() ud = mydict.fromkeys('ab') self.assertEqual(ud, {'a':None, 'b':None}) - self.assertIsInstance(ud, UserDict.UserDict) + self.assertIsInstance(ud, collections.UserDict) self.assertRaises(TypeError, dict.fromkeys) class Exc(Exception): pass @@ -239,7 +239,7 @@ class DictTest(unittest.TestCase): class BadSeq(object): def __iter__(self): return self - def next(self): + def __next__(self): raise Exc() self.assertRaises(Exc, dict.fromkeys, BadSeq()) @@ -366,13 +366,6 @@ class DictTest(unittest.TestCase): self.assertRaises(KeyError, d.pop, k) - # verify longs/ints get same value when key > 32 bits - # (for 64-bit archs). See SF bug #689659. - x = 4503599627370496L - y = 4503599627370496 - h = {x: 'anything', y: 'something else'} - self.assertEqual(h[x], h[y]) - self.assertEqual(d.pop(k, v), v) d[k] = v self.assertEqual(d.pop(k, 1), v) @@ -420,9 +413,9 @@ class DictTest(unittest.TestCase): d = {1: BadRepr()} self.assertRaises(Exc, repr, d) - def test_le(self): - self.assertFalse({} < {}) - self.assertFalse({1: 2} < {1L: 2L}) + def test_eq(self): + self.assertEqual({}, {}) + self.assertEqual({1: 2}, {1: 2}) class Exc(Exception): pass @@ -430,13 +423,125 @@ class DictTest(unittest.TestCase): def __eq__(self, other): raise Exc() def __hash__(self): - return 42 + return 1 d1 = {BadCmp(): 1} d2 = {1: 1} with self.assertRaises(Exc): - d1 < d2 + d1 == d2 + + def test_keys_contained(self): + self.helper_keys_contained(lambda x: x.keys()) + self.helper_keys_contained(lambda x: x.items()) + + def helper_keys_contained(self, fn): + # Test rich comparisons against dict key views, which should behave the + # same as sets. + 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}) + + self.assertTrue(smaller < larger) + self.assertTrue(smaller <= larger) + self.assertTrue(larger > smaller) + self.assertTrue(larger >= smaller) + + self.assertFalse(smaller >= larger) + self.assertFalse(smaller > larger) + self.assertFalse(larger <= smaller) + self.assertFalse(larger < smaller) + + self.assertFalse(smaller < larger3) + self.assertFalse(smaller <= larger3) + self.assertFalse(larger3 > smaller) + self.assertFalse(larger3 >= smaller) + + # Inequality strictness + self.assertTrue(larger2 >= larger) + self.assertTrue(larger2 <= larger) + self.assertFalse(larger2 > larger) + self.assertFalse(larger2 < larger) + + self.assertTrue(larger == larger2) + self.assertTrue(smaller != larger) + + # There is an optimization on the zero-element case. + self.assertTrue(empty == empty2) + self.assertFalse(empty != empty2) + self.assertFalse(empty == smaller) + self.assertTrue(empty != smaller) + + # With the same size, an elementwise compare happens + self.assertTrue(larger != larger3) + self.assertFalse(larger == larger3) + + def test_errors_in_view_containment_check(self): + class C: + def __eq__(self, other): + raise RuntimeError + + d1 = {1: C()} + d2 = {1: C()} + with self.assertRaises(RuntimeError): + d1.items() == d2.items() + with self.assertRaises(RuntimeError): + d1.items() != d2.items() + with self.assertRaises(RuntimeError): + d1.items() <= d2.items() + with self.assertRaises(RuntimeError): + d1.items() >= d2.items() + + d3 = {1: C(), 2: C()} + with self.assertRaises(RuntimeError): + d2.items() < d3.items() + with self.assertRaises(RuntimeError): + d3.items() > d2.items() + + def test_dictview_set_operations_on_keys(self): + k1 = {1:1, 2:2}.keys() + k2 = {1:1, 2:2, 3:3}.keys() + k3 = {4:4}.keys() + + self.assertEqual(k1 - k2, set()) + self.assertEqual(k1 - k3, {1,2}) + self.assertEqual(k2 - k1, {3}) + self.assertEqual(k3 - k1, {4}) + self.assertEqual(k1 & k2, {1,2}) + self.assertEqual(k1 & k3, set()) + self.assertEqual(k1 | k2, {1,2,3}) + self.assertEqual(k1 ^ k2, {3}) + self.assertEqual(k1 ^ k3, {1,2,4}) + + def test_dictview_set_operations_on_items(self): + k1 = {1:1, 2:2}.items() + k2 = {1:1, 2:2, 3:3}.items() + k3 = {4:4}.items() + + self.assertEqual(k1 - k2, set()) + self.assertEqual(k1 - k3, {(1,1), (2,2)}) + self.assertEqual(k2 - k1, {(3,3)}) + self.assertEqual(k3 - k1, {(4,4)}) + self.assertEqual(k1 & k2, {(1,1), (2,2)}) + self.assertEqual(k1 & k3, set()) + self.assertEqual(k1 | k2, {(1,1), (2,2), (3,3)}) + self.assertEqual(k1 ^ k2, {(3,3)}) + self.assertEqual(k1 ^ k3, {(1,1), (2,2), (4,4)}) + + def test_dictview_mixed_set_operations(self): + # Just a few for .keys() + self.assertTrue({1:1}.keys() == {1}) + self.assertTrue({1} == {1:1}.keys()) + self.assertEqual({1:1}.keys() | {2}, {1, 2}) + self.assertEqual({2} | {1:1}.keys(), {1, 2}) + # And a few for .items() + self.assertTrue({1:1}.items() == {(1,1)}) + self.assertTrue({(1,1)} == {1:1}.items()) + self.assertEqual({1:1}.items() | {2}, {(1,1), 2}) + self.assertEqual({2} | {1:1}.items(), {(1,1), 2}) def test_missing(self): # Make sure dict doesn't have a __missing__ method @@ -489,7 +594,7 @@ class DictTest(unittest.TestCase): self.assertEqual(c.exception.args, ((1,),)) def test_bad_key(self): - # Dictionary lookups should fail if __cmp__() raises an exception. + # Dictionary lookups should fail if __eq__() raises an exception. class CustomException(Exception): pass @@ -497,7 +602,7 @@ class DictTest(unittest.TestCase): def __hash__(self): return hash(self.__class__) - def __cmp__(self, other): + def __eq__(self, other): if isinstance(other, self.__class__): raise CustomException return other @@ -509,13 +614,12 @@ class DictTest(unittest.TestCase): for stmt in ['d[x2] = 2', 'z = d[x2]', 'x2 in d', - 'd.has_key(x2)', 'd.get(x2)', 'd.setdefault(x2, 42)', 'd.pop(x2)', 'd.update({x2: 2})']: with self.assertRaises(CustomException): - exec stmt in locals() + exec(stmt, locals()) def test_resize1(self): # Dict resizing bug, found by Jack Jansen in 2.2 CVS development. @@ -564,15 +668,17 @@ class DictTest(unittest.TestCase): d = {} def test_container_iterator(self): - # Bug #3680: tp_traverse was not implemented for dictiter objects + # Bug #3680: tp_traverse was not implemented for dictiter and + # dictview objects. class C(object): pass - iterators = (dict.iteritems, dict.itervalues, dict.iterkeys) - for i in iterators: + views = (dict.items, dict.values, dict.keys) + for v in views: obj = C() ref = weakref.ref(obj) container = {obj: 1} - obj.x = i(container) + obj.v = v(container) + obj.x = iter(obj.v) del obj, container gc.collect() self.assertIs(ref(), None, "Cycle was not collected") @@ -589,7 +695,7 @@ class DictTest(unittest.TestCase): gc.collect() self.assertTrue(gc.is_tracked(t), t) - @test_support.cpython_only + @support.cpython_only def test_track_literals(self): # Test GC-optimization of dict literals x, y, z, w = 1.5, "a", (1, None), [] @@ -607,7 +713,7 @@ class DictTest(unittest.TestCase): self._tracked({1: {}}) self._tracked({1: set()}) - @test_support.cpython_only + @support.cpython_only def test_track_dynamic(self): # Test GC-optimization of dynamically-created dicts class MyObject(object): @@ -671,7 +777,7 @@ class DictTest(unittest.TestCase): d.update([(x, y), (z, w)]) self._tracked(d) - @test_support.cpython_only + @support.cpython_only def test_track_subtypes(self): # Dict subtypes are always tracked class MyDict(dict): @@ -691,14 +797,11 @@ class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol): type2test = Dict def test_main(): - with test_support.check_py3k_warnings( - ('dict(.has_key..| inequality comparisons) not supported in 3.x', - DeprecationWarning)): - test_support.run_unittest( - DictTest, - GeneralMappingTests, - SubclassMappingTests, - ) + support.run_unittest( + DictTest, + GeneralMappingTests, + SubclassMappingTests, + ) if __name__ == "__main__": test_main() |