blob: aa149d31eb0e22cec78d5f61f96d207057f986aa [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
Victor Stinner78601a32016-09-09 19:28:36 -07007import sys
Victor Stinner5ebe2c82016-01-23 13:52:05 +01008import unittest
9import weakref
10from test import support
Walter Dörwald59b23e82004-09-30 13:46:00 +000011
12
13class DictTest(unittest.TestCase):
Guido van Rossum47b9ff62006-08-24 00:41:19 +000014
Benjamin Petersonfb886362010-04-24 18:21:17 +000015 def test_invalid_keyword_arguments(self):
Benjamin Petersonf6096542010-11-17 22:33:12 +000016 class Custom(dict):
17 pass
18 for invalid in {1 : 2}, Custom({1 : 2}):
19 with self.assertRaises(TypeError):
20 dict(**invalid)
21 with self.assertRaises(TypeError):
22 {}.update(**invalid)
Benjamin Petersonfb886362010-04-24 18:21:17 +000023
Walter Dörwald59b23e82004-09-30 13:46:00 +000024 def test_constructor(self):
25 # calling built-in types without argument must return empty
26 self.assertEqual(dict(), {})
Florent Xiclunaa988e422010-03-02 16:06:24 +000027 self.assertIsNot(dict(), {})
Walter Dörwald59b23e82004-09-30 13:46:00 +000028
Christian Heimes99170a52007-12-19 02:07:34 +000029 def test_literal_constructor(self):
Florent Xiclunaa988e422010-03-02 16:06:24 +000030 # check literal constructor for different sized dicts
31 # (to exercise the BUILD_MAP oparg).
Christian Heimesb186d002008-03-18 15:15:01 +000032 for n in (0, 1, 6, 256, 400):
Florent Xiclunaa988e422010-03-02 16:06:24 +000033 items = [(''.join(random.sample(string.ascii_letters, 8)), i)
Christian Heimesb186d002008-03-18 15:15:01 +000034 for i in range(n)]
35 random.shuffle(items)
Florent Xiclunaa988e422010-03-02 16:06:24 +000036 formatted_items = ('{!r}: {:d}'.format(k, v) for k, v in items)
37 dictliteral = '{' + ', '.join(formatted_items) + '}'
Christian Heimes99170a52007-12-19 02:07:34 +000038 self.assertEqual(eval(dictliteral), dict(items))
Christian Heimes99170a52007-12-19 02:07:34 +000039
Walter Dörwald59b23e82004-09-30 13:46:00 +000040 def test_bool(self):
Florent Xiclunaa988e422010-03-02 16:06:24 +000041 self.assertIs(not {}, True)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000042 self.assertTrue({1: 2})
Florent Xiclunaa988e422010-03-02 16:06:24 +000043 self.assertIs(bool({}), False)
44 self.assertIs(bool({1: 2}), True)
Walter Dörwald59b23e82004-09-30 13:46:00 +000045
46 def test_keys(self):
47 d = {}
Guido van Rossume34cdd12007-02-14 17:49:04 +000048 self.assertEqual(set(d.keys()), set())
Walter Dörwald59b23e82004-09-30 13:46:00 +000049 d = {'a': 1, 'b': 2}
50 k = d.keys()
Ezio Melotti4e1f3d62013-10-05 03:07:03 +030051 self.assertEqual(set(k), {'a', 'b'})
52 self.assertIn('a', k)
53 self.assertIn('b', k)
Benjamin Peterson577473f2010-01-19 00:09:57 +000054 self.assertIn('a', d)
Benjamin Peterson577473f2010-01-19 00:09:57 +000055 self.assertIn('b', d)
Walter Dörwald59b23e82004-09-30 13:46:00 +000056 self.assertRaises(TypeError, d.keys, None)
Raymond Hettingerb0d56af2009-03-03 10:52:49 +000057 self.assertEqual(repr(dict(a=1).keys()), "dict_keys(['a'])")
Walter Dörwald59b23e82004-09-30 13:46:00 +000058
59 def test_values(self):
60 d = {}
Guido van Rossume34cdd12007-02-14 17:49:04 +000061 self.assertEqual(set(d.values()), set())
Walter Dörwald59b23e82004-09-30 13:46:00 +000062 d = {1:2}
Guido van Rossume34cdd12007-02-14 17:49:04 +000063 self.assertEqual(set(d.values()), {2})
Walter Dörwald59b23e82004-09-30 13:46:00 +000064 self.assertRaises(TypeError, d.values, None)
Raymond Hettingerb0d56af2009-03-03 10:52:49 +000065 self.assertEqual(repr(dict(a=1).values()), "dict_values([1])")
Walter Dörwald59b23e82004-09-30 13:46:00 +000066
67 def test_items(self):
68 d = {}
Guido van Rossume34cdd12007-02-14 17:49:04 +000069 self.assertEqual(set(d.items()), set())
Walter Dörwald59b23e82004-09-30 13:46:00 +000070
71 d = {1:2}
Guido van Rossume34cdd12007-02-14 17:49:04 +000072 self.assertEqual(set(d.items()), {(1, 2)})
Walter Dörwald59b23e82004-09-30 13:46:00 +000073 self.assertRaises(TypeError, d.items, None)
Raymond Hettingerb0d56af2009-03-03 10:52:49 +000074 self.assertEqual(repr(dict(a=1).items()), "dict_items([('a', 1)])")
Walter Dörwald59b23e82004-09-30 13:46:00 +000075
Walter Dörwald59b23e82004-09-30 13:46:00 +000076 def test_contains(self):
77 d = {}
Ezio Melottib58e0bd2010-01-23 15:40:09 +000078 self.assertNotIn('a', d)
Florent Xiclunaa988e422010-03-02 16:06:24 +000079 self.assertFalse('a' in d)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000080 self.assertTrue('a' not in d)
Walter Dörwald59b23e82004-09-30 13:46:00 +000081 d = {'a': 1, 'b': 2}
Benjamin Peterson577473f2010-01-19 00:09:57 +000082 self.assertIn('a', d)
Benjamin Peterson577473f2010-01-19 00:09:57 +000083 self.assertIn('b', d)
Benjamin Peterson577473f2010-01-19 00:09:57 +000084 self.assertNotIn('c', d)
Walter Dörwald59b23e82004-09-30 13:46:00 +000085
86 self.assertRaises(TypeError, d.__contains__)
87
88 def test_len(self):
89 d = {}
90 self.assertEqual(len(d), 0)
91 d = {'a': 1, 'b': 2}
92 self.assertEqual(len(d), 2)
93
94 def test_getitem(self):
95 d = {'a': 1, 'b': 2}
96 self.assertEqual(d['a'], 1)
97 self.assertEqual(d['b'], 2)
98 d['c'] = 3
99 d['a'] = 4
100 self.assertEqual(d['c'], 3)
101 self.assertEqual(d['a'], 4)
102 del d['b']
103 self.assertEqual(d, {'a': 4, 'c': 3})
104
105 self.assertRaises(TypeError, d.__getitem__)
106
107 class BadEq(object):
108 def __eq__(self, other):
109 raise Exc()
Guido van Rossum38938152006-08-21 23:36:26 +0000110 def __hash__(self):
111 return 24
Walter Dörwald59b23e82004-09-30 13:46:00 +0000112
113 d = {}
114 d[BadEq()] = 42
115 self.assertRaises(KeyError, d.__getitem__, 23)
116
117 class Exc(Exception): pass
118
119 class BadHash(object):
120 fail = False
121 def __hash__(self):
122 if self.fail:
123 raise Exc()
124 else:
125 return 42
126
127 x = BadHash()
128 d[x] = 42
129 x.fail = True
130 self.assertRaises(Exc, d.__getitem__, x)
131
132 def test_clear(self):
133 d = {1:1, 2:2, 3:3}
134 d.clear()
135 self.assertEqual(d, {})
136
137 self.assertRaises(TypeError, d.clear, None)
138
139 def test_update(self):
140 d = {}
141 d.update({1:100})
142 d.update({2:20})
143 d.update({1:1, 2:2, 3:3})
144 self.assertEqual(d, {1:1, 2:2, 3:3})
145
146 d.update()
147 self.assertEqual(d, {1:1, 2:2, 3:3})
148
149 self.assertRaises((TypeError, AttributeError), d.update, None)
150
151 class SimpleUserDict:
152 def __init__(self):
153 self.d = {1:1, 2:2, 3:3}
154 def keys(self):
155 return self.d.keys()
156 def __getitem__(self, i):
157 return self.d[i]
158 d.clear()
159 d.update(SimpleUserDict())
160 self.assertEqual(d, {1:1, 2:2, 3:3})
161
162 class Exc(Exception): pass
163
164 d.clear()
165 class FailingUserDict:
166 def keys(self):
167 raise Exc
168 self.assertRaises(Exc, d.update, FailingUserDict())
169
170 class FailingUserDict:
171 def keys(self):
172 class BogonIter:
173 def __init__(self):
174 self.i = 1
175 def __iter__(self):
176 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000177 def __next__(self):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000178 if self.i:
179 self.i = 0
180 return 'a'
181 raise Exc
182 return BogonIter()
183 def __getitem__(self, key):
184 return key
185 self.assertRaises(Exc, d.update, FailingUserDict())
186
187 class FailingUserDict:
188 def keys(self):
189 class BogonIter:
190 def __init__(self):
191 self.i = ord('a')
192 def __iter__(self):
193 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000194 def __next__(self):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000195 if self.i <= ord('z'):
196 rtn = chr(self.i)
197 self.i += 1
198 return rtn
199 raise StopIteration
200 return BogonIter()
201 def __getitem__(self, key):
202 raise Exc
203 self.assertRaises(Exc, d.update, FailingUserDict())
204
205 class badseq(object):
206 def __iter__(self):
207 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000208 def __next__(self):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000209 raise Exc()
210
211 self.assertRaises(Exc, {}.update, badseq())
212
213 self.assertRaises(ValueError, {}.update, [(1, 2, 3)])
214
215 def test_fromkeys(self):
216 self.assertEqual(dict.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
217 d = {}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000218 self.assertIsNot(d.fromkeys('abc'), d)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000219 self.assertEqual(d.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
220 self.assertEqual(d.fromkeys((4,5),0), {4:0, 5:0})
221 self.assertEqual(d.fromkeys([]), {})
222 def g():
223 yield 1
224 self.assertEqual(d.fromkeys(g()), {1:None})
225 self.assertRaises(TypeError, {}.fromkeys, 3)
226 class dictlike(dict): pass
227 self.assertEqual(dictlike.fromkeys('a'), {'a':None})
228 self.assertEqual(dictlike().fromkeys('a'), {'a':None})
Florent Xiclunaa988e422010-03-02 16:06:24 +0000229 self.assertIsInstance(dictlike.fromkeys('a'), dictlike)
230 self.assertIsInstance(dictlike().fromkeys('a'), dictlike)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000231 class mydict(dict):
232 def __new__(cls):
Raymond Hettingerf80680d2008-02-06 00:07:11 +0000233 return collections.UserDict()
Walter Dörwald59b23e82004-09-30 13:46:00 +0000234 ud = mydict.fromkeys('ab')
235 self.assertEqual(ud, {'a':None, 'b':None})
Ezio Melottie9615932010-01-24 19:26:24 +0000236 self.assertIsInstance(ud, collections.UserDict)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000237 self.assertRaises(TypeError, dict.fromkeys)
238
239 class Exc(Exception): pass
240
241 class baddict1(dict):
242 def __init__(self):
243 raise Exc()
244
245 self.assertRaises(Exc, baddict1.fromkeys, [1])
246
247 class BadSeq(object):
248 def __iter__(self):
249 return self
Georg Brandla18af4e2007-04-21 15:47:16 +0000250 def __next__(self):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000251 raise Exc()
252
253 self.assertRaises(Exc, dict.fromkeys, BadSeq())
254
255 class baddict2(dict):
256 def __setitem__(self, key, value):
257 raise Exc()
258
259 self.assertRaises(Exc, baddict2.fromkeys, [1])
260
Guido van Rossum58da9312007-11-10 23:39:45 +0000261 # test fast path for dictionary inputs
262 d = dict(zip(range(6), range(6)))
263 self.assertEqual(dict.fromkeys(d, 0), dict(zip(range(6), [0]*6)))
264
Benjamin Petersond1f2cb32012-10-31 14:05:55 -0400265 class baddict3(dict):
266 def __new__(cls):
267 return d
268 d = {i : i for i in range(10)}
269 res = d.copy()
270 res.update(a=None, b=None, c=None)
271 self.assertEqual(baddict3.fromkeys({"a", "b", "c"}), res)
272
Walter Dörwald59b23e82004-09-30 13:46:00 +0000273 def test_copy(self):
Yury Selivanovb0a7a032018-01-22 11:54:41 -0500274 d = {1: 1, 2: 2, 3: 3}
275 self.assertIsNot(d.copy(), d)
276 self.assertEqual(d.copy(), d)
277 self.assertEqual(d.copy(), {1: 1, 2: 2, 3: 3})
278
279 copy = d.copy()
280 d[4] = 4
281 self.assertNotEqual(copy, d)
282
Walter Dörwald59b23e82004-09-30 13:46:00 +0000283 self.assertEqual({}.copy(), {})
284 self.assertRaises(TypeError, d.copy, None)
285
Yury Selivanovb0a7a032018-01-22 11:54:41 -0500286 def test_copy_fuzz(self):
287 for dict_size in [10, 100, 1000, 10000, 100000]:
288 dict_size = random.randrange(
289 dict_size // 2, dict_size + dict_size // 2)
290 with self.subTest(dict_size=dict_size):
291 d = {}
292 for i in range(dict_size):
293 d[i] = i
294
295 d2 = d.copy()
296 self.assertIsNot(d2, d)
297 self.assertEqual(d, d2)
298 d2['key'] = 'value'
299 self.assertNotEqual(d, d2)
300 self.assertEqual(len(d2), len(d) + 1)
301
302 def test_copy_maintains_tracking(self):
303 class A:
304 pass
305
306 key = A()
307
308 for d in ({}, {'a': 1}, {key: 'val'}):
309 d2 = d.copy()
310 self.assertEqual(gc.is_tracked(d), gc.is_tracked(d2))
311
312 def test_copy_noncompact(self):
313 # Dicts don't compact themselves on del/pop operations.
314 # Copy will use a slow merging strategy that produces
315 # a compacted copy when roughly 33% of dict is a non-used
316 # keys-space (to optimize memory footprint).
317 # In this test we want to hit the slow/compacting
318 # branch of dict.copy() and make sure it works OK.
319 d = {k: k for k in range(1000)}
320 for k in range(950):
321 del d[k]
322 d2 = d.copy()
323 self.assertEqual(d2, d)
324
Walter Dörwald59b23e82004-09-30 13:46:00 +0000325 def test_get(self):
326 d = {}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000327 self.assertIs(d.get('c'), None)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000328 self.assertEqual(d.get('c', 3), 3)
Florent Xiclunaa988e422010-03-02 16:06:24 +0000329 d = {'a': 1, 'b': 2}
330 self.assertIs(d.get('c'), None)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000331 self.assertEqual(d.get('c', 3), 3)
332 self.assertEqual(d.get('a'), 1)
333 self.assertEqual(d.get('a', 3), 1)
334 self.assertRaises(TypeError, d.get)
335 self.assertRaises(TypeError, d.get, None, None, None)
336
337 def test_setdefault(self):
338 # dict.setdefault()
339 d = {}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000340 self.assertIs(d.setdefault('key0'), None)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000341 d.setdefault('key0', [])
Florent Xiclunaa988e422010-03-02 16:06:24 +0000342 self.assertIs(d.setdefault('key0'), None)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000343 d.setdefault('key', []).append(3)
344 self.assertEqual(d['key'][0], 3)
345 d.setdefault('key', []).append(4)
346 self.assertEqual(len(d['key']), 2)
347 self.assertRaises(TypeError, d.setdefault)
348
349 class Exc(Exception): pass
350
351 class BadHash(object):
352 fail = False
353 def __hash__(self):
354 if self.fail:
355 raise Exc()
356 else:
357 return 42
358
359 x = BadHash()
360 d[x] = 42
361 x.fail = True
362 self.assertRaises(Exc, d.setdefault, x, [])
363
Antoine Pitroue965d972012-02-27 00:45:12 +0100364 def test_setdefault_atomic(self):
365 # Issue #13521: setdefault() calls __hash__ and __eq__ only once.
366 class Hashed(object):
367 def __init__(self):
368 self.hash_count = 0
369 self.eq_count = 0
370 def __hash__(self):
371 self.hash_count += 1
372 return 42
373 def __eq__(self, other):
374 self.eq_count += 1
375 return id(self) == id(other)
376 hashed1 = Hashed()
377 y = {hashed1: 5}
378 hashed2 = Hashed()
379 y.setdefault(hashed2, [])
380 self.assertEqual(hashed1.hash_count, 1)
381 self.assertEqual(hashed2.hash_count, 1)
382 self.assertEqual(hashed1.eq_count + hashed2.eq_count, 1)
383
Benjamin Peterson7d95e402012-04-23 11:24:50 -0400384 def test_setitem_atomic_at_resize(self):
385 class Hashed(object):
386 def __init__(self):
387 self.hash_count = 0
388 self.eq_count = 0
389 def __hash__(self):
390 self.hash_count += 1
391 return 42
392 def __eq__(self, other):
393 self.eq_count += 1
394 return id(self) == id(other)
395 hashed1 = Hashed()
396 # 5 items
397 y = {hashed1: 5, 0: 0, 1: 1, 2: 2, 3: 3}
398 hashed2 = Hashed()
399 # 6th item forces a resize
400 y[hashed2] = []
401 self.assertEqual(hashed1.hash_count, 1)
402 self.assertEqual(hashed2.hash_count, 1)
403 self.assertEqual(hashed1.eq_count + hashed2.eq_count, 1)
404
Walter Dörwald59b23e82004-09-30 13:46:00 +0000405 def test_popitem(self):
406 # dict.popitem()
407 for copymode in -1, +1:
408 # -1: b has same structure as a
409 # +1: b is a.copy()
410 for log2size in range(12):
411 size = 2**log2size
412 a = {}
413 b = {}
414 for i in range(size):
415 a[repr(i)] = i
416 if copymode < 0:
417 b[repr(i)] = i
418 if copymode > 0:
419 b = a.copy()
420 for i in range(size):
421 ka, va = ta = a.popitem()
422 self.assertEqual(va, int(ka))
423 kb, vb = tb = b.popitem()
424 self.assertEqual(vb, int(kb))
Florent Xiclunaa988e422010-03-02 16:06:24 +0000425 self.assertFalse(copymode < 0 and ta != tb)
426 self.assertFalse(a)
427 self.assertFalse(b)
Walter Dörwald59b23e82004-09-30 13:46:00 +0000428
429 d = {}
430 self.assertRaises(KeyError, d.popitem)
431
432 def test_pop(self):
433 # Tests for pop with specified key
434 d = {}
435 k, v = 'abc', 'def'
436 d[k] = v
437 self.assertRaises(KeyError, d.pop, 'ghi')
438
439 self.assertEqual(d.pop(k), v)
440 self.assertEqual(len(d), 0)
441
442 self.assertRaises(KeyError, d.pop, k)
443
Walter Dörwald59b23e82004-09-30 13:46:00 +0000444 self.assertEqual(d.pop(k, v), v)
445 d[k] = v
446 self.assertEqual(d.pop(k, 1), v)
447
448 self.assertRaises(TypeError, d.pop)
449
450 class Exc(Exception): pass
451
452 class BadHash(object):
453 fail = False
454 def __hash__(self):
455 if self.fail:
456 raise Exc()
457 else:
458 return 42
459
460 x = BadHash()
461 d[x] = 42
462 x.fail = True
463 self.assertRaises(Exc, d.pop, x)
464
Victor Stinner198b2912012-03-06 01:03:13 +0100465 def test_mutating_iteration(self):
Florent Xiclunaa988e422010-03-02 16:06:24 +0000466 # changing dict size during iteration
Walter Dörwald59b23e82004-09-30 13:46:00 +0000467 d = {}
468 d[1] = 1
Florent Xiclunaa988e422010-03-02 16:06:24 +0000469 with self.assertRaises(RuntimeError):
Walter Dörwald59b23e82004-09-30 13:46:00 +0000470 for i in d:
471 d[i+1] = 1
Walter Dörwald59b23e82004-09-30 13:46:00 +0000472
Victor Stinner198b2912012-03-06 01:03:13 +0100473 def test_mutating_lookup(self):
Antoine Pitrou9a234902012-05-13 20:48:01 +0200474 # changing dict during a lookup (issue #14417)
Victor Stinner198b2912012-03-06 01:03:13 +0100475 class NastyKey:
476 mutate_dict = None
477
Victor Stinner28393822012-03-09 22:58:51 +0100478 def __init__(self, value):
479 self.value = value
480
Victor Stinner198b2912012-03-06 01:03:13 +0100481 def __hash__(self):
482 # hash collision!
483 return 1
484
485 def __eq__(self, other):
Victor Stinner28393822012-03-09 22:58:51 +0100486 if NastyKey.mutate_dict:
487 mydict, key = NastyKey.mutate_dict
488 NastyKey.mutate_dict = None
489 del mydict[key]
490 return self.value == other.value
Victor Stinner198b2912012-03-06 01:03:13 +0100491
Victor Stinner28393822012-03-09 22:58:51 +0100492 key1 = NastyKey(1)
493 key2 = NastyKey(2)
494 d = {key1: 1}
495 NastyKey.mutate_dict = (d, key1)
Antoine Pitrou9a234902012-05-13 20:48:01 +0200496 d[key2] = 2
497 self.assertEqual(d, {key2: 2})
Victor Stinner198b2912012-03-06 01:03:13 +0100498
Walter Dörwald59b23e82004-09-30 13:46:00 +0000499 def test_repr(self):
500 d = {}
501 self.assertEqual(repr(d), '{}')
502 d[1] = 2
503 self.assertEqual(repr(d), '{1: 2}')
504 d = {}
505 d[1] = d
506 self.assertEqual(repr(d), '{1: {...}}')
507
508 class Exc(Exception): pass
509
510 class BadRepr(object):
511 def __repr__(self):
512 raise Exc()
513
514 d = {1: BadRepr()}
515 self.assertRaises(Exc, repr, d)
516
Serhiy Storchaka1fb72d22017-12-03 22:12:11 +0200517 def test_repr_deep(self):
518 d = {}
519 for i in range(sys.getrecursionlimit() + 100):
520 d = {1: d}
521 self.assertRaises(RecursionError, repr, d)
522
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000523 def test_eq(self):
524 self.assertEqual({}, {})
Guido van Rossume2a383d2007-01-15 16:59:06 +0000525 self.assertEqual({1: 2}, {1: 2})
Walter Dörwald59b23e82004-09-30 13:46:00 +0000526
527 class Exc(Exception): pass
528
529 class BadCmp(object):
530 def __eq__(self, other):
531 raise Exc()
Guido van Rossum38938152006-08-21 23:36:26 +0000532 def __hash__(self):
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000533 return 1
Walter Dörwald59b23e82004-09-30 13:46:00 +0000534
535 d1 = {BadCmp(): 1}
536 d2 = {1: 1}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000537
538 with self.assertRaises(Exc):
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000539 d1 == d2
Walter Dörwald59b23e82004-09-30 13:46:00 +0000540
Guido van Rossumaac530c2007-08-24 22:33:45 +0000541 def test_keys_contained(self):
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000542 self.helper_keys_contained(lambda x: x.keys())
543 self.helper_keys_contained(lambda x: x.items())
544
545 def helper_keys_contained(self, fn):
Guido van Rossumaac530c2007-08-24 22:33:45 +0000546 # Test rich comparisons against dict key views, which should behave the
547 # same as sets.
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000548 empty = fn(dict())
549 empty2 = fn(dict())
550 smaller = fn({1:1, 2:2})
551 larger = fn({1:1, 2:2, 3:3})
552 larger2 = fn({1:1, 2:2, 3:3})
553 larger3 = fn({4:1, 2:2, 3:3})
Guido van Rossumaac530c2007-08-24 22:33:45 +0000554
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000555 self.assertTrue(smaller < larger)
556 self.assertTrue(smaller <= larger)
557 self.assertTrue(larger > smaller)
558 self.assertTrue(larger >= smaller)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000559
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000560 self.assertFalse(smaller >= larger)
561 self.assertFalse(smaller > larger)
562 self.assertFalse(larger <= smaller)
563 self.assertFalse(larger < smaller)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000564
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000565 self.assertFalse(smaller < larger3)
566 self.assertFalse(smaller <= larger3)
567 self.assertFalse(larger3 > smaller)
568 self.assertFalse(larger3 >= smaller)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000569
570 # Inequality strictness
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000571 self.assertTrue(larger2 >= larger)
572 self.assertTrue(larger2 <= larger)
573 self.assertFalse(larger2 > larger)
574 self.assertFalse(larger2 < larger)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000575
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000576 self.assertTrue(larger == larger2)
577 self.assertTrue(smaller != larger)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000578
579 # There is an optimization on the zero-element case.
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000580 self.assertTrue(empty == empty2)
581 self.assertFalse(empty != empty2)
582 self.assertFalse(empty == smaller)
583 self.assertTrue(empty != smaller)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000584
585 # With the same size, an elementwise compare happens
Guido van Rossumcf2ce362007-08-24 23:49:54 +0000586 self.assertTrue(larger != larger3)
587 self.assertFalse(larger == larger3)
Guido van Rossumaac530c2007-08-24 22:33:45 +0000588
589 def test_errors_in_view_containment_check(self):
590 class C:
591 def __eq__(self, other):
592 raise RuntimeError
Florent Xiclunaa988e422010-03-02 16:06:24 +0000593
Guido van Rossumaac530c2007-08-24 22:33:45 +0000594 d1 = {1: C()}
595 d2 = {1: C()}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000596 with self.assertRaises(RuntimeError):
597 d1.items() == d2.items()
598 with self.assertRaises(RuntimeError):
599 d1.items() != d2.items()
600 with self.assertRaises(RuntimeError):
601 d1.items() <= d2.items()
602 with self.assertRaises(RuntimeError):
603 d1.items() >= d2.items()
604
Guido van Rossumaac530c2007-08-24 22:33:45 +0000605 d3 = {1: C(), 2: C()}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000606 with self.assertRaises(RuntimeError):
607 d2.items() < d3.items()
608 with self.assertRaises(RuntimeError):
609 d3.items() > d2.items()
Guido van Rossumaac530c2007-08-24 22:33:45 +0000610
Guido van Rossumbe534712007-08-24 23:43:52 +0000611 def test_dictview_set_operations_on_keys(self):
Guido van Rossum523259b2007-08-24 23:41:22 +0000612 k1 = {1:1, 2:2}.keys()
613 k2 = {1:1, 2:2, 3:3}.keys()
614 k3 = {4:4}.keys()
615
Florent Xiclunaa988e422010-03-02 16:06:24 +0000616 self.assertEqual(k1 - k2, set())
617 self.assertEqual(k1 - k3, {1,2})
618 self.assertEqual(k2 - k1, {3})
619 self.assertEqual(k3 - k1, {4})
620 self.assertEqual(k1 & k2, {1,2})
621 self.assertEqual(k1 & k3, set())
622 self.assertEqual(k1 | k2, {1,2,3})
623 self.assertEqual(k1 ^ k2, {3})
624 self.assertEqual(k1 ^ k3, {1,2,4})
Guido van Rossum523259b2007-08-24 23:41:22 +0000625
Guido van Rossumbe534712007-08-24 23:43:52 +0000626 def test_dictview_set_operations_on_items(self):
627 k1 = {1:1, 2:2}.items()
628 k2 = {1:1, 2:2, 3:3}.items()
629 k3 = {4:4}.items()
630
Florent Xiclunaa988e422010-03-02 16:06:24 +0000631 self.assertEqual(k1 - k2, set())
632 self.assertEqual(k1 - k3, {(1,1), (2,2)})
633 self.assertEqual(k2 - k1, {(3,3)})
634 self.assertEqual(k3 - k1, {(4,4)})
635 self.assertEqual(k1 & k2, {(1,1), (2,2)})
636 self.assertEqual(k1 & k3, set())
637 self.assertEqual(k1 | k2, {(1,1), (2,2), (3,3)})
638 self.assertEqual(k1 ^ k2, {(3,3)})
639 self.assertEqual(k1 ^ k3, {(1,1), (2,2), (4,4)})
Guido van Rossum523259b2007-08-24 23:41:22 +0000640
Guido van Rossum1d719962007-08-24 23:47:30 +0000641 def test_dictview_mixed_set_operations(self):
642 # Just a few for .keys()
Guido van Rossuma401bbe2007-08-24 23:51:55 +0000643 self.assertTrue({1:1}.keys() == {1})
644 self.assertTrue({1} == {1:1}.keys())
Florent Xiclunaa988e422010-03-02 16:06:24 +0000645 self.assertEqual({1:1}.keys() | {2}, {1, 2})
646 self.assertEqual({2} | {1:1}.keys(), {1, 2})
Guido van Rossum1d719962007-08-24 23:47:30 +0000647 # And a few for .items()
Guido van Rossuma401bbe2007-08-24 23:51:55 +0000648 self.assertTrue({1:1}.items() == {(1,1)})
649 self.assertTrue({(1,1)} == {1:1}.items())
Florent Xiclunaa988e422010-03-02 16:06:24 +0000650 self.assertEqual({1:1}.items() | {2}, {(1,1), 2})
651 self.assertEqual({2} | {1:1}.items(), {(1,1), 2})
Guido van Rossum1d719962007-08-24 23:47:30 +0000652
Guido van Rossum1968ad32006-02-25 22:38:04 +0000653 def test_missing(self):
654 # Make sure dict doesn't have a __missing__ method
Florent Xiclunaa988e422010-03-02 16:06:24 +0000655 self.assertFalse(hasattr(dict, "__missing__"))
656 self.assertFalse(hasattr({}, "__missing__"))
Guido van Rossum1968ad32006-02-25 22:38:04 +0000657 # Test several cases:
658 # (D) subclass defines __missing__ method returning a value
659 # (E) subclass defines __missing__ method raising RuntimeError
660 # (F) subclass sets __missing__ instance variable (no effect)
Serhiy Storchakad65c9492015-11-02 14:10:23 +0200661 # (G) subclass doesn't define __missing__ at all
Guido van Rossum1968ad32006-02-25 22:38:04 +0000662 class D(dict):
663 def __missing__(self, key):
664 return 42
665 d = D({1: 2, 3: 4})
666 self.assertEqual(d[1], 2)
667 self.assertEqual(d[3], 4)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000668 self.assertNotIn(2, d)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000669 self.assertNotIn(2, d.keys())
Guido van Rossum1968ad32006-02-25 22:38:04 +0000670 self.assertEqual(d[2], 42)
Florent Xiclunaa988e422010-03-02 16:06:24 +0000671
Guido van Rossum1968ad32006-02-25 22:38:04 +0000672 class E(dict):
673 def __missing__(self, key):
674 raise RuntimeError(key)
675 e = E()
Florent Xiclunaa988e422010-03-02 16:06:24 +0000676 with self.assertRaises(RuntimeError) as c:
Guido van Rossum1968ad32006-02-25 22:38:04 +0000677 e[42]
Florent Xiclunaa988e422010-03-02 16:06:24 +0000678 self.assertEqual(c.exception.args, (42,))
679
Guido van Rossum1968ad32006-02-25 22:38:04 +0000680 class F(dict):
681 def __init__(self):
682 # An instance variable __missing__ should have no effect
683 self.__missing__ = lambda key: None
684 f = F()
Florent Xiclunaa988e422010-03-02 16:06:24 +0000685 with self.assertRaises(KeyError) as c:
Guido van Rossum1968ad32006-02-25 22:38:04 +0000686 f[42]
Florent Xiclunaa988e422010-03-02 16:06:24 +0000687 self.assertEqual(c.exception.args, (42,))
688
Guido van Rossum1968ad32006-02-25 22:38:04 +0000689 class G(dict):
690 pass
691 g = G()
Florent Xiclunaa988e422010-03-02 16:06:24 +0000692 with self.assertRaises(KeyError) as c:
Guido van Rossum1968ad32006-02-25 22:38:04 +0000693 g[42]
Florent Xiclunaa988e422010-03-02 16:06:24 +0000694 self.assertEqual(c.exception.args, (42,))
Guido van Rossum1968ad32006-02-25 22:38:04 +0000695
Thomas Wouters89f507f2006-12-13 04:49:30 +0000696 def test_tuple_keyerror(self):
697 # SF #1576657
698 d = {}
Florent Xiclunaa988e422010-03-02 16:06:24 +0000699 with self.assertRaises(KeyError) as c:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000700 d[(1,)]
Florent Xiclunaa988e422010-03-02 16:06:24 +0000701 self.assertEqual(c.exception.args, ((1,),))
Thomas Wouters89f507f2006-12-13 04:49:30 +0000702
Guido van Rossumd8faa362007-04-27 19:54:29 +0000703 def test_bad_key(self):
Mark Dickinsona56c4672009-01-27 18:17:45 +0000704 # Dictionary lookups should fail if __eq__() raises an exception.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000705 class CustomException(Exception):
706 pass
707
708 class BadDictKey:
709 def __hash__(self):
710 return hash(self.__class__)
711
712 def __eq__(self, other):
713 if isinstance(other, self.__class__):
714 raise CustomException
715 return other
716
717 d = {}
718 x1 = BadDictKey()
719 x2 = BadDictKey()
720 d[x1] = 1
721 for stmt in ['d[x2] = 2',
722 'z = d[x2]',
723 'x2 in d',
724 'd.get(x2)',
725 'd.setdefault(x2, 42)',
726 'd.pop(x2)',
727 'd.update({x2: 2})']:
Florent Xiclunaa988e422010-03-02 16:06:24 +0000728 with self.assertRaises(CustomException):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000729 exec(stmt, locals())
Guido van Rossumd8faa362007-04-27 19:54:29 +0000730
731 def test_resize1(self):
732 # Dict resizing bug, found by Jack Jansen in 2.2 CVS development.
733 # This version got an assert failure in debug build, infinite loop in
734 # release build. Unfortunately, provoking this kind of stuff requires
735 # a mix of inserts and deletes hitting exactly the right hash codes in
736 # exactly the right order, and I can't think of a randomized approach
737 # that would be *likely* to hit a failing case in reasonable time.
738
739 d = {}
740 for i in range(5):
741 d[i] = i
742 for i in range(5):
743 del d[i]
744 for i in range(5, 9): # i==8 was the problem
745 d[i] = i
746
747 def test_resize2(self):
748 # Another dict resizing bug (SF bug #1456209).
749 # This caused Segmentation faults or Illegal instructions.
750
751 class X(object):
752 def __hash__(self):
753 return 5
754 def __eq__(self, other):
755 if resizing:
756 d.clear()
757 return False
758 d = {}
759 resizing = False
760 d[X()] = 1
761 d[X()] = 2
762 d[X()] = 3
763 d[X()] = 4
764 d[X()] = 5
765 # now trigger a resize
766 resizing = True
767 d[9] = 6
768
Georg Brandl6aa2d1f2008-08-12 08:35:52 +0000769 def test_empty_presized_dict_in_freelist(self):
770 # Bug #3537: if an empty but presized dict with a size larger
771 # than 7 was in the freelist, it triggered an assertion failure
Florent Xiclunaa988e422010-03-02 16:06:24 +0000772 with self.assertRaises(ZeroDivisionError):
773 d = {'a': 1 // 0, 'b': None, 'c': None, 'd': None, 'e': None,
Georg Brandl6aa2d1f2008-08-12 08:35:52 +0000774 'f': None, 'g': None, 'h': None}
Georg Brandl6aa2d1f2008-08-12 08:35:52 +0000775 d = {}
776
Antoine Pitrou7ddda782009-01-01 15:35:33 +0000777 def test_container_iterator(self):
778 # Bug #3680: tp_traverse was not implemented for dictiter and
779 # dictview objects.
780 class C(object):
781 pass
782 views = (dict.items, dict.values, dict.keys)
783 for v in views:
784 obj = C()
785 ref = weakref.ref(obj)
786 container = {obj: 1}
787 obj.v = v(container)
788 obj.x = iter(obj.v)
789 del obj, container
790 gc.collect()
Florent Xiclunaa988e422010-03-02 16:06:24 +0000791 self.assertIs(ref(), None, "Cycle was not collected")
Georg Brandl6aa2d1f2008-08-12 08:35:52 +0000792
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000793 def _not_tracked(self, t):
794 # Nested containers can take several collections to untrack
795 gc.collect()
796 gc.collect()
797 self.assertFalse(gc.is_tracked(t), t)
798
799 def _tracked(self, t):
800 self.assertTrue(gc.is_tracked(t), t)
801 gc.collect()
802 gc.collect()
803 self.assertTrue(gc.is_tracked(t), t)
804
Benjamin Peterson3e5cd1d2010-06-27 21:45:24 +0000805 @support.cpython_only
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000806 def test_track_literals(self):
807 # Test GC-optimization of dict literals
808 x, y, z, w = 1.5, "a", (1, None), []
809
810 self._not_tracked({})
811 self._not_tracked({x:(), y:x, z:1})
812 self._not_tracked({1: "a", "b": 2})
813 self._not_tracked({1: 2, (None, True, False, ()): int})
814 self._not_tracked({1: object()})
815
816 # Dicts with mutable elements are always tracked, even if those
817 # elements are not tracked right now.
818 self._tracked({1: []})
819 self._tracked({1: ([],)})
820 self._tracked({1: {}})
821 self._tracked({1: set()})
822
Benjamin Peterson3e5cd1d2010-06-27 21:45:24 +0000823 @support.cpython_only
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000824 def test_track_dynamic(self):
825 # Test GC-optimization of dynamically-created dicts
826 class MyObject(object):
827 pass
828 x, y, z, w, o = 1.5, "a", (1, object()), [], MyObject()
829
830 d = dict()
831 self._not_tracked(d)
832 d[1] = "a"
833 self._not_tracked(d)
834 d[y] = 2
835 self._not_tracked(d)
836 d[z] = 3
837 self._not_tracked(d)
838 self._not_tracked(d.copy())
839 d[4] = w
840 self._tracked(d)
841 self._tracked(d.copy())
842 d[4] = None
843 self._not_tracked(d)
844 self._not_tracked(d.copy())
845
846 # dd isn't tracked right now, but it may mutate and therefore d
847 # which contains it must be tracked.
848 d = dict()
849 dd = dict()
850 d[1] = dd
851 self._not_tracked(dd)
852 self._tracked(d)
853 dd[1] = d
854 self._tracked(dd)
855
856 d = dict.fromkeys([x, y, z])
857 self._not_tracked(d)
858 dd = dict()
859 dd.update(d)
860 self._not_tracked(dd)
861 d = dict.fromkeys([x, y, z, o])
862 self._tracked(d)
863 dd = dict()
864 dd.update(d)
865 self._tracked(dd)
866
867 d = dict(x=x, y=y, z=z)
868 self._not_tracked(d)
869 d = dict(x=x, y=y, z=z, w=w)
870 self._tracked(d)
871 d = dict()
872 d.update(x=x, y=y, z=z)
873 self._not_tracked(d)
874 d.update(w=w)
875 self._tracked(d)
876
877 d = dict([(x, y), (z, 1)])
878 self._not_tracked(d)
879 d = dict([(x, y), (z, w)])
880 self._tracked(d)
881 d = dict()
882 d.update([(x, y), (z, 1)])
883 self._not_tracked(d)
884 d.update([(x, y), (z, w)])
885 self._tracked(d)
886
Benjamin Peterson3e5cd1d2010-06-27 21:45:24 +0000887 @support.cpython_only
Antoine Pitrou3a652b12009-03-23 18:52:06 +0000888 def test_track_subtypes(self):
889 # Dict subtypes are always tracked
890 class MyDict(dict):
891 pass
892 self._tracked(MyDict())
893
Victor Stinner78601a32016-09-09 19:28:36 -0700894 def make_shared_key_dict(self, n):
895 class C:
896 pass
897
898 dicts = []
899 for i in range(n):
900 a = C()
901 a.x, a.y, a.z = 1, 2, 3
902 dicts.append(a.__dict__)
903
904 return dicts
905
906 @support.cpython_only
INADA Naoki93f26f72016-11-02 18:45:16 +0900907 def test_splittable_setdefault(self):
908 """split table must be combined when setdefault()
909 breaks insertion order"""
910 a, b = self.make_shared_key_dict(2)
911
912 a['a'] = 1
913 size_a = sys.getsizeof(a)
914 a['b'] = 2
915 b.setdefault('b', 2)
916 size_b = sys.getsizeof(b)
917 b['a'] = 1
918
919 self.assertGreater(size_b, size_a)
920 self.assertEqual(list(a), ['x', 'y', 'z', 'a', 'b'])
921 self.assertEqual(list(b), ['x', 'y', 'z', 'b', 'a'])
922
923 @support.cpython_only
Victor Stinner78601a32016-09-09 19:28:36 -0700924 def test_splittable_del(self):
925 """split table must be combined when del d[k]"""
926 a, b = self.make_shared_key_dict(2)
927
928 orig_size = sys.getsizeof(a)
929
930 del a['y'] # split table is combined
931 with self.assertRaises(KeyError):
932 del a['y']
933
934 self.assertGreater(sys.getsizeof(a), orig_size)
935 self.assertEqual(list(a), ['x', 'z'])
936 self.assertEqual(list(b), ['x', 'y', 'z'])
937
938 # Two dicts have different insertion order.
939 a['y'] = 42
940 self.assertEqual(list(a), ['x', 'z', 'y'])
941 self.assertEqual(list(b), ['x', 'y', 'z'])
942
943 @support.cpython_only
944 def test_splittable_pop(self):
945 """split table must be combined when d.pop(k)"""
946 a, b = self.make_shared_key_dict(2)
947
948 orig_size = sys.getsizeof(a)
949
950 a.pop('y') # split table is combined
951 with self.assertRaises(KeyError):
952 a.pop('y')
953
954 self.assertGreater(sys.getsizeof(a), orig_size)
955 self.assertEqual(list(a), ['x', 'z'])
956 self.assertEqual(list(b), ['x', 'y', 'z'])
957
958 # Two dicts have different insertion order.
959 a['y'] = 42
960 self.assertEqual(list(a), ['x', 'z', 'y'])
961 self.assertEqual(list(b), ['x', 'y', 'z'])
962
963 @support.cpython_only
Victor Stinnerd0ad11f2016-09-13 16:56:38 +0200964 def test_splittable_pop_pending(self):
965 """pop a pending key in a splitted table should not crash"""
966 a, b = self.make_shared_key_dict(2)
967
968 a['a'] = 4
969 with self.assertRaises(KeyError):
970 b.pop('a')
971
972 @support.cpython_only
Victor Stinner78601a32016-09-09 19:28:36 -0700973 def test_splittable_popitem(self):
974 """split table must be combined when d.popitem()"""
975 a, b = self.make_shared_key_dict(2)
976
977 orig_size = sys.getsizeof(a)
978
979 item = a.popitem() # split table is combined
980 self.assertEqual(item, ('z', 3))
981 with self.assertRaises(KeyError):
982 del a['z']
983
984 self.assertGreater(sys.getsizeof(a), orig_size)
985 self.assertEqual(list(a), ['x', 'y'])
986 self.assertEqual(list(b), ['x', 'y', 'z'])
987
Victor Stinner3d3f2642016-12-15 17:21:23 +0100988 @support.cpython_only
989 def test_splittable_setattr_after_pop(self):
990 """setattr() must not convert combined table into split table."""
991 # Issue 28147
992 import _testcapi
993
994 class C:
995 pass
996 a = C()
997
998 a.a = 1
999 self.assertTrue(_testcapi.dict_hassplittable(a.__dict__))
1000
1001 # dict.pop() convert it to combined table
1002 a.__dict__.pop('a')
1003 self.assertFalse(_testcapi.dict_hassplittable(a.__dict__))
1004
1005 # But C should not convert a.__dict__ to split table again.
1006 a.a = 1
1007 self.assertFalse(_testcapi.dict_hassplittable(a.__dict__))
1008
1009 # Same for popitem()
1010 a = C()
1011 a.a = 2
1012 self.assertTrue(_testcapi.dict_hassplittable(a.__dict__))
1013 a.__dict__.popitem()
1014 self.assertFalse(_testcapi.dict_hassplittable(a.__dict__))
1015 a.a = 3
1016 self.assertFalse(_testcapi.dict_hassplittable(a.__dict__))
1017
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00001018 def test_iterator_pickling(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +02001019 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1020 data = {1:"a", 2:"b", 3:"c"}
1021 it = iter(data)
1022 d = pickle.dumps(it, proto)
1023 it = pickle.loads(d)
1024 self.assertEqual(sorted(it), sorted(data))
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00001025
Serhiy Storchakabad12572014-12-15 14:03:42 +02001026 it = pickle.loads(d)
1027 try:
1028 drop = next(it)
1029 except StopIteration:
1030 continue
1031 d = pickle.dumps(it, proto)
1032 it = pickle.loads(d)
1033 del data[drop]
1034 self.assertEqual(sorted(it), sorted(data))
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00001035
1036 def test_itemiterator_pickling(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +02001037 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1038 data = {1:"a", 2:"b", 3:"c"}
1039 # dictviews aren't picklable, only their iterators
1040 itorg = iter(data.items())
1041 d = pickle.dumps(itorg, proto)
1042 it = pickle.loads(d)
Martin Pantera90a4a92016-05-30 04:04:50 +00001043 # note that the type of the unpickled iterator
Serhiy Storchakabad12572014-12-15 14:03:42 +02001044 # is not necessarily the same as the original. It is
1045 # merely an object supporting the iterator protocol, yielding
1046 # the same objects as the original one.
1047 # self.assertEqual(type(itorg), type(it))
1048 self.assertIsInstance(it, collections.abc.Iterator)
1049 self.assertEqual(dict(it), data)
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00001050
Serhiy Storchakabad12572014-12-15 14:03:42 +02001051 it = pickle.loads(d)
1052 drop = next(it)
1053 d = pickle.dumps(it, proto)
1054 it = pickle.loads(d)
1055 del data[drop[0]]
1056 self.assertEqual(dict(it), data)
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00001057
1058 def test_valuesiterator_pickling(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +02001059 for proto in range(pickle.HIGHEST_PROTOCOL):
1060 data = {1:"a", 2:"b", 3:"c"}
1061 # data.values() isn't picklable, only its iterator
1062 it = iter(data.values())
1063 d = pickle.dumps(it, proto)
1064 it = pickle.loads(d)
1065 self.assertEqual(sorted(list(it)), sorted(list(data.values())))
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00001066
Serhiy Storchakabad12572014-12-15 14:03:42 +02001067 it = pickle.loads(d)
1068 drop = next(it)
1069 d = pickle.dumps(it, proto)
1070 it = pickle.loads(d)
1071 values = list(it) + [drop]
1072 self.assertEqual(sorted(values), sorted(list(data.values())))
Guido van Rossum1968ad32006-02-25 22:38:04 +00001073
Benjamin Petersondb780d02012-04-23 13:44:32 -04001074 def test_instance_dict_getattr_str_subclass(self):
1075 class Foo:
1076 def __init__(self, msg):
1077 self.msg = msg
1078 f = Foo('123')
1079 class _str(str):
1080 pass
1081 self.assertEqual(f.msg, getattr(f, _str('msg')))
1082 self.assertEqual(f.msg, f.__dict__[_str('msg')])
1083
Benjamin Peterson15ee8212012-04-24 14:44:18 -04001084 def test_object_set_item_single_instance_non_str_key(self):
1085 class Foo: pass
1086 f = Foo()
1087 f.__dict__[1] = 1
1088 f.a = 'a'
1089 self.assertEqual(f.__dict__, {1:1, 'a':'a'})
1090
Antoine Pitroud6967322014-10-18 00:35:00 +02001091 def check_reentrant_insertion(self, mutate):
1092 # This object will trigger mutation of the dict when replaced
1093 # by another value. Note this relies on refcounting: the test
1094 # won't achieve its purpose on fully-GCed Python implementations.
1095 class Mutating:
1096 def __del__(self):
1097 mutate(d)
1098
1099 d = {k: Mutating() for k in 'abcdefghijklmnopqr'}
1100 for k in list(d):
1101 d[k] = k
1102
1103 def test_reentrant_insertion(self):
1104 # Reentrant insertion shouldn't crash (see issue #22653)
1105 def mutate(d):
1106 d['b'] = 5
1107 self.check_reentrant_insertion(mutate)
1108
1109 def mutate(d):
1110 d.update(self.__dict__)
1111 d.clear()
1112 self.check_reentrant_insertion(mutate)
1113
1114 def mutate(d):
1115 while d:
1116 d.popitem()
1117 self.check_reentrant_insertion(mutate)
1118
Benjamin Petersona82f77f2015-07-04 19:55:16 -05001119 def test_merge_and_mutate(self):
1120 class X:
1121 def __hash__(self):
1122 return 0
1123
1124 def __eq__(self, o):
1125 other.clear()
1126 return False
1127
1128 l = [(i,0) for i in range(1, 1337)]
1129 other = dict(l)
1130 other[X()] = 0
1131 d = {X(): 0, 1: 1}
1132 self.assertRaises(RuntimeError, d.update, other)
Antoine Pitroud6967322014-10-18 00:35:00 +02001133
Serhiy Storchakafbb1c5e2016-03-30 20:40:02 +03001134 def test_free_after_iterating(self):
1135 support.check_free_after_iterating(self, iter, dict)
1136 support.check_free_after_iterating(self, lambda d: iter(d.keys()), dict)
1137 support.check_free_after_iterating(self, lambda d: iter(d.values()), dict)
1138 support.check_free_after_iterating(self, lambda d: iter(d.items()), dict)
1139
Serhiy Storchaka753bca32017-05-20 12:30:02 +03001140 def test_equal_operator_modifying_operand(self):
1141 # test fix for seg fault reported in issue 27945 part 3.
1142 class X():
1143 def __del__(self):
1144 dict_b.clear()
1145
1146 def __eq__(self, other):
1147 dict_a.clear()
1148 return True
1149
1150 def __hash__(self):
1151 return 13
1152
1153 dict_a = {X(): 0}
1154 dict_b = {X(): X()}
1155 self.assertTrue(dict_a == dict_b)
1156
1157 def test_fromkeys_operator_modifying_dict_operand(self):
1158 # test fix for seg fault reported in issue 27945 part 4a.
1159 class X(int):
1160 def __hash__(self):
1161 return 13
1162
1163 def __eq__(self, other):
1164 if len(d) > 1:
1165 d.clear()
1166 return False
1167
1168 d = {} # this is required to exist so that d can be constructed!
1169 d = {X(1): 1, X(2): 2}
1170 try:
1171 dict.fromkeys(d) # shouldn't crash
1172 except RuntimeError: # implementation defined
1173 pass
1174
1175 def test_fromkeys_operator_modifying_set_operand(self):
1176 # test fix for seg fault reported in issue 27945 part 4b.
1177 class X(int):
1178 def __hash__(self):
1179 return 13
1180
1181 def __eq__(self, other):
1182 if len(d) > 1:
1183 d.clear()
1184 return False
1185
1186 d = {} # this is required to exist so that d can be constructed!
1187 d = {X(1), X(2)}
1188 try:
1189 dict.fromkeys(d) # shouldn't crash
1190 except RuntimeError: # implementation defined
1191 pass
1192
1193 def test_dictitems_contains_use_after_free(self):
1194 class X:
1195 def __eq__(self, other):
1196 d.clear()
1197 return NotImplemented
1198
1199 d = {0: set()}
1200 (0, X()) in d.items()
1201
1202 def test_init_use_after_free(self):
1203 class X:
1204 def __hash__(self):
1205 pair[:] = []
1206 return 13
1207
1208 pair = [X(), 123]
1209 dict([pair])
1210
1211 def test_oob_indexing_dictiter_iternextitem(self):
1212 class X(int):
1213 def __del__(self):
1214 d.clear()
1215
1216 d = {i: X(i) for i in range(8)}
1217
1218 def iter_and_mutate():
1219 for result in d.items():
1220 if result[0] == 2:
1221 d[2] = None # free d[2] --> X(2).__del__ was called
1222
1223 self.assertRaises(RuntimeError, iter_and_mutate)
1224
Serhiy Storchakaf0b311b2016-11-06 13:18:24 +02001225
1226class CAPITest(unittest.TestCase):
1227
1228 # Test _PyDict_GetItem_KnownHash()
1229 @support.cpython_only
1230 def test_getitem_knownhash(self):
1231 from _testcapi import dict_getitem_knownhash
1232
1233 d = {'x': 1, 'y': 2, 'z': 3}
1234 self.assertEqual(dict_getitem_knownhash(d, 'x', hash('x')), 1)
1235 self.assertEqual(dict_getitem_knownhash(d, 'y', hash('y')), 2)
1236 self.assertEqual(dict_getitem_knownhash(d, 'z', hash('z')), 3)
1237
1238 # not a dict
1239 self.assertRaises(SystemError, dict_getitem_knownhash, [], 1, hash(1))
1240 # key does not exist
1241 self.assertRaises(KeyError, dict_getitem_knownhash, {}, 1, hash(1))
1242
1243 class Exc(Exception): pass
1244 class BadEq:
1245 def __eq__(self, other):
1246 raise Exc
1247 def __hash__(self):
1248 return 7
1249
1250 k1, k2 = BadEq(), BadEq()
1251 d = {k1: 1}
1252 self.assertEqual(dict_getitem_knownhash(d, k1, hash(k1)), 1)
1253 self.assertRaises(Exc, dict_getitem_knownhash, d, k2, hash(k2))
1254
1255
Neal Norwitzc3e54b82006-03-24 07:38:37 +00001256from test import mapping_tests
Raymond Hettinger49c522b2004-09-30 15:07:29 +00001257
1258class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1259 type2test = dict
1260
1261class Dict(dict):
1262 pass
1263
1264class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1265 type2test = Dict
1266
Victor Stinner5ebe2c82016-01-23 13:52:05 +01001267
Walter Dörwald59b23e82004-09-30 13:46:00 +00001268if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -05001269 unittest.main()