blob: 7dd44b9515b5cf2248892c344d8b26c66d5252ce [file] [log] [blame]
Victor Stinner5ebe2c82016-01-23 13:52:05 +01001import collections
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00002import collections.abc
Victor Stinner5ebe2c82016-01-23 13:52:05 +01003import gc
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00004import pickle
Victor Stinner5ebe2c82016-01-23 13:52:05 +01005import random
6import string
7import unittest
8import weakref
9from test import support
Walter Dörwald59b23e82004-09-30 13:46:00 +000010
11
12class DictTest(unittest.TestCase):
Guido van Rossum47b9ff62006-08-24 00:41:19 +000013
Benjamin Petersonfb886362010-04-24 18:21:17 +000014 def test_invalid_keyword_arguments(self):
Benjamin Petersonf6096542010-11-17 22:33:12 +000015 class Custom(dict):
16 pass
17 for invalid in {1 : 2}, Custom({1 : 2}):
18 with self.assertRaises(TypeError):
19 dict(**invalid)
20 with self.assertRaises(TypeError):
21 {}.update(**invalid)
Benjamin Petersonfb886362010-04-24 18:21:17 +000022
Walter Dörwald59b23e82004-09-30 13:46:00 +000023 def test_constructor(self):
24 # calling built-in types without argument must return empty
25 self.assertEqual(dict(), {})
Florent Xiclunaa988e422010-03-02 16:06:24 +000026 self.assertIsNot(dict(), {})
Walter Dörwald59b23e82004-09-30 13:46:00 +000027
Christian Heimes99170a52007-12-19 02:07:34 +000028 def test_literal_constructor(self):
Florent Xiclunaa988e422010-03-02 16:06:24 +000029 # check literal constructor for different sized dicts
30 # (to exercise the BUILD_MAP oparg).
Christian Heimesb186d002008-03-18 15:15:01 +000031 for n in (0, 1, 6, 256, 400):
Florent Xiclunaa988e422010-03-02 16:06:24 +000032 items = [(''.join(random.sample(string.ascii_letters, 8)), i)
Christian Heimesb186d002008-03-18 15:15:01 +000033 for i in range(n)]
34 random.shuffle(items)
Florent Xiclunaa988e422010-03-02 16:06:24 +000035 formatted_items = ('{!r}: {:d}'.format(k, v) for k, v in items)
36 dictliteral = '{' + ', '.join(formatted_items) + '}'
Christian Heimes99170a52007-12-19 02:07:34 +000037 self.assertEqual(eval(dictliteral), dict(items))
Christian Heimes99170a52007-12-19 02:07:34 +000038
Walter Dörwald59b23e82004-09-30 13:46:00 +000039 def test_bool(self):
Florent Xiclunaa988e422010-03-02 16:06:24 +000040 self.assertIs(not {}, True)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000041 self.assertTrue({1: 2})
Florent Xiclunaa988e422010-03-02 16:06:24 +000042 self.assertIs(bool({}), False)
43 self.assertIs(bool({1: 2}), True)
Walter Dörwald59b23e82004-09-30 13:46:00 +000044
45 def test_keys(self):
46 d = {}
Guido van Rossume34cdd12007-02-14 17:49:04 +000047 self.assertEqual(set(d.keys()), set())
Walter Dörwald59b23e82004-09-30 13:46:00 +000048 d = {'a': 1, 'b': 2}
49 k = d.keys()
Ezio Melotti4e1f3d62013-10-05 03:07:03 +030050 self.assertEqual(set(k), {'a', 'b'})
51 self.assertIn('a', k)
52 self.assertIn('b', k)
Benjamin Peterson577473f2010-01-19 00:09:57 +000053 self.assertIn('a', d)
Benjamin Peterson577473f2010-01-19 00:09:57 +000054 self.assertIn('b', d)
Walter Dörwald59b23e82004-09-30 13:46:00 +000055 self.assertRaises(TypeError, d.keys, None)
Raymond Hettingerb0d56af2009-03-03 10:52:49 +000056 self.assertEqual(repr(dict(a=1).keys()), "dict_keys(['a'])")
Walter Dörwald59b23e82004-09-30 13:46:00 +000057
58 def test_values(self):
59 d = {}
Guido van Rossume34cdd12007-02-14 17:49:04 +000060 self.assertEqual(set(d.values()), set())
Walter Dörwald59b23e82004-09-30 13:46:00 +000061 d = {1:2}
Guido van Rossume34cdd12007-02-14 17:49:04 +000062 self.assertEqual(set(d.values()), {2})
Walter Dörwald59b23e82004-09-30 13:46:00 +000063 self.assertRaises(TypeError, d.values, None)
Raymond Hettingerb0d56af2009-03-03 10:52:49 +000064 self.assertEqual(repr(dict(a=1).values()), "dict_values([1])")
Walter Dörwald59b23e82004-09-30 13:46:00 +000065
66 def test_items(self):
67 d = {}
Guido van Rossume34cdd12007-02-14 17:49:04 +000068 self.assertEqual(set(d.items()), set())
Walter Dörwald59b23e82004-09-30 13:46:00 +000069
70 d = {1:2}
Guido van Rossume34cdd12007-02-14 17:49:04 +000071 self.assertEqual(set(d.items()), {(1, 2)})
Walter Dörwald59b23e82004-09-30 13:46:00 +000072 self.assertRaises(TypeError, d.items, None)
Raymond Hettingerb0d56af2009-03-03 10:52:49 +000073 self.assertEqual(repr(dict(a=1).items()), "dict_items([('a', 1)])")
Walter Dörwald59b23e82004-09-30 13:46:00 +000074
Walter Dörwald59b23e82004-09-30 13:46:00 +000075 def test_contains(self):
76 d = {}
Ezio Melottib58e0bd2010-01-23 15:40:09 +000077 self.assertNotIn('a', d)
Florent Xiclunaa988e422010-03-02 16:06:24 +000078 self.assertFalse('a' in d)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000079 self.assertTrue('a' not in d)
Walter Dörwald59b23e82004-09-30 13:46:00 +000080 d = {'a': 1, 'b': 2}
Benjamin Peterson577473f2010-01-19 00:09:57 +000081 self.assertIn('a', d)
Benjamin Peterson577473f2010-01-19 00:09:57 +000082 self.assertIn('b', d)
Benjamin Peterson577473f2010-01-19 00:09:57 +000083 self.assertNotIn('c', d)
Walter Dörwald59b23e82004-09-30 13:46:00 +000084
85 self.assertRaises(TypeError, d.__contains__)
86
87 def test_len(self):
88 d = {}
89 self.assertEqual(len(d), 0)
90 d = {'a': 1, 'b': 2}
91 self.assertEqual(len(d), 2)
92
93 def test_getitem(self):
94 d = {'a': 1, 'b': 2}
95 self.assertEqual(d['a'], 1)
96 self.assertEqual(d['b'], 2)
97 d['c'] = 3
98 d['a'] = 4
99 self.assertEqual(d['c'], 3)
100 self.assertEqual(d['a'], 4)
101 del d['b']
102 self.assertEqual(d, {'a': 4, 'c': 3})
103
104 self.assertRaises(TypeError, d.__getitem__)
105
106 class BadEq(object):
107 def __eq__(self, other):
108 raise Exc()
Guido van Rossum38938152006-08-21 23:36:26 +0000109 def __hash__(self):
110 return 24
Walter Dörwald59b23e82004-09-30 13:46:00 +0000111
112 d = {}
113 d[BadEq()] = 42
114 self.assertRaises(KeyError, d.__getitem__, 23)
115
116 class Exc(Exception): pass
117
118 class BadHash(object):
119 fail = False
120 def __hash__(self):
121 if self.fail:
122 raise Exc()
123 else:
124 return 42
125
126 x = BadHash()
127 d[x] = 42
128 x.fail = True
129 self.assertRaises(Exc, d.__getitem__, x)
130
131 def test_clear(self):
132 d = {1:1, 2:2, 3:3}
133 d.clear()
134 self.assertEqual(d, {})
135
136 self.assertRaises(TypeError, d.clear, None)
137
138 def test_update(self):
139 d = {}
140 d.update({1:100})
141 d.update({2:20})
142 d.update({1:1, 2:2, 3:3})
143 self.assertEqual(d, {1:1, 2:2, 3:3})
144
145 d.update()
146 self.assertEqual(d, {1:1, 2:2, 3:3})
147
148 self.assertRaises((TypeError, AttributeError), d.update, None)
149
150 class SimpleUserDict:
151 def __init__(self):
152 self.d = {1:1, 2:2, 3:3}
153 def keys(self):
154 return self.d.keys()
155 def __getitem__(self, i):
156 return self.d[i]
157 d.clear()
158 d.update(SimpleUserDict())
159 self.assertEqual(d, {1:1, 2:2, 3:3})
160
161 class Exc(Exception): pass
162
163 d.clear()
164 class FailingUserDict:
165 def keys(self):
166 raise Exc
167 self.assertRaises(Exc, d.update, FailingUserDict())
168
169 class FailingUserDict:
170 def keys(self):
171 class BogonIter:
172 def __init__(self):
173 self.i = 1
174 def __iter__(self):
175 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000176 def __next__(self):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000177 if self.i:
178 self.i = 0
179 return 'a'
180 raise Exc
181 return BogonIter()
182 def __getitem__(self, key):
183 return key
184 self.assertRaises(Exc, d.update, FailingUserDict())
185
186 class FailingUserDict:
187 def keys(self):
188 class BogonIter:
189 def __init__(self):
190 self.i = ord('a')
191 def __iter__(self):
192 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000193 def __next__(self):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000194 if self.i <= ord('z'):
195 rtn = chr(self.i)
196 self.i += 1
197 return rtn
198 raise StopIteration
199 return BogonIter()
200 def __getitem__(self, key):
201 raise Exc
202 self.assertRaises(Exc, d.update, FailingUserDict())
203
204 class badseq(object):
205 def __iter__(self):
206 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000207 def __next__(self):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000208 raise Exc()
209
210 self.assertRaises(Exc, {}.update, badseq())
211
212 self.assertRaises(ValueError, {}.update, [(1, 2, 3)])
213
214 def test_fromkeys(self):
215 self.assertEqual(dict.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
216 d = {}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000217 self.assertIsNot(d.fromkeys('abc'), d)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000218 self.assertEqual(d.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
219 self.assertEqual(d.fromkeys((4,5),0), {4:0, 5:0})
220 self.assertEqual(d.fromkeys([]), {})
221 def g():
222 yield 1
223 self.assertEqual(d.fromkeys(g()), {1:None})
224 self.assertRaises(TypeError, {}.fromkeys, 3)
225 class dictlike(dict): pass
226 self.assertEqual(dictlike.fromkeys('a'), {'a':None})
227 self.assertEqual(dictlike().fromkeys('a'), {'a':None})
Florent Xiclunaa988e422010-03-02 16:06:24 +0000228 self.assertIsInstance(dictlike.fromkeys('a'), dictlike)
229 self.assertIsInstance(dictlike().fromkeys('a'), dictlike)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000230 class mydict(dict):
231 def __new__(cls):
Raymond Hettingerf80680d2008-02-06 00:07:11 +0000232 return collections.UserDict()
Walter Dörwald59b23e82004-09-30 13:46:00 +0000233 ud = mydict.fromkeys('ab')
234 self.assertEqual(ud, {'a':None, 'b':None})
Ezio Melottie9615932010-01-24 19:26:24 +0000235 self.assertIsInstance(ud, collections.UserDict)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000236 self.assertRaises(TypeError, dict.fromkeys)
237
238 class Exc(Exception): pass
239
240 class baddict1(dict):
241 def __init__(self):
242 raise Exc()
243
244 self.assertRaises(Exc, baddict1.fromkeys, [1])
245
246 class BadSeq(object):
247 def __iter__(self):
248 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000249 def __next__(self):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000250 raise Exc()
251
252 self.assertRaises(Exc, dict.fromkeys, BadSeq())
253
254 class baddict2(dict):
255 def __setitem__(self, key, value):
256 raise Exc()
257
258 self.assertRaises(Exc, baddict2.fromkeys, [1])
259
Guido van Rossum58da9312007-11-10 23:39:45 +0000260 # test fast path for dictionary inputs
261 d = dict(zip(range(6), range(6)))
262 self.assertEqual(dict.fromkeys(d, 0), dict(zip(range(6), [0]*6)))
263
Benjamin Petersond1f2cb32012-10-31 14:05:55 -0400264 class baddict3(dict):
265 def __new__(cls):
266 return d
267 d = {i : i for i in range(10)}
268 res = d.copy()
269 res.update(a=None, b=None, c=None)
270 self.assertEqual(baddict3.fromkeys({"a", "b", "c"}), res)
271
Walter Dörwald59b23e82004-09-30 13:46:00 +0000272 def test_copy(self):
273 d = {1:1, 2:2, 3:3}
274 self.assertEqual(d.copy(), {1:1, 2:2, 3:3})
275 self.assertEqual({}.copy(), {})
276 self.assertRaises(TypeError, d.copy, None)
277
278 def test_get(self):
279 d = {}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000280 self.assertIs(d.get('c'), None)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000281 self.assertEqual(d.get('c', 3), 3)
Florent Xiclunaa988e422010-03-02 16:06:24 +0000282 d = {'a': 1, 'b': 2}
283 self.assertIs(d.get('c'), None)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000284 self.assertEqual(d.get('c', 3), 3)
285 self.assertEqual(d.get('a'), 1)
286 self.assertEqual(d.get('a', 3), 1)
287 self.assertRaises(TypeError, d.get)
288 self.assertRaises(TypeError, d.get, None, None, None)
289
290 def test_setdefault(self):
291 # dict.setdefault()
292 d = {}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000293 self.assertIs(d.setdefault('key0'), None)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000294 d.setdefault('key0', [])
Florent Xiclunaa988e422010-03-02 16:06:24 +0000295 self.assertIs(d.setdefault('key0'), None)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000296 d.setdefault('key', []).append(3)
297 self.assertEqual(d['key'][0], 3)
298 d.setdefault('key', []).append(4)
299 self.assertEqual(len(d['key']), 2)
300 self.assertRaises(TypeError, d.setdefault)
301
302 class Exc(Exception): pass
303
304 class BadHash(object):
305 fail = False
306 def __hash__(self):
307 if self.fail:
308 raise Exc()
309 else:
310 return 42
311
312 x = BadHash()
313 d[x] = 42
314 x.fail = True
315 self.assertRaises(Exc, d.setdefault, x, [])
316
Antoine Pitroue965d972012-02-27 00:45:12 +0100317 def test_setdefault_atomic(self):
318 # Issue #13521: setdefault() calls __hash__ and __eq__ only once.
319 class Hashed(object):
320 def __init__(self):
321 self.hash_count = 0
322 self.eq_count = 0
323 def __hash__(self):
324 self.hash_count += 1
325 return 42
326 def __eq__(self, other):
327 self.eq_count += 1
328 return id(self) == id(other)
329 hashed1 = Hashed()
330 y = {hashed1: 5}
331 hashed2 = Hashed()
332 y.setdefault(hashed2, [])
333 self.assertEqual(hashed1.hash_count, 1)
334 self.assertEqual(hashed2.hash_count, 1)
335 self.assertEqual(hashed1.eq_count + hashed2.eq_count, 1)
336
Benjamin Peterson7d95e402012-04-23 11:24:50 -0400337 def test_setitem_atomic_at_resize(self):
338 class Hashed(object):
339 def __init__(self):
340 self.hash_count = 0
341 self.eq_count = 0
342 def __hash__(self):
343 self.hash_count += 1
344 return 42
345 def __eq__(self, other):
346 self.eq_count += 1
347 return id(self) == id(other)
348 hashed1 = Hashed()
349 # 5 items
350 y = {hashed1: 5, 0: 0, 1: 1, 2: 2, 3: 3}
351 hashed2 = Hashed()
352 # 6th item forces a resize
353 y[hashed2] = []
354 self.assertEqual(hashed1.hash_count, 1)
355 self.assertEqual(hashed2.hash_count, 1)
356 self.assertEqual(hashed1.eq_count + hashed2.eq_count, 1)
357
Walter Dörwald59b23e82004-09-30 13:46:00 +0000358 def test_popitem(self):
359 # dict.popitem()
360 for copymode in -1, +1:
361 # -1: b has same structure as a
362 # +1: b is a.copy()
363 for log2size in range(12):
364 size = 2**log2size
365 a = {}
366 b = {}
367 for i in range(size):
368 a[repr(i)] = i
369 if copymode < 0:
370 b[repr(i)] = i
371 if copymode > 0:
372 b = a.copy()
373 for i in range(size):
374 ka, va = ta = a.popitem()
375 self.assertEqual(va, int(ka))
376 kb, vb = tb = b.popitem()
377 self.assertEqual(vb, int(kb))
Florent Xiclunaa988e422010-03-02 16:06:24 +0000378 self.assertFalse(copymode < 0 and ta != tb)
379 self.assertFalse(a)
380 self.assertFalse(b)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000381
382 d = {}
383 self.assertRaises(KeyError, d.popitem)
384
385 def test_pop(self):
386 # Tests for pop with specified key
387 d = {}
388 k, v = 'abc', 'def'
389 d[k] = v
390 self.assertRaises(KeyError, d.pop, 'ghi')
391
392 self.assertEqual(d.pop(k), v)
393 self.assertEqual(len(d), 0)
394
395 self.assertRaises(KeyError, d.pop, k)
396
Walter Dörwald59b23e82004-09-30 13:46:00 +0000397 self.assertEqual(d.pop(k, v), v)
398 d[k] = v
399 self.assertEqual(d.pop(k, 1), v)
400
401 self.assertRaises(TypeError, d.pop)
402
403 class Exc(Exception): pass
404
405 class BadHash(object):
406 fail = False
407 def __hash__(self):
408 if self.fail:
409 raise Exc()
410 else:
411 return 42
412
413 x = BadHash()
414 d[x] = 42
415 x.fail = True
416 self.assertRaises(Exc, d.pop, x)
417
Victor Stinner198b2912012-03-06 01:03:13 +0100418 def test_mutating_iteration(self):
Florent Xiclunaa988e422010-03-02 16:06:24 +0000419 # changing dict size during iteration
Walter Dörwald59b23e82004-09-30 13:46:00 +0000420 d = {}
421 d[1] = 1
Florent Xiclunaa988e422010-03-02 16:06:24 +0000422 with self.assertRaises(RuntimeError):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000423 for i in d:
424 d[i+1] = 1
Walter Dörwald59b23e82004-09-30 13:46:00 +0000425
Victor Stinner198b2912012-03-06 01:03:13 +0100426 def test_mutating_lookup(self):
Antoine Pitrou9a234902012-05-13 20:48:01 +0200427 # changing dict during a lookup (issue #14417)
Victor Stinner198b2912012-03-06 01:03:13 +0100428 class NastyKey:
429 mutate_dict = None
430
Victor Stinner28393822012-03-09 22:58:51 +0100431 def __init__(self, value):
432 self.value = value
433
Victor Stinner198b2912012-03-06 01:03:13 +0100434 def __hash__(self):
435 # hash collision!
436 return 1
437
438 def __eq__(self, other):
Victor Stinner28393822012-03-09 22:58:51 +0100439 if NastyKey.mutate_dict:
440 mydict, key = NastyKey.mutate_dict
441 NastyKey.mutate_dict = None
442 del mydict[key]
443 return self.value == other.value
Victor Stinner198b2912012-03-06 01:03:13 +0100444
Victor Stinner28393822012-03-09 22:58:51 +0100445 key1 = NastyKey(1)
446 key2 = NastyKey(2)
447 d = {key1: 1}
448 NastyKey.mutate_dict = (d, key1)
Antoine Pitrou9a234902012-05-13 20:48:01 +0200449 d[key2] = 2
450 self.assertEqual(d, {key2: 2})
Victor Stinner198b2912012-03-06 01:03:13 +0100451
Walter Dörwald59b23e82004-09-30 13:46:00 +0000452 def test_repr(self):
453 d = {}
454 self.assertEqual(repr(d), '{}')
455 d[1] = 2
456 self.assertEqual(repr(d), '{1: 2}')
457 d = {}
458 d[1] = d
459 self.assertEqual(repr(d), '{1: {...}}')
460
461 class Exc(Exception): pass
462
463 class BadRepr(object):
464 def __repr__(self):
465 raise Exc()
466
467 d = {1: BadRepr()}
468 self.assertRaises(Exc, repr, d)
469
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000470 def test_eq(self):
471 self.assertEqual({}, {})
Guido van Rossume2a383d2007-01-15 16:59:06 +0000472 self.assertEqual({1: 2}, {1: 2})
Walter Dörwald59b23e82004-09-30 13:46:00 +0000473
474 class Exc(Exception): pass
475
476 class BadCmp(object):
477 def __eq__(self, other):
478 raise Exc()
Guido van Rossum38938152006-08-21 23:36:26 +0000479 def __hash__(self):
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000480 return 1
Walter Dörwald59b23e82004-09-30 13:46:00 +0000481
482 d1 = {BadCmp(): 1}
483 d2 = {1: 1}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000484
485 with self.assertRaises(Exc):
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000486 d1 == d2
Walter Dörwald59b23e82004-09-30 13:46:00 +0000487
Guido van Rossumaac530c2007-08-24 22:33:45 +0000488 def test_keys_contained(self):
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000489 self.helper_keys_contained(lambda x: x.keys())
490 self.helper_keys_contained(lambda x: x.items())
491
492 def helper_keys_contained(self, fn):
Guido van Rossumaac530c2007-08-24 22:33:45 +0000493 # Test rich comparisons against dict key views, which should behave the
494 # same as sets.
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000495 empty = fn(dict())
496 empty2 = fn(dict())
497 smaller = fn({1:1, 2:2})
498 larger = fn({1:1, 2:2, 3:3})
499 larger2 = fn({1:1, 2:2, 3:3})
500 larger3 = fn({4:1, 2:2, 3:3})
Guido van Rossumaac530c2007-08-24 22:33:45 +0000501
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000502 self.assertTrue(smaller < larger)
503 self.assertTrue(smaller <= larger)
504 self.assertTrue(larger > smaller)
505 self.assertTrue(larger >= smaller)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000506
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000507 self.assertFalse(smaller >= larger)
508 self.assertFalse(smaller > larger)
509 self.assertFalse(larger <= smaller)
510 self.assertFalse(larger < smaller)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000511
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000512 self.assertFalse(smaller < larger3)
513 self.assertFalse(smaller <= larger3)
514 self.assertFalse(larger3 > smaller)
515 self.assertFalse(larger3 >= smaller)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000516
517 # Inequality strictness
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000518 self.assertTrue(larger2 >= larger)
519 self.assertTrue(larger2 <= larger)
520 self.assertFalse(larger2 > larger)
521 self.assertFalse(larger2 < larger)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000522
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000523 self.assertTrue(larger == larger2)
524 self.assertTrue(smaller != larger)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000525
526 # There is an optimization on the zero-element case.
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000527 self.assertTrue(empty == empty2)
528 self.assertFalse(empty != empty2)
529 self.assertFalse(empty == smaller)
530 self.assertTrue(empty != smaller)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000531
532 # With the same size, an elementwise compare happens
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000533 self.assertTrue(larger != larger3)
534 self.assertFalse(larger == larger3)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000535
536 def test_errors_in_view_containment_check(self):
537 class C:
538 def __eq__(self, other):
539 raise RuntimeError
Florent Xiclunaa988e422010-03-02 16:06:24 +0000540
Guido van Rossumaac530c2007-08-24 22:33:45 +0000541 d1 = {1: C()}
542 d2 = {1: C()}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000543 with self.assertRaises(RuntimeError):
544 d1.items() == d2.items()
545 with self.assertRaises(RuntimeError):
546 d1.items() != d2.items()
547 with self.assertRaises(RuntimeError):
548 d1.items() <= d2.items()
549 with self.assertRaises(RuntimeError):
550 d1.items() >= d2.items()
551
Guido van Rossumaac530c2007-08-24 22:33:45 +0000552 d3 = {1: C(), 2: C()}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000553 with self.assertRaises(RuntimeError):
554 d2.items() < d3.items()
555 with self.assertRaises(RuntimeError):
556 d3.items() > d2.items()
Guido van Rossumaac530c2007-08-24 22:33:45 +0000557
Guido van Rossumbe534712007-08-24 23:43:52 +0000558 def test_dictview_set_operations_on_keys(self):
Guido van Rossum523259b2007-08-24 23:41:22 +0000559 k1 = {1:1, 2:2}.keys()
560 k2 = {1:1, 2:2, 3:3}.keys()
561 k3 = {4:4}.keys()
562
Florent Xiclunaa988e422010-03-02 16:06:24 +0000563 self.assertEqual(k1 - k2, set())
564 self.assertEqual(k1 - k3, {1,2})
565 self.assertEqual(k2 - k1, {3})
566 self.assertEqual(k3 - k1, {4})
567 self.assertEqual(k1 & k2, {1,2})
568 self.assertEqual(k1 & k3, set())
569 self.assertEqual(k1 | k2, {1,2,3})
570 self.assertEqual(k1 ^ k2, {3})
571 self.assertEqual(k1 ^ k3, {1,2,4})
Guido van Rossum523259b2007-08-24 23:41:22 +0000572
Guido van Rossumbe534712007-08-24 23:43:52 +0000573 def test_dictview_set_operations_on_items(self):
574 k1 = {1:1, 2:2}.items()
575 k2 = {1:1, 2:2, 3:3}.items()
576 k3 = {4:4}.items()
577
Florent Xiclunaa988e422010-03-02 16:06:24 +0000578 self.assertEqual(k1 - k2, set())
579 self.assertEqual(k1 - k3, {(1,1), (2,2)})
580 self.assertEqual(k2 - k1, {(3,3)})
581 self.assertEqual(k3 - k1, {(4,4)})
582 self.assertEqual(k1 & k2, {(1,1), (2,2)})
583 self.assertEqual(k1 & k3, set())
584 self.assertEqual(k1 | k2, {(1,1), (2,2), (3,3)})
585 self.assertEqual(k1 ^ k2, {(3,3)})
586 self.assertEqual(k1 ^ k3, {(1,1), (2,2), (4,4)})
Guido van Rossum523259b2007-08-24 23:41:22 +0000587
Guido van Rossum1d719962007-08-24 23:47:30 +0000588 def test_dictview_mixed_set_operations(self):
589 # Just a few for .keys()
Guido van Rossuma401bbe2007-08-24 23:51:55 +0000590 self.assertTrue({1:1}.keys() == {1})
591 self.assertTrue({1} == {1:1}.keys())
Florent Xiclunaa988e422010-03-02 16:06:24 +0000592 self.assertEqual({1:1}.keys() | {2}, {1, 2})
593 self.assertEqual({2} | {1:1}.keys(), {1, 2})
Guido van Rossum1d719962007-08-24 23:47:30 +0000594 # And a few for .items()
Guido van Rossuma401bbe2007-08-24 23:51:55 +0000595 self.assertTrue({1:1}.items() == {(1,1)})
596 self.assertTrue({(1,1)} == {1:1}.items())
Florent Xiclunaa988e422010-03-02 16:06:24 +0000597 self.assertEqual({1:1}.items() | {2}, {(1,1), 2})
598 self.assertEqual({2} | {1:1}.items(), {(1,1), 2})
Guido van Rossum1d719962007-08-24 23:47:30 +0000599
Guido van Rossum1968ad32006-02-25 22:38:04 +0000600 def test_missing(self):
601 # Make sure dict doesn't have a __missing__ method
Florent Xiclunaa988e422010-03-02 16:06:24 +0000602 self.assertFalse(hasattr(dict, "__missing__"))
603 self.assertFalse(hasattr({}, "__missing__"))
Guido van Rossum1968ad32006-02-25 22:38:04 +0000604 # Test several cases:
605 # (D) subclass defines __missing__ method returning a value
606 # (E) subclass defines __missing__ method raising RuntimeError
607 # (F) subclass sets __missing__ instance variable (no effect)
Serhiy Storchakad65c9492015-11-02 14:10:23 +0200608 # (G) subclass doesn't define __missing__ at all
Guido van Rossum1968ad32006-02-25 22:38:04 +0000609 class D(dict):
610 def __missing__(self, key):
611 return 42
612 d = D({1: 2, 3: 4})
613 self.assertEqual(d[1], 2)
614 self.assertEqual(d[3], 4)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000615 self.assertNotIn(2, d)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000616 self.assertNotIn(2, d.keys())
Guido van Rossum1968ad32006-02-25 22:38:04 +0000617 self.assertEqual(d[2], 42)
Florent Xiclunaa988e422010-03-02 16:06:24 +0000618
Guido van Rossum1968ad32006-02-25 22:38:04 +0000619 class E(dict):
620 def __missing__(self, key):
621 raise RuntimeError(key)
622 e = E()
Florent Xiclunaa988e422010-03-02 16:06:24 +0000623 with self.assertRaises(RuntimeError) as c:
Guido van Rossum1968ad32006-02-25 22:38:04 +0000624 e[42]
Florent Xiclunaa988e422010-03-02 16:06:24 +0000625 self.assertEqual(c.exception.args, (42,))
626
Guido van Rossum1968ad32006-02-25 22:38:04 +0000627 class F(dict):
628 def __init__(self):
629 # An instance variable __missing__ should have no effect
630 self.__missing__ = lambda key: None
631 f = F()
Florent Xiclunaa988e422010-03-02 16:06:24 +0000632 with self.assertRaises(KeyError) as c:
Guido van Rossum1968ad32006-02-25 22:38:04 +0000633 f[42]
Florent Xiclunaa988e422010-03-02 16:06:24 +0000634 self.assertEqual(c.exception.args, (42,))
635
Guido van Rossum1968ad32006-02-25 22:38:04 +0000636 class G(dict):
637 pass
638 g = G()
Florent Xiclunaa988e422010-03-02 16:06:24 +0000639 with self.assertRaises(KeyError) as c:
Guido van Rossum1968ad32006-02-25 22:38:04 +0000640 g[42]
Florent Xiclunaa988e422010-03-02 16:06:24 +0000641 self.assertEqual(c.exception.args, (42,))
Guido van Rossum1968ad32006-02-25 22:38:04 +0000642
Thomas Wouters89f507f2006-12-13 04:49:30 +0000643 def test_tuple_keyerror(self):
644 # SF #1576657
645 d = {}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000646 with self.assertRaises(KeyError) as c:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000647 d[(1,)]
Florent Xiclunaa988e422010-03-02 16:06:24 +0000648 self.assertEqual(c.exception.args, ((1,),))
Thomas Wouters89f507f2006-12-13 04:49:30 +0000649
Guido van Rossumd8faa362007-04-27 19:54:29 +0000650 def test_bad_key(self):
Mark Dickinsona56c4672009-01-27 18:17:45 +0000651 # Dictionary lookups should fail if __eq__() raises an exception.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000652 class CustomException(Exception):
653 pass
654
655 class BadDictKey:
656 def __hash__(self):
657 return hash(self.__class__)
658
659 def __eq__(self, other):
660 if isinstance(other, self.__class__):
661 raise CustomException
662 return other
663
664 d = {}
665 x1 = BadDictKey()
666 x2 = BadDictKey()
667 d[x1] = 1
668 for stmt in ['d[x2] = 2',
669 'z = d[x2]',
670 'x2 in d',
671 'd.get(x2)',
672 'd.setdefault(x2, 42)',
673 'd.pop(x2)',
674 'd.update({x2: 2})']:
Florent Xiclunaa988e422010-03-02 16:06:24 +0000675 with self.assertRaises(CustomException):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000676 exec(stmt, locals())
Guido van Rossumd8faa362007-04-27 19:54:29 +0000677
678 def test_resize1(self):
679 # Dict resizing bug, found by Jack Jansen in 2.2 CVS development.
680 # This version got an assert failure in debug build, infinite loop in
681 # release build. Unfortunately, provoking this kind of stuff requires
682 # a mix of inserts and deletes hitting exactly the right hash codes in
683 # exactly the right order, and I can't think of a randomized approach
684 # that would be *likely* to hit a failing case in reasonable time.
685
686 d = {}
687 for i in range(5):
688 d[i] = i
689 for i in range(5):
690 del d[i]
691 for i in range(5, 9): # i==8 was the problem
692 d[i] = i
693
694 def test_resize2(self):
695 # Another dict resizing bug (SF bug #1456209).
696 # This caused Segmentation faults or Illegal instructions.
697
698 class X(object):
699 def __hash__(self):
700 return 5
701 def __eq__(self, other):
702 if resizing:
703 d.clear()
704 return False
705 d = {}
706 resizing = False
707 d[X()] = 1
708 d[X()] = 2
709 d[X()] = 3
710 d[X()] = 4
711 d[X()] = 5
712 # now trigger a resize
713 resizing = True
714 d[9] = 6
715
Georg Brandl6aa2d1f2008-08-12 08:35:52 +0000716 def test_empty_presized_dict_in_freelist(self):
717 # Bug #3537: if an empty but presized dict with a size larger
718 # than 7 was in the freelist, it triggered an assertion failure
Florent Xiclunaa988e422010-03-02 16:06:24 +0000719 with self.assertRaises(ZeroDivisionError):
720 d = {'a': 1 // 0, 'b': None, 'c': None, 'd': None, 'e': None,
Georg Brandl6aa2d1f2008-08-12 08:35:52 +0000721 'f': None, 'g': None, 'h': None}
Georg Brandl6aa2d1f2008-08-12 08:35:52 +0000722 d = {}
723
Antoine Pitrou7ddda782009-01-01 15:35:33 +0000724 def test_container_iterator(self):
725 # Bug #3680: tp_traverse was not implemented for dictiter and
726 # dictview objects.
727 class C(object):
728 pass
729 views = (dict.items, dict.values, dict.keys)
730 for v in views:
731 obj = C()
732 ref = weakref.ref(obj)
733 container = {obj: 1}
734 obj.v = v(container)
735 obj.x = iter(obj.v)
736 del obj, container
737 gc.collect()
Florent Xiclunaa988e422010-03-02 16:06:24 +0000738 self.assertIs(ref(), None, "Cycle was not collected")
Georg Brandl6aa2d1f2008-08-12 08:35:52 +0000739
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000740 def _not_tracked(self, t):
741 # Nested containers can take several collections to untrack
742 gc.collect()
743 gc.collect()
744 self.assertFalse(gc.is_tracked(t), t)
745
746 def _tracked(self, t):
747 self.assertTrue(gc.is_tracked(t), t)
748 gc.collect()
749 gc.collect()
750 self.assertTrue(gc.is_tracked(t), t)
751
Benjamin Peterson3e5cd1d2010-06-27 21:45:24 +0000752 @support.cpython_only
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000753 def test_track_literals(self):
754 # Test GC-optimization of dict literals
755 x, y, z, w = 1.5, "a", (1, None), []
756
757 self._not_tracked({})
758 self._not_tracked({x:(), y:x, z:1})
759 self._not_tracked({1: "a", "b": 2})
760 self._not_tracked({1: 2, (None, True, False, ()): int})
761 self._not_tracked({1: object()})
762
763 # Dicts with mutable elements are always tracked, even if those
764 # elements are not tracked right now.
765 self._tracked({1: []})
766 self._tracked({1: ([],)})
767 self._tracked({1: {}})
768 self._tracked({1: set()})
769
Benjamin Peterson3e5cd1d2010-06-27 21:45:24 +0000770 @support.cpython_only
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000771 def test_track_dynamic(self):
772 # Test GC-optimization of dynamically-created dicts
773 class MyObject(object):
774 pass
775 x, y, z, w, o = 1.5, "a", (1, object()), [], MyObject()
776
777 d = dict()
778 self._not_tracked(d)
779 d[1] = "a"
780 self._not_tracked(d)
781 d[y] = 2
782 self._not_tracked(d)
783 d[z] = 3
784 self._not_tracked(d)
785 self._not_tracked(d.copy())
786 d[4] = w
787 self._tracked(d)
788 self._tracked(d.copy())
789 d[4] = None
790 self._not_tracked(d)
791 self._not_tracked(d.copy())
792
793 # dd isn't tracked right now, but it may mutate and therefore d
794 # which contains it must be tracked.
795 d = dict()
796 dd = dict()
797 d[1] = dd
798 self._not_tracked(dd)
799 self._tracked(d)
800 dd[1] = d
801 self._tracked(dd)
802
803 d = dict.fromkeys([x, y, z])
804 self._not_tracked(d)
805 dd = dict()
806 dd.update(d)
807 self._not_tracked(dd)
808 d = dict.fromkeys([x, y, z, o])
809 self._tracked(d)
810 dd = dict()
811 dd.update(d)
812 self._tracked(dd)
813
814 d = dict(x=x, y=y, z=z)
815 self._not_tracked(d)
816 d = dict(x=x, y=y, z=z, w=w)
817 self._tracked(d)
818 d = dict()
819 d.update(x=x, y=y, z=z)
820 self._not_tracked(d)
821 d.update(w=w)
822 self._tracked(d)
823
824 d = dict([(x, y), (z, 1)])
825 self._not_tracked(d)
826 d = dict([(x, y), (z, w)])
827 self._tracked(d)
828 d = dict()
829 d.update([(x, y), (z, 1)])
830 self._not_tracked(d)
831 d.update([(x, y), (z, w)])
832 self._tracked(d)
833
Benjamin Peterson3e5cd1d2010-06-27 21:45:24 +0000834 @support.cpython_only
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000835 def test_track_subtypes(self):
836 # Dict subtypes are always tracked
837 class MyDict(dict):
838 pass
839 self._tracked(MyDict())
840
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000841 def test_iterator_pickling(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +0200842 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
843 data = {1:"a", 2:"b", 3:"c"}
844 it = iter(data)
845 d = pickle.dumps(it, proto)
846 it = pickle.loads(d)
847 self.assertEqual(sorted(it), sorted(data))
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000848
Serhiy Storchakabad12572014-12-15 14:03:42 +0200849 it = pickle.loads(d)
850 try:
851 drop = next(it)
852 except StopIteration:
853 continue
854 d = pickle.dumps(it, proto)
855 it = pickle.loads(d)
856 del data[drop]
857 self.assertEqual(sorted(it), sorted(data))
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000858
859 def test_itemiterator_pickling(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +0200860 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
861 data = {1:"a", 2:"b", 3:"c"}
862 # dictviews aren't picklable, only their iterators
863 itorg = iter(data.items())
864 d = pickle.dumps(itorg, proto)
865 it = pickle.loads(d)
866 # note that the type of type of the unpickled iterator
867 # is not necessarily the same as the original. It is
868 # merely an object supporting the iterator protocol, yielding
869 # the same objects as the original one.
870 # self.assertEqual(type(itorg), type(it))
871 self.assertIsInstance(it, collections.abc.Iterator)
872 self.assertEqual(dict(it), data)
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000873
Serhiy Storchakabad12572014-12-15 14:03:42 +0200874 it = pickle.loads(d)
875 drop = next(it)
876 d = pickle.dumps(it, proto)
877 it = pickle.loads(d)
878 del data[drop[0]]
879 self.assertEqual(dict(it), data)
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000880
881 def test_valuesiterator_pickling(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +0200882 for proto in range(pickle.HIGHEST_PROTOCOL):
883 data = {1:"a", 2:"b", 3:"c"}
884 # data.values() isn't picklable, only its iterator
885 it = iter(data.values())
886 d = pickle.dumps(it, proto)
887 it = pickle.loads(d)
888 self.assertEqual(sorted(list(it)), sorted(list(data.values())))
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000889
Serhiy Storchakabad12572014-12-15 14:03:42 +0200890 it = pickle.loads(d)
891 drop = next(it)
892 d = pickle.dumps(it, proto)
893 it = pickle.loads(d)
894 values = list(it) + [drop]
895 self.assertEqual(sorted(values), sorted(list(data.values())))
Guido van Rossum1968ad32006-02-25 22:38:04 +0000896
Benjamin Petersondb780d02012-04-23 13:44:32 -0400897 def test_instance_dict_getattr_str_subclass(self):
898 class Foo:
899 def __init__(self, msg):
900 self.msg = msg
901 f = Foo('123')
902 class _str(str):
903 pass
904 self.assertEqual(f.msg, getattr(f, _str('msg')))
905 self.assertEqual(f.msg, f.__dict__[_str('msg')])
906
Benjamin Peterson15ee8212012-04-24 14:44:18 -0400907 def test_object_set_item_single_instance_non_str_key(self):
908 class Foo: pass
909 f = Foo()
910 f.__dict__[1] = 1
911 f.a = 'a'
912 self.assertEqual(f.__dict__, {1:1, 'a':'a'})
913
Antoine Pitroud6967322014-10-18 00:35:00 +0200914 def check_reentrant_insertion(self, mutate):
915 # This object will trigger mutation of the dict when replaced
916 # by another value. Note this relies on refcounting: the test
917 # won't achieve its purpose on fully-GCed Python implementations.
918 class Mutating:
919 def __del__(self):
920 mutate(d)
921
922 d = {k: Mutating() for k in 'abcdefghijklmnopqr'}
923 for k in list(d):
924 d[k] = k
925
926 def test_reentrant_insertion(self):
927 # Reentrant insertion shouldn't crash (see issue #22653)
928 def mutate(d):
929 d['b'] = 5
930 self.check_reentrant_insertion(mutate)
931
932 def mutate(d):
933 d.update(self.__dict__)
934 d.clear()
935 self.check_reentrant_insertion(mutate)
936
937 def mutate(d):
938 while d:
939 d.popitem()
940 self.check_reentrant_insertion(mutate)
941
Benjamin Petersona82f77f2015-07-04 19:55:16 -0500942 def test_merge_and_mutate(self):
943 class X:
944 def __hash__(self):
945 return 0
946
947 def __eq__(self, o):
948 other.clear()
949 return False
950
951 l = [(i,0) for i in range(1, 1337)]
952 other = dict(l)
953 other[X()] = 0
954 d = {X(): 0, 1: 1}
955 self.assertRaises(RuntimeError, d.update, other)
Antoine Pitroud6967322014-10-18 00:35:00 +0200956
Serhiy Storchakafbb1c5e2016-03-30 20:40:02 +0300957 def test_free_after_iterating(self):
958 support.check_free_after_iterating(self, iter, dict)
959 support.check_free_after_iterating(self, lambda d: iter(d.keys()), dict)
960 support.check_free_after_iterating(self, lambda d: iter(d.values()), dict)
961 support.check_free_after_iterating(self, lambda d: iter(d.items()), dict)
962
Neal Norwitzc3e54b82006-03-24 07:38:37 +0000963from test import mapping_tests
Raymond Hettinger49c522b2004-09-30 15:07:29 +0000964
965class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
966 type2test = dict
967
968class Dict(dict):
969 pass
970
971class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
972 type2test = Dict
973
Victor Stinner5ebe2c82016-01-23 13:52:05 +0100974
Walter Dörwald59b23e82004-09-30 13:46:00 +0000975if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -0500976 unittest.main()