ยปCore Development>Code coverage>Lib/test/test_dict.py

Python code coverage for Lib/test/test_dict.py

#countcontent
1n/aimport collections
2n/aimport collections.abc
3n/aimport gc
4n/aimport pickle
5n/aimport random
6n/aimport string
7n/aimport sys
8n/aimport unittest
9n/aimport weakref
10n/afrom test import support
11n/a
12n/a
13n/aclass DictTest(unittest.TestCase):
14n/a
15n/a def test_invalid_keyword_arguments(self):
16n/a class Custom(dict):
17n/a pass
18n/a for invalid in {1 : 2}, Custom({1 : 2}):
19n/a with self.assertRaises(TypeError):
20n/a dict(**invalid)
21n/a with self.assertRaises(TypeError):
22n/a {}.update(**invalid)
23n/a
24n/a def test_constructor(self):
25n/a # calling built-in types without argument must return empty
26n/a self.assertEqual(dict(), {})
27n/a self.assertIsNot(dict(), {})
28n/a
29n/a def test_literal_constructor(self):
30n/a # check literal constructor for different sized dicts
31n/a # (to exercise the BUILD_MAP oparg).
32n/a for n in (0, 1, 6, 256, 400):
33n/a items = [(''.join(random.sample(string.ascii_letters, 8)), i)
34n/a for i in range(n)]
35n/a random.shuffle(items)
36n/a formatted_items = ('{!r}: {:d}'.format(k, v) for k, v in items)
37n/a dictliteral = '{' + ', '.join(formatted_items) + '}'
38n/a self.assertEqual(eval(dictliteral), dict(items))
39n/a
40n/a def test_bool(self):
41n/a self.assertIs(not {}, True)
42n/a self.assertTrue({1: 2})
43n/a self.assertIs(bool({}), False)
44n/a self.assertIs(bool({1: 2}), True)
45n/a
46n/a def test_keys(self):
47n/a d = {}
48n/a self.assertEqual(set(d.keys()), set())
49n/a d = {'a': 1, 'b': 2}
50n/a k = d.keys()
51n/a self.assertEqual(set(k), {'a', 'b'})
52n/a self.assertIn('a', k)
53n/a self.assertIn('b', k)
54n/a self.assertIn('a', d)
55n/a self.assertIn('b', d)
56n/a self.assertRaises(TypeError, d.keys, None)
57n/a self.assertEqual(repr(dict(a=1).keys()), "dict_keys(['a'])")
58n/a
59n/a def test_values(self):
60n/a d = {}
61n/a self.assertEqual(set(d.values()), set())
62n/a d = {1:2}
63n/a self.assertEqual(set(d.values()), {2})
64n/a self.assertRaises(TypeError, d.values, None)
65n/a self.assertEqual(repr(dict(a=1).values()), "dict_values([1])")
66n/a
67n/a def test_items(self):
68n/a d = {}
69n/a self.assertEqual(set(d.items()), set())
70n/a
71n/a d = {1:2}
72n/a self.assertEqual(set(d.items()), {(1, 2)})
73n/a self.assertRaises(TypeError, d.items, None)
74n/a self.assertEqual(repr(dict(a=1).items()), "dict_items([('a', 1)])")
75n/a
76n/a def test_contains(self):
77n/a d = {}
78n/a self.assertNotIn('a', d)
79n/a self.assertFalse('a' in d)
80n/a self.assertTrue('a' not in d)
81n/a d = {'a': 1, 'b': 2}
82n/a self.assertIn('a', d)
83n/a self.assertIn('b', d)
84n/a self.assertNotIn('c', d)
85n/a
86n/a self.assertRaises(TypeError, d.__contains__)
87n/a
88n/a def test_len(self):
89n/a d = {}
90n/a self.assertEqual(len(d), 0)
91n/a d = {'a': 1, 'b': 2}
92n/a self.assertEqual(len(d), 2)
93n/a
94n/a def test_getitem(self):
95n/a d = {'a': 1, 'b': 2}
96n/a self.assertEqual(d['a'], 1)
97n/a self.assertEqual(d['b'], 2)
98n/a d['c'] = 3
99n/a d['a'] = 4
100n/a self.assertEqual(d['c'], 3)
101n/a self.assertEqual(d['a'], 4)
102n/a del d['b']
103n/a self.assertEqual(d, {'a': 4, 'c': 3})
104n/a
105n/a self.assertRaises(TypeError, d.__getitem__)
106n/a
107n/a class BadEq(object):
108n/a def __eq__(self, other):
109n/a raise Exc()
110n/a def __hash__(self):
111n/a return 24
112n/a
113n/a d = {}
114n/a d[BadEq()] = 42
115n/a self.assertRaises(KeyError, d.__getitem__, 23)
116n/a
117n/a class Exc(Exception): pass
118n/a
119n/a class BadHash(object):
120n/a fail = False
121n/a def __hash__(self):
122n/a if self.fail:
123n/a raise Exc()
124n/a else:
125n/a return 42
126n/a
127n/a x = BadHash()
128n/a d[x] = 42
129n/a x.fail = True
130n/a self.assertRaises(Exc, d.__getitem__, x)
131n/a
132n/a def test_clear(self):
133n/a d = {1:1, 2:2, 3:3}
134n/a d.clear()
135n/a self.assertEqual(d, {})
136n/a
137n/a self.assertRaises(TypeError, d.clear, None)
138n/a
139n/a def test_update(self):
140n/a d = {}
141n/a d.update({1:100})
142n/a d.update({2:20})
143n/a d.update({1:1, 2:2, 3:3})
144n/a self.assertEqual(d, {1:1, 2:2, 3:3})
145n/a
146n/a d.update()
147n/a self.assertEqual(d, {1:1, 2:2, 3:3})
148n/a
149n/a self.assertRaises((TypeError, AttributeError), d.update, None)
150n/a
151n/a class SimpleUserDict:
152n/a def __init__(self):
153n/a self.d = {1:1, 2:2, 3:3}
154n/a def keys(self):
155n/a return self.d.keys()
156n/a def __getitem__(self, i):
157n/a return self.d[i]
158n/a d.clear()
159n/a d.update(SimpleUserDict())
160n/a self.assertEqual(d, {1:1, 2:2, 3:3})
161n/a
162n/a class Exc(Exception): pass
163n/a
164n/a d.clear()
165n/a class FailingUserDict:
166n/a def keys(self):
167n/a raise Exc
168n/a self.assertRaises(Exc, d.update, FailingUserDict())
169n/a
170n/a class FailingUserDict:
171n/a def keys(self):
172n/a class BogonIter:
173n/a def __init__(self):
174n/a self.i = 1
175n/a def __iter__(self):
176n/a return self
177n/a def __next__(self):
178n/a if self.i:
179n/a self.i = 0
180n/a return 'a'
181n/a raise Exc
182n/a return BogonIter()
183n/a def __getitem__(self, key):
184n/a return key
185n/a self.assertRaises(Exc, d.update, FailingUserDict())
186n/a
187n/a class FailingUserDict:
188n/a def keys(self):
189n/a class BogonIter:
190n/a def __init__(self):
191n/a self.i = ord('a')
192n/a def __iter__(self):
193n/a return self
194n/a def __next__(self):
195n/a if self.i <= ord('z'):
196n/a rtn = chr(self.i)
197n/a self.i += 1
198n/a return rtn
199n/a raise StopIteration
200n/a return BogonIter()
201n/a def __getitem__(self, key):
202n/a raise Exc
203n/a self.assertRaises(Exc, d.update, FailingUserDict())
204n/a
205n/a class badseq(object):
206n/a def __iter__(self):
207n/a return self
208n/a def __next__(self):
209n/a raise Exc()
210n/a
211n/a self.assertRaises(Exc, {}.update, badseq())
212n/a
213n/a self.assertRaises(ValueError, {}.update, [(1, 2, 3)])
214n/a
215n/a def test_fromkeys(self):
216n/a self.assertEqual(dict.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
217n/a d = {}
218n/a self.assertIsNot(d.fromkeys('abc'), d)
219n/a self.assertEqual(d.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
220n/a self.assertEqual(d.fromkeys((4,5),0), {4:0, 5:0})
221n/a self.assertEqual(d.fromkeys([]), {})
222n/a def g():
223n/a yield 1
224n/a self.assertEqual(d.fromkeys(g()), {1:None})
225n/a self.assertRaises(TypeError, {}.fromkeys, 3)
226n/a class dictlike(dict): pass
227n/a self.assertEqual(dictlike.fromkeys('a'), {'a':None})
228n/a self.assertEqual(dictlike().fromkeys('a'), {'a':None})
229n/a self.assertIsInstance(dictlike.fromkeys('a'), dictlike)
230n/a self.assertIsInstance(dictlike().fromkeys('a'), dictlike)
231n/a class mydict(dict):
232n/a def __new__(cls):
233n/a return collections.UserDict()
234n/a ud = mydict.fromkeys('ab')
235n/a self.assertEqual(ud, {'a':None, 'b':None})
236n/a self.assertIsInstance(ud, collections.UserDict)
237n/a self.assertRaises(TypeError, dict.fromkeys)
238n/a
239n/a class Exc(Exception): pass
240n/a
241n/a class baddict1(dict):
242n/a def __init__(self):
243n/a raise Exc()
244n/a
245n/a self.assertRaises(Exc, baddict1.fromkeys, [1])
246n/a
247n/a class BadSeq(object):
248n/a def __iter__(self):
249n/a return self
250n/a def __next__(self):
251n/a raise Exc()
252n/a
253n/a self.assertRaises(Exc, dict.fromkeys, BadSeq())
254n/a
255n/a class baddict2(dict):
256n/a def __setitem__(self, key, value):
257n/a raise Exc()
258n/a
259n/a self.assertRaises(Exc, baddict2.fromkeys, [1])
260n/a
261n/a # test fast path for dictionary inputs
262n/a d = dict(zip(range(6), range(6)))
263n/a self.assertEqual(dict.fromkeys(d, 0), dict(zip(range(6), [0]*6)))
264n/a
265n/a class baddict3(dict):
266n/a def __new__(cls):
267n/a return d
268n/a d = {i : i for i in range(10)}
269n/a res = d.copy()
270n/a res.update(a=None, b=None, c=None)
271n/a self.assertEqual(baddict3.fromkeys({"a", "b", "c"}), res)
272n/a
273n/a def test_copy(self):
274n/a d = {1:1, 2:2, 3:3}
275n/a self.assertEqual(d.copy(), {1:1, 2:2, 3:3})
276n/a self.assertEqual({}.copy(), {})
277n/a self.assertRaises(TypeError, d.copy, None)
278n/a
279n/a def test_get(self):
280n/a d = {}
281n/a self.assertIs(d.get('c'), None)
282n/a self.assertEqual(d.get('c', 3), 3)
283n/a d = {'a': 1, 'b': 2}
284n/a self.assertIs(d.get('c'), None)
285n/a self.assertEqual(d.get('c', 3), 3)
286n/a self.assertEqual(d.get('a'), 1)
287n/a self.assertEqual(d.get('a', 3), 1)
288n/a self.assertRaises(TypeError, d.get)
289n/a self.assertRaises(TypeError, d.get, None, None, None)
290n/a
291n/a def test_setdefault(self):
292n/a # dict.setdefault()
293n/a d = {}
294n/a self.assertIs(d.setdefault('key0'), None)
295n/a d.setdefault('key0', [])
296n/a self.assertIs(d.setdefault('key0'), None)
297n/a d.setdefault('key', []).append(3)
298n/a self.assertEqual(d['key'][0], 3)
299n/a d.setdefault('key', []).append(4)
300n/a self.assertEqual(len(d['key']), 2)
301n/a self.assertRaises(TypeError, d.setdefault)
302n/a
303n/a class Exc(Exception): pass
304n/a
305n/a class BadHash(object):
306n/a fail = False
307n/a def __hash__(self):
308n/a if self.fail:
309n/a raise Exc()
310n/a else:
311n/a return 42
312n/a
313n/a x = BadHash()
314n/a d[x] = 42
315n/a x.fail = True
316n/a self.assertRaises(Exc, d.setdefault, x, [])
317n/a
318n/a def test_setdefault_atomic(self):
319n/a # Issue #13521: setdefault() calls __hash__ and __eq__ only once.
320n/a class Hashed(object):
321n/a def __init__(self):
322n/a self.hash_count = 0
323n/a self.eq_count = 0
324n/a def __hash__(self):
325n/a self.hash_count += 1
326n/a return 42
327n/a def __eq__(self, other):
328n/a self.eq_count += 1
329n/a return id(self) == id(other)
330n/a hashed1 = Hashed()
331n/a y = {hashed1: 5}
332n/a hashed2 = Hashed()
333n/a y.setdefault(hashed2, [])
334n/a self.assertEqual(hashed1.hash_count, 1)
335n/a self.assertEqual(hashed2.hash_count, 1)
336n/a self.assertEqual(hashed1.eq_count + hashed2.eq_count, 1)
337n/a
338n/a def test_setitem_atomic_at_resize(self):
339n/a class Hashed(object):
340n/a def __init__(self):
341n/a self.hash_count = 0
342n/a self.eq_count = 0
343n/a def __hash__(self):
344n/a self.hash_count += 1
345n/a return 42
346n/a def __eq__(self, other):
347n/a self.eq_count += 1
348n/a return id(self) == id(other)
349n/a hashed1 = Hashed()
350n/a # 5 items
351n/a y = {hashed1: 5, 0: 0, 1: 1, 2: 2, 3: 3}
352n/a hashed2 = Hashed()
353n/a # 6th item forces a resize
354n/a y[hashed2] = []
355n/a self.assertEqual(hashed1.hash_count, 1)
356n/a self.assertEqual(hashed2.hash_count, 1)
357n/a self.assertEqual(hashed1.eq_count + hashed2.eq_count, 1)
358n/a
359n/a def test_popitem(self):
360n/a # dict.popitem()
361n/a for copymode in -1, +1:
362n/a # -1: b has same structure as a
363n/a # +1: b is a.copy()
364n/a for log2size in range(12):
365n/a size = 2**log2size
366n/a a = {}
367n/a b = {}
368n/a for i in range(size):
369n/a a[repr(i)] = i
370n/a if copymode < 0:
371n/a b[repr(i)] = i
372n/a if copymode > 0:
373n/a b = a.copy()
374n/a for i in range(size):
375n/a ka, va = ta = a.popitem()
376n/a self.assertEqual(va, int(ka))
377n/a kb, vb = tb = b.popitem()
378n/a self.assertEqual(vb, int(kb))
379n/a self.assertFalse(copymode < 0 and ta != tb)
380n/a self.assertFalse(a)
381n/a self.assertFalse(b)
382n/a
383n/a d = {}
384n/a self.assertRaises(KeyError, d.popitem)
385n/a
386n/a def test_pop(self):
387n/a # Tests for pop with specified key
388n/a d = {}
389n/a k, v = 'abc', 'def'
390n/a d[k] = v
391n/a self.assertRaises(KeyError, d.pop, 'ghi')
392n/a
393n/a self.assertEqual(d.pop(k), v)
394n/a self.assertEqual(len(d), 0)
395n/a
396n/a self.assertRaises(KeyError, d.pop, k)
397n/a
398n/a self.assertEqual(d.pop(k, v), v)
399n/a d[k] = v
400n/a self.assertEqual(d.pop(k, 1), v)
401n/a
402n/a self.assertRaises(TypeError, d.pop)
403n/a
404n/a class Exc(Exception): pass
405n/a
406n/a class BadHash(object):
407n/a fail = False
408n/a def __hash__(self):
409n/a if self.fail:
410n/a raise Exc()
411n/a else:
412n/a return 42
413n/a
414n/a x = BadHash()
415n/a d[x] = 42
416n/a x.fail = True
417n/a self.assertRaises(Exc, d.pop, x)
418n/a
419n/a def test_mutating_iteration(self):
420n/a # changing dict size during iteration
421n/a d = {}
422n/a d[1] = 1
423n/a with self.assertRaises(RuntimeError):
424n/a for i in d:
425n/a d[i+1] = 1
426n/a
427n/a def test_mutating_lookup(self):
428n/a # changing dict during a lookup (issue #14417)
429n/a class NastyKey:
430n/a mutate_dict = None
431n/a
432n/a def __init__(self, value):
433n/a self.value = value
434n/a
435n/a def __hash__(self):
436n/a # hash collision!
437n/a return 1
438n/a
439n/a def __eq__(self, other):
440n/a if NastyKey.mutate_dict:
441n/a mydict, key = NastyKey.mutate_dict
442n/a NastyKey.mutate_dict = None
443n/a del mydict[key]
444n/a return self.value == other.value
445n/a
446n/a key1 = NastyKey(1)
447n/a key2 = NastyKey(2)
448n/a d = {key1: 1}
449n/a NastyKey.mutate_dict = (d, key1)
450n/a d[key2] = 2
451n/a self.assertEqual(d, {key2: 2})
452n/a
453n/a def test_repr(self):
454n/a d = {}
455n/a self.assertEqual(repr(d), '{}')
456n/a d[1] = 2
457n/a self.assertEqual(repr(d), '{1: 2}')
458n/a d = {}
459n/a d[1] = d
460n/a self.assertEqual(repr(d), '{1: {...}}')
461n/a
462n/a class Exc(Exception): pass
463n/a
464n/a class BadRepr(object):
465n/a def __repr__(self):
466n/a raise Exc()
467n/a
468n/a d = {1: BadRepr()}
469n/a self.assertRaises(Exc, repr, d)
470n/a
471n/a def test_eq(self):
472n/a self.assertEqual({}, {})
473n/a self.assertEqual({1: 2}, {1: 2})
474n/a
475n/a class Exc(Exception): pass
476n/a
477n/a class BadCmp(object):
478n/a def __eq__(self, other):
479n/a raise Exc()
480n/a def __hash__(self):
481n/a return 1
482n/a
483n/a d1 = {BadCmp(): 1}
484n/a d2 = {1: 1}
485n/a
486n/a with self.assertRaises(Exc):
487n/a d1 == d2
488n/a
489n/a def test_keys_contained(self):
490n/a self.helper_keys_contained(lambda x: x.keys())
491n/a self.helper_keys_contained(lambda x: x.items())
492n/a
493n/a def helper_keys_contained(self, fn):
494n/a # Test rich comparisons against dict key views, which should behave the
495n/a # same as sets.
496n/a empty = fn(dict())
497n/a empty2 = fn(dict())
498n/a smaller = fn({1:1, 2:2})
499n/a larger = fn({1:1, 2:2, 3:3})
500n/a larger2 = fn({1:1, 2:2, 3:3})
501n/a larger3 = fn({4:1, 2:2, 3:3})
502n/a
503n/a self.assertTrue(smaller < larger)
504n/a self.assertTrue(smaller <= larger)
505n/a self.assertTrue(larger > smaller)
506n/a self.assertTrue(larger >= smaller)
507n/a
508n/a self.assertFalse(smaller >= larger)
509n/a self.assertFalse(smaller > larger)
510n/a self.assertFalse(larger <= smaller)
511n/a self.assertFalse(larger < smaller)
512n/a
513n/a self.assertFalse(smaller < larger3)
514n/a self.assertFalse(smaller <= larger3)
515n/a self.assertFalse(larger3 > smaller)
516n/a self.assertFalse(larger3 >= smaller)
517n/a
518n/a # Inequality strictness
519n/a self.assertTrue(larger2 >= larger)
520n/a self.assertTrue(larger2 <= larger)
521n/a self.assertFalse(larger2 > larger)
522n/a self.assertFalse(larger2 < larger)
523n/a
524n/a self.assertTrue(larger == larger2)
525n/a self.assertTrue(smaller != larger)
526n/a
527n/a # There is an optimization on the zero-element case.
528n/a self.assertTrue(empty == empty2)
529n/a self.assertFalse(empty != empty2)
530n/a self.assertFalse(empty == smaller)
531n/a self.assertTrue(empty != smaller)
532n/a
533n/a # With the same size, an elementwise compare happens
534n/a self.assertTrue(larger != larger3)
535n/a self.assertFalse(larger == larger3)
536n/a
537n/a def test_errors_in_view_containment_check(self):
538n/a class C:
539n/a def __eq__(self, other):
540n/a raise RuntimeError
541n/a
542n/a d1 = {1: C()}
543n/a d2 = {1: C()}
544n/a with self.assertRaises(RuntimeError):
545n/a d1.items() == d2.items()
546n/a with self.assertRaises(RuntimeError):
547n/a d1.items() != d2.items()
548n/a with self.assertRaises(RuntimeError):
549n/a d1.items() <= d2.items()
550n/a with self.assertRaises(RuntimeError):
551n/a d1.items() >= d2.items()
552n/a
553n/a d3 = {1: C(), 2: C()}
554n/a with self.assertRaises(RuntimeError):
555n/a d2.items() < d3.items()
556n/a with self.assertRaises(RuntimeError):
557n/a d3.items() > d2.items()
558n/a
559n/a def test_dictview_set_operations_on_keys(self):
560n/a k1 = {1:1, 2:2}.keys()
561n/a k2 = {1:1, 2:2, 3:3}.keys()
562n/a k3 = {4:4}.keys()
563n/a
564n/a self.assertEqual(k1 - k2, set())
565n/a self.assertEqual(k1 - k3, {1,2})
566n/a self.assertEqual(k2 - k1, {3})
567n/a self.assertEqual(k3 - k1, {4})
568n/a self.assertEqual(k1 & k2, {1,2})
569n/a self.assertEqual(k1 & k3, set())
570n/a self.assertEqual(k1 | k2, {1,2,3})
571n/a self.assertEqual(k1 ^ k2, {3})
572n/a self.assertEqual(k1 ^ k3, {1,2,4})
573n/a
574n/a def test_dictview_set_operations_on_items(self):
575n/a k1 = {1:1, 2:2}.items()
576n/a k2 = {1:1, 2:2, 3:3}.items()
577n/a k3 = {4:4}.items()
578n/a
579n/a self.assertEqual(k1 - k2, set())
580n/a self.assertEqual(k1 - k3, {(1,1), (2,2)})
581n/a self.assertEqual(k2 - k1, {(3,3)})
582n/a self.assertEqual(k3 - k1, {(4,4)})
583n/a self.assertEqual(k1 & k2, {(1,1), (2,2)})
584n/a self.assertEqual(k1 & k3, set())
585n/a self.assertEqual(k1 | k2, {(1,1), (2,2), (3,3)})
586n/a self.assertEqual(k1 ^ k2, {(3,3)})
587n/a self.assertEqual(k1 ^ k3, {(1,1), (2,2), (4,4)})
588n/a
589n/a def test_dictview_mixed_set_operations(self):
590n/a # Just a few for .keys()
591n/a self.assertTrue({1:1}.keys() == {1})
592n/a self.assertTrue({1} == {1:1}.keys())
593n/a self.assertEqual({1:1}.keys() | {2}, {1, 2})
594n/a self.assertEqual({2} | {1:1}.keys(), {1, 2})
595n/a # And a few for .items()
596n/a self.assertTrue({1:1}.items() == {(1,1)})
597n/a self.assertTrue({(1,1)} == {1:1}.items())
598n/a self.assertEqual({1:1}.items() | {2}, {(1,1), 2})
599n/a self.assertEqual({2} | {1:1}.items(), {(1,1), 2})
600n/a
601n/a def test_missing(self):
602n/a # Make sure dict doesn't have a __missing__ method
603n/a self.assertFalse(hasattr(dict, "__missing__"))
604n/a self.assertFalse(hasattr({}, "__missing__"))
605n/a # Test several cases:
606n/a # (D) subclass defines __missing__ method returning a value
607n/a # (E) subclass defines __missing__ method raising RuntimeError
608n/a # (F) subclass sets __missing__ instance variable (no effect)
609n/a # (G) subclass doesn't define __missing__ at all
610n/a class D(dict):
611n/a def __missing__(self, key):
612n/a return 42
613n/a d = D({1: 2, 3: 4})
614n/a self.assertEqual(d[1], 2)
615n/a self.assertEqual(d[3], 4)
616n/a self.assertNotIn(2, d)
617n/a self.assertNotIn(2, d.keys())
618n/a self.assertEqual(d[2], 42)
619n/a
620n/a class E(dict):
621n/a def __missing__(self, key):
622n/a raise RuntimeError(key)
623n/a e = E()
624n/a with self.assertRaises(RuntimeError) as c:
625n/a e[42]
626n/a self.assertEqual(c.exception.args, (42,))
627n/a
628n/a class F(dict):
629n/a def __init__(self):
630n/a # An instance variable __missing__ should have no effect
631n/a self.__missing__ = lambda key: None
632n/a f = F()
633n/a with self.assertRaises(KeyError) as c:
634n/a f[42]
635n/a self.assertEqual(c.exception.args, (42,))
636n/a
637n/a class G(dict):
638n/a pass
639n/a g = G()
640n/a with self.assertRaises(KeyError) as c:
641n/a g[42]
642n/a self.assertEqual(c.exception.args, (42,))
643n/a
644n/a def test_tuple_keyerror(self):
645n/a # SF #1576657
646n/a d = {}
647n/a with self.assertRaises(KeyError) as c:
648n/a d[(1,)]
649n/a self.assertEqual(c.exception.args, ((1,),))
650n/a
651n/a def test_bad_key(self):
652n/a # Dictionary lookups should fail if __eq__() raises an exception.
653n/a class CustomException(Exception):
654n/a pass
655n/a
656n/a class BadDictKey:
657n/a def __hash__(self):
658n/a return hash(self.__class__)
659n/a
660n/a def __eq__(self, other):
661n/a if isinstance(other, self.__class__):
662n/a raise CustomException
663n/a return other
664n/a
665n/a d = {}
666n/a x1 = BadDictKey()
667n/a x2 = BadDictKey()
668n/a d[x1] = 1
669n/a for stmt in ['d[x2] = 2',
670n/a 'z = d[x2]',
671n/a 'x2 in d',
672n/a 'd.get(x2)',
673n/a 'd.setdefault(x2, 42)',
674n/a 'd.pop(x2)',
675n/a 'd.update({x2: 2})']:
676n/a with self.assertRaises(CustomException):
677n/a exec(stmt, locals())
678n/a
679n/a def test_resize1(self):
680n/a # Dict resizing bug, found by Jack Jansen in 2.2 CVS development.
681n/a # This version got an assert failure in debug build, infinite loop in
682n/a # release build. Unfortunately, provoking this kind of stuff requires
683n/a # a mix of inserts and deletes hitting exactly the right hash codes in
684n/a # exactly the right order, and I can't think of a randomized approach
685n/a # that would be *likely* to hit a failing case in reasonable time.
686n/a
687n/a d = {}
688n/a for i in range(5):
689n/a d[i] = i
690n/a for i in range(5):
691n/a del d[i]
692n/a for i in range(5, 9): # i==8 was the problem
693n/a d[i] = i
694n/a
695n/a def test_resize2(self):
696n/a # Another dict resizing bug (SF bug #1456209).
697n/a # This caused Segmentation faults or Illegal instructions.
698n/a
699n/a class X(object):
700n/a def __hash__(self):
701n/a return 5
702n/a def __eq__(self, other):
703n/a if resizing:
704n/a d.clear()
705n/a return False
706n/a d = {}
707n/a resizing = False
708n/a d[X()] = 1
709n/a d[X()] = 2
710n/a d[X()] = 3
711n/a d[X()] = 4
712n/a d[X()] = 5
713n/a # now trigger a resize
714n/a resizing = True
715n/a d[9] = 6
716n/a
717n/a def test_empty_presized_dict_in_freelist(self):
718n/a # Bug #3537: if an empty but presized dict with a size larger
719n/a # than 7 was in the freelist, it triggered an assertion failure
720n/a with self.assertRaises(ZeroDivisionError):
721n/a d = {'a': 1 // 0, 'b': None, 'c': None, 'd': None, 'e': None,
722n/a 'f': None, 'g': None, 'h': None}
723n/a d = {}
724n/a
725n/a def test_container_iterator(self):
726n/a # Bug #3680: tp_traverse was not implemented for dictiter and
727n/a # dictview objects.
728n/a class C(object):
729n/a pass
730n/a views = (dict.items, dict.values, dict.keys)
731n/a for v in views:
732n/a obj = C()
733n/a ref = weakref.ref(obj)
734n/a container = {obj: 1}
735n/a obj.v = v(container)
736n/a obj.x = iter(obj.v)
737n/a del obj, container
738n/a gc.collect()
739n/a self.assertIs(ref(), None, "Cycle was not collected")
740n/a
741n/a def _not_tracked(self, t):
742n/a # Nested containers can take several collections to untrack
743n/a gc.collect()
744n/a gc.collect()
745n/a self.assertFalse(gc.is_tracked(t), t)
746n/a
747n/a def _tracked(self, t):
748n/a self.assertTrue(gc.is_tracked(t), t)
749n/a gc.collect()
750n/a gc.collect()
751n/a self.assertTrue(gc.is_tracked(t), t)
752n/a
753n/a @support.cpython_only
754n/a def test_track_literals(self):
755n/a # Test GC-optimization of dict literals
756n/a x, y, z, w = 1.5, "a", (1, None), []
757n/a
758n/a self._not_tracked({})
759n/a self._not_tracked({x:(), y:x, z:1})
760n/a self._not_tracked({1: "a", "b": 2})
761n/a self._not_tracked({1: 2, (None, True, False, ()): int})
762n/a self._not_tracked({1: object()})
763n/a
764n/a # Dicts with mutable elements are always tracked, even if those
765n/a # elements are not tracked right now.
766n/a self._tracked({1: []})
767n/a self._tracked({1: ([],)})
768n/a self._tracked({1: {}})
769n/a self._tracked({1: set()})
770n/a
771n/a @support.cpython_only
772n/a def test_track_dynamic(self):
773n/a # Test GC-optimization of dynamically-created dicts
774n/a class MyObject(object):
775n/a pass
776n/a x, y, z, w, o = 1.5, "a", (1, object()), [], MyObject()
777n/a
778n/a d = dict()
779n/a self._not_tracked(d)
780n/a d[1] = "a"
781n/a self._not_tracked(d)
782n/a d[y] = 2
783n/a self._not_tracked(d)
784n/a d[z] = 3
785n/a self._not_tracked(d)
786n/a self._not_tracked(d.copy())
787n/a d[4] = w
788n/a self._tracked(d)
789n/a self._tracked(d.copy())
790n/a d[4] = None
791n/a self._not_tracked(d)
792n/a self._not_tracked(d.copy())
793n/a
794n/a # dd isn't tracked right now, but it may mutate and therefore d
795n/a # which contains it must be tracked.
796n/a d = dict()
797n/a dd = dict()
798n/a d[1] = dd
799n/a self._not_tracked(dd)
800n/a self._tracked(d)
801n/a dd[1] = d
802n/a self._tracked(dd)
803n/a
804n/a d = dict.fromkeys([x, y, z])
805n/a self._not_tracked(d)
806n/a dd = dict()
807n/a dd.update(d)
808n/a self._not_tracked(dd)
809n/a d = dict.fromkeys([x, y, z, o])
810n/a self._tracked(d)
811n/a dd = dict()
812n/a dd.update(d)
813n/a self._tracked(dd)
814n/a
815n/a d = dict(x=x, y=y, z=z)
816n/a self._not_tracked(d)
817n/a d = dict(x=x, y=y, z=z, w=w)
818n/a self._tracked(d)
819n/a d = dict()
820n/a d.update(x=x, y=y, z=z)
821n/a self._not_tracked(d)
822n/a d.update(w=w)
823n/a self._tracked(d)
824n/a
825n/a d = dict([(x, y), (z, 1)])
826n/a self._not_tracked(d)
827n/a d = dict([(x, y), (z, w)])
828n/a self._tracked(d)
829n/a d = dict()
830n/a d.update([(x, y), (z, 1)])
831n/a self._not_tracked(d)
832n/a d.update([(x, y), (z, w)])
833n/a self._tracked(d)
834n/a
835n/a @support.cpython_only
836n/a def test_track_subtypes(self):
837n/a # Dict subtypes are always tracked
838n/a class MyDict(dict):
839n/a pass
840n/a self._tracked(MyDict())
841n/a
842n/a def make_shared_key_dict(self, n):
843n/a class C:
844n/a pass
845n/a
846n/a dicts = []
847n/a for i in range(n):
848n/a a = C()
849n/a a.x, a.y, a.z = 1, 2, 3
850n/a dicts.append(a.__dict__)
851n/a
852n/a return dicts
853n/a
854n/a @support.cpython_only
855n/a def test_splittable_setdefault(self):
856n/a """split table must be combined when setdefault()
857n/a breaks insertion order"""
858n/a a, b = self.make_shared_key_dict(2)
859n/a
860n/a a['a'] = 1
861n/a size_a = sys.getsizeof(a)
862n/a a['b'] = 2
863n/a b.setdefault('b', 2)
864n/a size_b = sys.getsizeof(b)
865n/a b['a'] = 1
866n/a
867n/a self.assertGreater(size_b, size_a)
868n/a self.assertEqual(list(a), ['x', 'y', 'z', 'a', 'b'])
869n/a self.assertEqual(list(b), ['x', 'y', 'z', 'b', 'a'])
870n/a
871n/a @support.cpython_only
872n/a def test_splittable_del(self):
873n/a """split table must be combined when del d[k]"""
874n/a a, b = self.make_shared_key_dict(2)
875n/a
876n/a orig_size = sys.getsizeof(a)
877n/a
878n/a del a['y'] # split table is combined
879n/a with self.assertRaises(KeyError):
880n/a del a['y']
881n/a
882n/a self.assertGreater(sys.getsizeof(a), orig_size)
883n/a self.assertEqual(list(a), ['x', 'z'])
884n/a self.assertEqual(list(b), ['x', 'y', 'z'])
885n/a
886n/a # Two dicts have different insertion order.
887n/a a['y'] = 42
888n/a self.assertEqual(list(a), ['x', 'z', 'y'])
889n/a self.assertEqual(list(b), ['x', 'y', 'z'])
890n/a
891n/a @support.cpython_only
892n/a def test_splittable_pop(self):
893n/a """split table must be combined when d.pop(k)"""
894n/a a, b = self.make_shared_key_dict(2)
895n/a
896n/a orig_size = sys.getsizeof(a)
897n/a
898n/a a.pop('y') # split table is combined
899n/a with self.assertRaises(KeyError):
900n/a a.pop('y')
901n/a
902n/a self.assertGreater(sys.getsizeof(a), orig_size)
903n/a self.assertEqual(list(a), ['x', 'z'])
904n/a self.assertEqual(list(b), ['x', 'y', 'z'])
905n/a
906n/a # Two dicts have different insertion order.
907n/a a['y'] = 42
908n/a self.assertEqual(list(a), ['x', 'z', 'y'])
909n/a self.assertEqual(list(b), ['x', 'y', 'z'])
910n/a
911n/a @support.cpython_only
912n/a def test_splittable_pop_pending(self):
913n/a """pop a pending key in a splitted table should not crash"""
914n/a a, b = self.make_shared_key_dict(2)
915n/a
916n/a a['a'] = 4
917n/a with self.assertRaises(KeyError):
918n/a b.pop('a')
919n/a
920n/a @support.cpython_only
921n/a def test_splittable_popitem(self):
922n/a """split table must be combined when d.popitem()"""
923n/a a, b = self.make_shared_key_dict(2)
924n/a
925n/a orig_size = sys.getsizeof(a)
926n/a
927n/a item = a.popitem() # split table is combined
928n/a self.assertEqual(item, ('z', 3))
929n/a with self.assertRaises(KeyError):
930n/a del a['z']
931n/a
932n/a self.assertGreater(sys.getsizeof(a), orig_size)
933n/a self.assertEqual(list(a), ['x', 'y'])
934n/a self.assertEqual(list(b), ['x', 'y', 'z'])
935n/a
936n/a @support.cpython_only
937n/a def test_splittable_setattr_after_pop(self):
938n/a """setattr() must not convert combined table into split table."""
939n/a # Issue 28147
940n/a import _testcapi
941n/a
942n/a class C:
943n/a pass
944n/a a = C()
945n/a
946n/a a.a = 1
947n/a self.assertTrue(_testcapi.dict_hassplittable(a.__dict__))
948n/a
949n/a # dict.pop() convert it to combined table
950n/a a.__dict__.pop('a')
951n/a self.assertFalse(_testcapi.dict_hassplittable(a.__dict__))
952n/a
953n/a # But C should not convert a.__dict__ to split table again.
954n/a a.a = 1
955n/a self.assertFalse(_testcapi.dict_hassplittable(a.__dict__))
956n/a
957n/a # Same for popitem()
958n/a a = C()
959n/a a.a = 2
960n/a self.assertTrue(_testcapi.dict_hassplittable(a.__dict__))
961n/a a.__dict__.popitem()
962n/a self.assertFalse(_testcapi.dict_hassplittable(a.__dict__))
963n/a a.a = 3
964n/a self.assertFalse(_testcapi.dict_hassplittable(a.__dict__))
965n/a
966n/a def test_iterator_pickling(self):
967n/a for proto in range(pickle.HIGHEST_PROTOCOL + 1):
968n/a data = {1:"a", 2:"b", 3:"c"}
969n/a it = iter(data)
970n/a d = pickle.dumps(it, proto)
971n/a it = pickle.loads(d)
972n/a self.assertEqual(sorted(it), sorted(data))
973n/a
974n/a it = pickle.loads(d)
975n/a try:
976n/a drop = next(it)
977n/a except StopIteration:
978n/a continue
979n/a d = pickle.dumps(it, proto)
980n/a it = pickle.loads(d)
981n/a del data[drop]
982n/a self.assertEqual(sorted(it), sorted(data))
983n/a
984n/a def test_itemiterator_pickling(self):
985n/a for proto in range(pickle.HIGHEST_PROTOCOL + 1):
986n/a data = {1:"a", 2:"b", 3:"c"}
987n/a # dictviews aren't picklable, only their iterators
988n/a itorg = iter(data.items())
989n/a d = pickle.dumps(itorg, proto)
990n/a it = pickle.loads(d)
991n/a # note that the type of the unpickled iterator
992n/a # is not necessarily the same as the original. It is
993n/a # merely an object supporting the iterator protocol, yielding
994n/a # the same objects as the original one.
995n/a # self.assertEqual(type(itorg), type(it))
996n/a self.assertIsInstance(it, collections.abc.Iterator)
997n/a self.assertEqual(dict(it), data)
998n/a
999n/a it = pickle.loads(d)
1000n/a drop = next(it)
1001n/a d = pickle.dumps(it, proto)
1002n/a it = pickle.loads(d)
1003n/a del data[drop[0]]
1004n/a self.assertEqual(dict(it), data)
1005n/a
1006n/a def test_valuesiterator_pickling(self):
1007n/a for proto in range(pickle.HIGHEST_PROTOCOL):
1008n/a data = {1:"a", 2:"b", 3:"c"}
1009n/a # data.values() isn't picklable, only its iterator
1010n/a it = iter(data.values())
1011n/a d = pickle.dumps(it, proto)
1012n/a it = pickle.loads(d)
1013n/a self.assertEqual(sorted(list(it)), sorted(list(data.values())))
1014n/a
1015n/a it = pickle.loads(d)
1016n/a drop = next(it)
1017n/a d = pickle.dumps(it, proto)
1018n/a it = pickle.loads(d)
1019n/a values = list(it) + [drop]
1020n/a self.assertEqual(sorted(values), sorted(list(data.values())))
1021n/a
1022n/a def test_instance_dict_getattr_str_subclass(self):
1023n/a class Foo:
1024n/a def __init__(self, msg):
1025n/a self.msg = msg
1026n/a f = Foo('123')
1027n/a class _str(str):
1028n/a pass
1029n/a self.assertEqual(f.msg, getattr(f, _str('msg')))
1030n/a self.assertEqual(f.msg, f.__dict__[_str('msg')])
1031n/a
1032n/a def test_object_set_item_single_instance_non_str_key(self):
1033n/a class Foo: pass
1034n/a f = Foo()
1035n/a f.__dict__[1] = 1
1036n/a f.a = 'a'
1037n/a self.assertEqual(f.__dict__, {1:1, 'a':'a'})
1038n/a
1039n/a def check_reentrant_insertion(self, mutate):
1040n/a # This object will trigger mutation of the dict when replaced
1041n/a # by another value. Note this relies on refcounting: the test
1042n/a # won't achieve its purpose on fully-GCed Python implementations.
1043n/a class Mutating:
1044n/a def __del__(self):
1045n/a mutate(d)
1046n/a
1047n/a d = {k: Mutating() for k in 'abcdefghijklmnopqr'}
1048n/a for k in list(d):
1049n/a d[k] = k
1050n/a
1051n/a def test_reentrant_insertion(self):
1052n/a # Reentrant insertion shouldn't crash (see issue #22653)
1053n/a def mutate(d):
1054n/a d['b'] = 5
1055n/a self.check_reentrant_insertion(mutate)
1056n/a
1057n/a def mutate(d):
1058n/a d.update(self.__dict__)
1059n/a d.clear()
1060n/a self.check_reentrant_insertion(mutate)
1061n/a
1062n/a def mutate(d):
1063n/a while d:
1064n/a d.popitem()
1065n/a self.check_reentrant_insertion(mutate)
1066n/a
1067n/a def test_merge_and_mutate(self):
1068n/a class X:
1069n/a def __hash__(self):
1070n/a return 0
1071n/a
1072n/a def __eq__(self, o):
1073n/a other.clear()
1074n/a return False
1075n/a
1076n/a l = [(i,0) for i in range(1, 1337)]
1077n/a other = dict(l)
1078n/a other[X()] = 0
1079n/a d = {X(): 0, 1: 1}
1080n/a self.assertRaises(RuntimeError, d.update, other)
1081n/a
1082n/a def test_free_after_iterating(self):
1083n/a support.check_free_after_iterating(self, iter, dict)
1084n/a support.check_free_after_iterating(self, lambda d: iter(d.keys()), dict)
1085n/a support.check_free_after_iterating(self, lambda d: iter(d.values()), dict)
1086n/a support.check_free_after_iterating(self, lambda d: iter(d.items()), dict)
1087n/a
1088n/a
1089n/aclass CAPITest(unittest.TestCase):
1090n/a
1091n/a # Test _PyDict_GetItem_KnownHash()
1092n/a @support.cpython_only
1093n/a def test_getitem_knownhash(self):
1094n/a from _testcapi import dict_getitem_knownhash
1095n/a
1096n/a d = {'x': 1, 'y': 2, 'z': 3}
1097n/a self.assertEqual(dict_getitem_knownhash(d, 'x', hash('x')), 1)
1098n/a self.assertEqual(dict_getitem_knownhash(d, 'y', hash('y')), 2)
1099n/a self.assertEqual(dict_getitem_knownhash(d, 'z', hash('z')), 3)
1100n/a
1101n/a # not a dict
1102n/a self.assertRaises(SystemError, dict_getitem_knownhash, [], 1, hash(1))
1103n/a # key does not exist
1104n/a self.assertRaises(KeyError, dict_getitem_knownhash, {}, 1, hash(1))
1105n/a
1106n/a class Exc(Exception): pass
1107n/a class BadEq:
1108n/a def __eq__(self, other):
1109n/a raise Exc
1110n/a def __hash__(self):
1111n/a return 7
1112n/a
1113n/a k1, k2 = BadEq(), BadEq()
1114n/a d = {k1: 1}
1115n/a self.assertEqual(dict_getitem_knownhash(d, k1, hash(k1)), 1)
1116n/a self.assertRaises(Exc, dict_getitem_knownhash, d, k2, hash(k2))
1117n/a
1118n/a
1119n/afrom test import mapping_tests
1120n/a
1121n/aclass GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1122n/a type2test = dict
1123n/a
1124n/aclass Dict(dict):
1125n/a pass
1126n/a
1127n/aclass SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1128n/a type2test = Dict
1129n/a
1130n/a
1131n/aif __name__ == "__main__":
1132n/a unittest.main()