2 from test
import test_support
4 import UserDict
, random
, string
8 class DictTest(unittest
.TestCase
):
9 def test_constructor(self
):
10 # calling built-in types without argument must return empty
11 self
.assertEqual(dict(), {})
12 self
.assertTrue(dict() is not {})
14 def test_literal_constructor(self
):
15 # check literal constructor for different sized dicts (to exercise the BUILD_MAP oparg
16 for n
in (0, 1, 6, 256, 400):
17 items
= [(''.join([random
.choice(string
.letters
)
22 dictliteral
= '{' + ', '.join('%r: %d' % item
for item
in items
) + '}'
23 self
.assertEqual(eval(dictliteral
), dict(items
))
26 self
.assertTrue(not {})
27 self
.assertTrue({1: 2})
28 self
.assertTrue(bool({}) is False)
29 self
.assertTrue(bool({1: 2}) is True)
33 self
.assertEqual(d
.keys(), [])
36 self
.assertTrue(d
.has_key('a'))
37 self
.assertTrue(d
.has_key('b'))
39 self
.assertRaises(TypeError, d
.keys
, None)
41 def test_values(self
):
43 self
.assertEqual(d
.values(), [])
45 self
.assertEqual(d
.values(), [2])
47 self
.assertRaises(TypeError, d
.values
, None)
51 self
.assertEqual(d
.items(), [])
54 self
.assertEqual(d
.items(), [(1, 2)])
56 self
.assertRaises(TypeError, d
.items
, None)
58 def test_has_key(self
):
60 self
.assertTrue(not d
.has_key('a'))
64 self
.assertEqual(k
, ['a', 'b'])
66 self
.assertRaises(TypeError, d
.has_key
)
68 def test_contains(self
):
70 self
.assertTrue(not ('a' in d
))
71 self
.assertTrue('a' not in d
)
73 self
.assertTrue('a' in d
)
74 self
.assertTrue('b' in d
)
75 self
.assertTrue('c' not in d
)
77 self
.assertRaises(TypeError, d
.__contains
__)
81 self
.assertEqual(len(d
), 0)
83 self
.assertEqual(len(d
), 2)
85 def test_getitem(self
):
87 self
.assertEqual(d
['a'], 1)
88 self
.assertEqual(d
['b'], 2)
91 self
.assertEqual(d
['c'], 3)
92 self
.assertEqual(d
['a'], 4)
94 self
.assertEqual(d
, {'a': 4, 'c': 3})
96 self
.assertRaises(TypeError, d
.__getitem
__)
99 def __eq__(self
, other
):
106 self
.assertRaises(KeyError, d
.__getitem
__, 23)
108 class Exc(Exception): pass
110 class BadHash(object):
121 self
.assertRaises(Exc
, d
.__getitem
__, x
)
123 def test_clear(self
):
126 self
.assertEqual(d
, {})
128 self
.assertRaises(TypeError, d
.clear
, None)
130 def test_update(self
):
134 d
.update({1:1, 2:2, 3:3})
135 self
.assertEqual(d
, {1:1, 2:2, 3:3})
138 self
.assertEqual(d
, {1:1, 2:2, 3:3})
140 self
.assertRaises((TypeError, AttributeError), d
.update
, None)
142 class SimpleUserDict
:
144 self
.d
= {1:1, 2:2, 3:3}
147 def __getitem__(self
, i
):
150 d
.update(SimpleUserDict())
151 self
.assertEqual(d
, {1:1, 2:2, 3:3})
153 class Exc(Exception): pass
156 class FailingUserDict
:
159 self
.assertRaises(Exc
, d
.update
, FailingUserDict())
161 class FailingUserDict
:
174 def __getitem__(self
, key
):
176 self
.assertRaises(Exc
, d
.update
, FailingUserDict())
178 class FailingUserDict
:
186 if self
.i
<= ord('z'):
192 def __getitem__(self
, key
):
194 self
.assertRaises(Exc
, d
.update
, FailingUserDict())
196 class badseq(object):
202 self
.assertRaises(Exc
, {}.update
, badseq())
204 self
.assertRaises(ValueError, {}.update
, [(1, 2, 3)])
206 def test_fromkeys(self
):
207 self
.assertEqual(dict.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
209 self
.assertTrue(not(d
.fromkeys('abc') is d
))
210 self
.assertEqual(d
.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
211 self
.assertEqual(d
.fromkeys((4,5),0), {4:0, 5:0})
212 self
.assertEqual(d
.fromkeys([]), {})
215 self
.assertEqual(d
.fromkeys(g()), {1:None})
216 self
.assertRaises(TypeError, {}.fromkeys
, 3)
217 class dictlike(dict): pass
218 self
.assertEqual(dictlike
.fromkeys('a'), {'a':None})
219 self
.assertEqual(dictlike().fromkeys('a'), {'a':None})
220 self
.assertTrue(type(dictlike
.fromkeys('a')) is dictlike
)
221 self
.assertTrue(type(dictlike().fromkeys('a')) is dictlike
)
224 return UserDict
.UserDict()
225 ud
= mydict
.fromkeys('ab')
226 self
.assertEqual(ud
, {'a':None, 'b':None})
227 self
.assertTrue(isinstance(ud
, UserDict
.UserDict
))
228 self
.assertRaises(TypeError, dict.fromkeys
)
230 class Exc(Exception): pass
232 class baddict1(dict):
236 self
.assertRaises(Exc
, baddict1
.fromkeys
, [1])
238 class BadSeq(object):
244 self
.assertRaises(Exc
, dict.fromkeys
, BadSeq())
246 class baddict2(dict):
247 def __setitem__(self
, key
, value
):
250 self
.assertRaises(Exc
, baddict2
.fromkeys
, [1])
252 # test fast path for dictionary inputs
253 d
= dict(zip(range(6), range(6)))
254 self
.assertEqual(dict.fromkeys(d
, 0), dict(zip(range(6), [0]*6)))
258 self
.assertEqual(d
.copy(), {1:1, 2:2, 3:3})
259 self
.assertEqual({}.copy(), {})
260 self
.assertRaises(TypeError, d
.copy
, None)
264 self
.assertTrue(d
.get('c') is None)
265 self
.assertEqual(d
.get('c', 3), 3)
266 d
= {'a' : 1, 'b' : 2}
267 self
.assertTrue(d
.get('c') is None)
268 self
.assertEqual(d
.get('c', 3), 3)
269 self
.assertEqual(d
.get('a'), 1)
270 self
.assertEqual(d
.get('a', 3), 1)
271 self
.assertRaises(TypeError, d
.get
)
272 self
.assertRaises(TypeError, d
.get
, None, None, None)
274 def test_setdefault(self
):
277 self
.assertTrue(d
.setdefault('key0') is None)
278 d
.setdefault('key0', [])
279 self
.assertTrue(d
.setdefault('key0') is None)
280 d
.setdefault('key', []).append(3)
281 self
.assertEqual(d
['key'][0], 3)
282 d
.setdefault('key', []).append(4)
283 self
.assertEqual(len(d
['key']), 2)
284 self
.assertRaises(TypeError, d
.setdefault
)
286 class Exc(Exception): pass
288 class BadHash(object):
299 self
.assertRaises(Exc
, d
.setdefault
, x
, [])
301 def test_popitem(self
):
303 for copymode
in -1, +1:
304 # -1: b has same structure as a
306 for log2size
in range(12):
310 for i
in range(size
):
316 for i
in range(size
):
317 ka
, va
= ta
= a
.popitem()
318 self
.assertEqual(va
, int(ka
))
319 kb
, vb
= tb
= b
.popitem()
320 self
.assertEqual(vb
, int(kb
))
321 self
.assertTrue(not(copymode
< 0 and ta
!= tb
))
322 self
.assertTrue(not a
)
323 self
.assertTrue(not b
)
326 self
.assertRaises(KeyError, d
.popitem
)
329 # Tests for pop with specified key
333 self
.assertRaises(KeyError, d
.pop
, 'ghi')
335 self
.assertEqual(d
.pop(k
), v
)
336 self
.assertEqual(len(d
), 0)
338 self
.assertRaises(KeyError, d
.pop
, k
)
340 # verify longs/ints get same value when key > 32 bits (for 64-bit archs)
342 x
= 4503599627370496L
344 h
= {x
: 'anything', y
: 'something else'}
345 self
.assertEqual(h
[x
], h
[y
])
347 self
.assertEqual(d
.pop(k
, v
), v
)
349 self
.assertEqual(d
.pop(k
, 1), v
)
351 self
.assertRaises(TypeError, d
.pop
)
353 class Exc(Exception): pass
355 class BadHash(object):
366 self
.assertRaises(Exc
, d
.pop
, x
)
368 def test_mutatingiteration(self
):
377 self
.fail("changing dict size during iteration doesn't raise Error")
381 self
.assertEqual(repr(d
), '{}')
383 self
.assertEqual(repr(d
), '{1: 2}')
386 self
.assertEqual(repr(d
), '{1: {...}}')
388 class Exc(Exception): pass
390 class BadRepr(object):
395 self
.assertRaises(Exc
, repr, d
)
398 self
.assertTrue(not ({} < {}))
399 self
.assertTrue(not ({1: 2} < {1L: 2L}))
401 class Exc(Exception): pass
403 class BadCmp(object):
404 def __eq__(self
, other
):
416 self
.fail("< didn't raise Exc")
418 def test_missing(self
):
419 # Make sure dict doesn't have a __missing__ method
420 self
.assertEqual(hasattr(dict, "__missing__"), False)
421 self
.assertEqual(hasattr({}, "__missing__"), False)
422 # Test several cases:
423 # (D) subclass defines __missing__ method returning a value
424 # (E) subclass defines __missing__ method raising RuntimeError
425 # (F) subclass sets __missing__ instance variable (no effect)
426 # (G) subclass doesn't define __missing__ at a all
428 def __missing__(self
, key
):
431 self
.assertEqual(d
[1], 2)
432 self
.assertEqual(d
[3], 4)
433 self
.assertTrue(2 not in d
)
434 self
.assertTrue(2 not in d
.keys())
435 self
.assertEqual(d
[2], 42)
437 def __missing__(self
, key
):
438 raise RuntimeError(key
)
442 except RuntimeError, err
:
443 self
.assertEqual(err
.args
, (42,))
445 self
.fail("e[42] didn't raise RuntimeError")
448 # An instance variable __missing__ should have no effect
449 self
.__missing
__ = lambda key
: None
453 except KeyError, err
:
454 self
.assertEqual(err
.args
, (42,))
456 self
.fail("f[42] didn't raise KeyError")
462 except KeyError, err
:
463 self
.assertEqual(err
.args
, (42,))
465 self
.fail("g[42] didn't raise KeyError")
467 def test_tuple_keyerror(self
):
473 self
.assertEqual(e
.args
, ((1,),))
475 self
.fail("missing KeyError")
477 def test_bad_key(self
):
478 # Dictionary lookups should fail if __cmp__() raises an exception.
479 class CustomException(Exception):
484 return hash(self
.__class
__)
486 def __cmp__(self
, other
):
487 if isinstance(other
, self
.__class
__):
488 raise CustomException
495 for stmt
in ['d[x2] = 2',
500 'd.setdefault(x2, 42)',
502 'd.update({x2: 2})']:
504 exec stmt
in locals()
505 except CustomException
:
508 self
.fail("Statement didn't raise exception")
510 def test_resize1(self
):
511 # Dict resizing bug, found by Jack Jansen in 2.2 CVS development.
512 # This version got an assert failure in debug build, infinite loop in
513 # release build. Unfortunately, provoking this kind of stuff requires
514 # a mix of inserts and deletes hitting exactly the right hash codes in
515 # exactly the right order, and I can't think of a randomized approach
516 # that would be *likely* to hit a failing case in reasonable time.
523 for i
in range(5, 9): # i==8 was the problem
526 def test_resize2(self
):
527 # Another dict resizing bug (SF bug #1456209).
528 # This caused Segmentation faults or Illegal instructions.
533 def __eq__(self
, other
):
544 # now trigger a resize
548 def test_empty_presized_dict_in_freelist(self
):
549 # Bug #3537: if an empty but presized dict with a size larger
550 # than 7 was in the freelist, it triggered an assertion failure
552 d
= {'a': 1/0, 'b': None, 'c': None, 'd': None, 'e': None,
553 'f': None, 'g': None, 'h': None}
554 except ZeroDivisionError:
558 def test_container_iterator(self
):
559 # Bug #3680: tp_traverse was not implemented for dictiter objects
562 iterators
= (dict.iteritems
, dict.itervalues
, dict.iterkeys
)
565 ref
= weakref
.ref(obj
)
570 self
.assertTrue(ref() is None, "Cycle was not collected")
572 def _not_tracked(self
, t
):
573 # Nested containers can take several collections to untrack
576 self
.assertFalse(gc
.is_tracked(t
), t
)
578 def _tracked(self
, t
):
579 self
.assertTrue(gc
.is_tracked(t
), t
)
582 self
.assertTrue(gc
.is_tracked(t
), t
)
584 def test_track_literals(self
):
585 # Test GC-optimization of dict literals
586 x
, y
, z
, w
= 1.5, "a", (1, None), []
588 self
._not
_tracked
({})
589 self
._not
_tracked
({x
:(), y
:x
, z
:1})
590 self
._not
_tracked
({1: "a", "b": 2})
591 self
._not
_tracked
({1: 2, (None, True, False, ()): int})
592 self
._not
_tracked
({1: object()})
594 # Dicts with mutable elements are always tracked, even if those
595 # elements are not tracked right now.
596 self
._tracked
({1: []})
597 self
._tracked
({1: ([],)})
598 self
._tracked
({1: {}})
599 self
._tracked
({1: set()})
601 def test_track_dynamic(self
):
602 # Test GC-optimization of dynamically-created dicts
603 class MyObject(object):
605 x
, y
, z
, w
, o
= 1.5, "a", (1, object()), [], MyObject()
615 self
._not
_tracked
(d
.copy())
618 self
._tracked
(d
.copy())
621 self
._not
_tracked
(d
.copy())
623 # dd isn't tracked right now, but it may mutate and therefore d
624 # which contains it must be tracked.
628 self
._not
_tracked
(dd
)
633 d
= dict.fromkeys([x
, y
, z
])
637 self
._not
_tracked
(dd
)
638 d
= dict.fromkeys([x
, y
, z
, o
])
644 d
= dict(x
=x
, y
=y
, z
=z
)
646 d
= dict(x
=x
, y
=y
, z
=z
, w
=w
)
649 d
.update(x
=x
, y
=y
, z
=z
)
654 d
= dict([(x
, y
), (z
, 1)])
656 d
= dict([(x
, y
), (z
, w
)])
659 d
.update([(x
, y
), (z
, 1)])
661 d
.update([(x
, y
), (z
, w
)])
664 def test_track_subtypes(self
):
665 # Dict subtypes are always tracked
668 self
._tracked
(MyDict())
671 from test
import mapping_tests
673 class GeneralMappingTests(mapping_tests
.BasicTestMappingProtocol
):
679 class SubclassMappingTests(mapping_tests
.BasicTestMappingProtocol
):
683 test_support
.run_unittest(
686 SubclassMappingTests
,
689 if __name__
== "__main__":