Back to index

python3.2  3.2.2
test_dict.py
Go to the documentation of this file.
00001 import unittest
00002 from test import support
00003 
00004 import collections, random, string
00005 import gc, weakref
00006 
00007 
00008 class DictTest(unittest.TestCase):
00009 
00010     def test_invalid_keyword_arguments(self):
00011         class Custom(dict):
00012             pass
00013         for invalid in {1 : 2}, Custom({1 : 2}):
00014             with self.assertRaises(TypeError):
00015                 dict(**invalid)
00016             with self.assertRaises(TypeError):
00017                 {}.update(**invalid)
00018 
00019     def test_constructor(self):
00020         # calling built-in types without argument must return empty
00021         self.assertEqual(dict(), {})
00022         self.assertIsNot(dict(), {})
00023 
00024     def test_literal_constructor(self):
00025         # check literal constructor for different sized dicts
00026         # (to exercise the BUILD_MAP oparg).
00027         for n in (0, 1, 6, 256, 400):
00028             items = [(''.join(random.sample(string.ascii_letters, 8)), i)
00029                      for i in range(n)]
00030             random.shuffle(items)
00031             formatted_items = ('{!r}: {:d}'.format(k, v) for k, v in items)
00032             dictliteral = '{' + ', '.join(formatted_items) + '}'
00033             self.assertEqual(eval(dictliteral), dict(items))
00034 
00035     def test_bool(self):
00036         self.assertIs(not {}, True)
00037         self.assertTrue({1: 2})
00038         self.assertIs(bool({}), False)
00039         self.assertIs(bool({1: 2}), True)
00040 
00041     def test_keys(self):
00042         d = {}
00043         self.assertEqual(set(d.keys()), set())
00044         d = {'a': 1, 'b': 2}
00045         k = d.keys()
00046         self.assertIn('a', d)
00047         self.assertIn('b', d)
00048         self.assertRaises(TypeError, d.keys, None)
00049         self.assertEqual(repr(dict(a=1).keys()), "dict_keys(['a'])")
00050 
00051     def test_values(self):
00052         d = {}
00053         self.assertEqual(set(d.values()), set())
00054         d = {1:2}
00055         self.assertEqual(set(d.values()), {2})
00056         self.assertRaises(TypeError, d.values, None)
00057         self.assertEqual(repr(dict(a=1).values()), "dict_values([1])")
00058 
00059     def test_items(self):
00060         d = {}
00061         self.assertEqual(set(d.items()), set())
00062 
00063         d = {1:2}
00064         self.assertEqual(set(d.items()), {(1, 2)})
00065         self.assertRaises(TypeError, d.items, None)
00066         self.assertEqual(repr(dict(a=1).items()), "dict_items([('a', 1)])")
00067 
00068     def test_contains(self):
00069         d = {}
00070         self.assertNotIn('a', d)
00071         self.assertFalse('a' in d)
00072         self.assertTrue('a' not in d)
00073         d = {'a': 1, 'b': 2}
00074         self.assertIn('a', d)
00075         self.assertIn('b', d)
00076         self.assertNotIn('c', d)
00077 
00078         self.assertRaises(TypeError, d.__contains__)
00079 
00080     def test_len(self):
00081         d = {}
00082         self.assertEqual(len(d), 0)
00083         d = {'a': 1, 'b': 2}
00084         self.assertEqual(len(d), 2)
00085 
00086     def test_getitem(self):
00087         d = {'a': 1, 'b': 2}
00088         self.assertEqual(d['a'], 1)
00089         self.assertEqual(d['b'], 2)
00090         d['c'] = 3
00091         d['a'] = 4
00092         self.assertEqual(d['c'], 3)
00093         self.assertEqual(d['a'], 4)
00094         del d['b']
00095         self.assertEqual(d, {'a': 4, 'c': 3})
00096 
00097         self.assertRaises(TypeError, d.__getitem__)
00098 
00099         class BadEq(object):
00100             def __eq__(self, other):
00101                 raise Exc()
00102             def __hash__(self):
00103                 return 24
00104 
00105         d = {}
00106         d[BadEq()] = 42
00107         self.assertRaises(KeyError, d.__getitem__, 23)
00108 
00109         class Exc(Exception): pass
00110 
00111         class BadHash(object):
00112             fail = False
00113             def __hash__(self):
00114                 if self.fail:
00115                     raise Exc()
00116                 else:
00117                     return 42
00118 
00119         x = BadHash()
00120         d[x] = 42
00121         x.fail = True
00122         self.assertRaises(Exc, d.__getitem__, x)
00123 
00124     def test_clear(self):
00125         d = {1:1, 2:2, 3:3}
00126         d.clear()
00127         self.assertEqual(d, {})
00128 
00129         self.assertRaises(TypeError, d.clear, None)
00130 
00131     def test_update(self):
00132         d = {}
00133         d.update({1:100})
00134         d.update({2:20})
00135         d.update({1:1, 2:2, 3:3})
00136         self.assertEqual(d, {1:1, 2:2, 3:3})
00137 
00138         d.update()
00139         self.assertEqual(d, {1:1, 2:2, 3:3})
00140 
00141         self.assertRaises((TypeError, AttributeError), d.update, None)
00142 
00143         class SimpleUserDict:
00144             def __init__(self):
00145                 self.d = {1:1, 2:2, 3:3}
00146             def keys(self):
00147                 return self.d.keys()
00148             def __getitem__(self, i):
00149                 return self.d[i]
00150         d.clear()
00151         d.update(SimpleUserDict())
00152         self.assertEqual(d, {1:1, 2:2, 3:3})
00153 
00154         class Exc(Exception): pass
00155 
00156         d.clear()
00157         class FailingUserDict:
00158             def keys(self):
00159                 raise Exc
00160         self.assertRaises(Exc, d.update, FailingUserDict())
00161 
00162         class FailingUserDict:
00163             def keys(self):
00164                 class BogonIter:
00165                     def __init__(self):
00166                         self.i = 1
00167                     def __iter__(self):
00168                         return self
00169                     def __next__(self):
00170                         if self.i:
00171                             self.i = 0
00172                             return 'a'
00173                         raise Exc
00174                 return BogonIter()
00175             def __getitem__(self, key):
00176                 return key
00177         self.assertRaises(Exc, d.update, FailingUserDict())
00178 
00179         class FailingUserDict:
00180             def keys(self):
00181                 class BogonIter:
00182                     def __init__(self):
00183                         self.i = ord('a')
00184                     def __iter__(self):
00185                         return self
00186                     def __next__(self):
00187                         if self.i <= ord('z'):
00188                             rtn = chr(self.i)
00189                             self.i += 1
00190                             return rtn
00191                         raise StopIteration
00192                 return BogonIter()
00193             def __getitem__(self, key):
00194                 raise Exc
00195         self.assertRaises(Exc, d.update, FailingUserDict())
00196 
00197         class badseq(object):
00198             def __iter__(self):
00199                 return self
00200             def __next__(self):
00201                 raise Exc()
00202 
00203         self.assertRaises(Exc, {}.update, badseq())
00204 
00205         self.assertRaises(ValueError, {}.update, [(1, 2, 3)])
00206 
00207     def test_fromkeys(self):
00208         self.assertEqual(dict.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
00209         d = {}
00210         self.assertIsNot(d.fromkeys('abc'), d)
00211         self.assertEqual(d.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
00212         self.assertEqual(d.fromkeys((4,5),0), {4:0, 5:0})
00213         self.assertEqual(d.fromkeys([]), {})
00214         def g():
00215             yield 1
00216         self.assertEqual(d.fromkeys(g()), {1:None})
00217         self.assertRaises(TypeError, {}.fromkeys, 3)
00218         class dictlike(dict): pass
00219         self.assertEqual(dictlike.fromkeys('a'), {'a':None})
00220         self.assertEqual(dictlike().fromkeys('a'), {'a':None})
00221         self.assertIsInstance(dictlike.fromkeys('a'), dictlike)
00222         self.assertIsInstance(dictlike().fromkeys('a'), dictlike)
00223         class mydict(dict):
00224             def __new__(cls):
00225                 return collections.UserDict()
00226         ud = mydict.fromkeys('ab')
00227         self.assertEqual(ud, {'a':None, 'b':None})
00228         self.assertIsInstance(ud, collections.UserDict)
00229         self.assertRaises(TypeError, dict.fromkeys)
00230 
00231         class Exc(Exception): pass
00232 
00233         class baddict1(dict):
00234             def __init__(self):
00235                 raise Exc()
00236 
00237         self.assertRaises(Exc, baddict1.fromkeys, [1])
00238 
00239         class BadSeq(object):
00240             def __iter__(self):
00241                 return self
00242             def __next__(self):
00243                 raise Exc()
00244 
00245         self.assertRaises(Exc, dict.fromkeys, BadSeq())
00246 
00247         class baddict2(dict):
00248             def __setitem__(self, key, value):
00249                 raise Exc()
00250 
00251         self.assertRaises(Exc, baddict2.fromkeys, [1])
00252 
00253         # test fast path for dictionary inputs
00254         d = dict(zip(range(6), range(6)))
00255         self.assertEqual(dict.fromkeys(d, 0), dict(zip(range(6), [0]*6)))
00256 
00257     def test_copy(self):
00258         d = {1:1, 2:2, 3:3}
00259         self.assertEqual(d.copy(), {1:1, 2:2, 3:3})
00260         self.assertEqual({}.copy(), {})
00261         self.assertRaises(TypeError, d.copy, None)
00262 
00263     def test_get(self):
00264         d = {}
00265         self.assertIs(d.get('c'), None)
00266         self.assertEqual(d.get('c', 3), 3)
00267         d = {'a': 1, 'b': 2}
00268         self.assertIs(d.get('c'), None)
00269         self.assertEqual(d.get('c', 3), 3)
00270         self.assertEqual(d.get('a'), 1)
00271         self.assertEqual(d.get('a', 3), 1)
00272         self.assertRaises(TypeError, d.get)
00273         self.assertRaises(TypeError, d.get, None, None, None)
00274 
00275     def test_setdefault(self):
00276         # dict.setdefault()
00277         d = {}
00278         self.assertIs(d.setdefault('key0'), None)
00279         d.setdefault('key0', [])
00280         self.assertIs(d.setdefault('key0'), None)
00281         d.setdefault('key', []).append(3)
00282         self.assertEqual(d['key'][0], 3)
00283         d.setdefault('key', []).append(4)
00284         self.assertEqual(len(d['key']), 2)
00285         self.assertRaises(TypeError, d.setdefault)
00286 
00287         class Exc(Exception): pass
00288 
00289         class BadHash(object):
00290             fail = False
00291             def __hash__(self):
00292                 if self.fail:
00293                     raise Exc()
00294                 else:
00295                     return 42
00296 
00297         x = BadHash()
00298         d[x] = 42
00299         x.fail = True
00300         self.assertRaises(Exc, d.setdefault, x, [])
00301 
00302     def test_popitem(self):
00303         # dict.popitem()
00304         for copymode in -1, +1:
00305             # -1: b has same structure as a
00306             # +1: b is a.copy()
00307             for log2size in range(12):
00308                 size = 2**log2size
00309                 a = {}
00310                 b = {}
00311                 for i in range(size):
00312                     a[repr(i)] = i
00313                     if copymode < 0:
00314                         b[repr(i)] = i
00315                 if copymode > 0:
00316                     b = a.copy()
00317                 for i in range(size):
00318                     ka, va = ta = a.popitem()
00319                     self.assertEqual(va, int(ka))
00320                     kb, vb = tb = b.popitem()
00321                     self.assertEqual(vb, int(kb))
00322                     self.assertFalse(copymode < 0 and ta != tb)
00323                 self.assertFalse(a)
00324                 self.assertFalse(b)
00325 
00326         d = {}
00327         self.assertRaises(KeyError, d.popitem)
00328 
00329     def test_pop(self):
00330         # Tests for pop with specified key
00331         d = {}
00332         k, v = 'abc', 'def'
00333         d[k] = v
00334         self.assertRaises(KeyError, d.pop, 'ghi')
00335 
00336         self.assertEqual(d.pop(k), v)
00337         self.assertEqual(len(d), 0)
00338 
00339         self.assertRaises(KeyError, d.pop, k)
00340 
00341         self.assertEqual(d.pop(k, v), v)
00342         d[k] = v
00343         self.assertEqual(d.pop(k, 1), v)
00344 
00345         self.assertRaises(TypeError, d.pop)
00346 
00347         class Exc(Exception): pass
00348 
00349         class BadHash(object):
00350             fail = False
00351             def __hash__(self):
00352                 if self.fail:
00353                     raise Exc()
00354                 else:
00355                     return 42
00356 
00357         x = BadHash()
00358         d[x] = 42
00359         x.fail = True
00360         self.assertRaises(Exc, d.pop, x)
00361 
00362     def test_mutatingiteration(self):
00363         # changing dict size during iteration
00364         d = {}
00365         d[1] = 1
00366         with self.assertRaises(RuntimeError):
00367             for i in d:
00368                 d[i+1] = 1
00369 
00370     def test_repr(self):
00371         d = {}
00372         self.assertEqual(repr(d), '{}')
00373         d[1] = 2
00374         self.assertEqual(repr(d), '{1: 2}')
00375         d = {}
00376         d[1] = d
00377         self.assertEqual(repr(d), '{1: {...}}')
00378 
00379         class Exc(Exception): pass
00380 
00381         class BadRepr(object):
00382             def __repr__(self):
00383                 raise Exc()
00384 
00385         d = {1: BadRepr()}
00386         self.assertRaises(Exc, repr, d)
00387 
00388     def test_eq(self):
00389         self.assertEqual({}, {})
00390         self.assertEqual({1: 2}, {1: 2})
00391 
00392         class Exc(Exception): pass
00393 
00394         class BadCmp(object):
00395             def __eq__(self, other):
00396                 raise Exc()
00397             def __hash__(self):
00398                 return 1
00399 
00400         d1 = {BadCmp(): 1}
00401         d2 = {1: 1}
00402 
00403         with self.assertRaises(Exc):
00404             d1 == d2
00405 
00406     def test_keys_contained(self):
00407         self.helper_keys_contained(lambda x: x.keys())
00408         self.helper_keys_contained(lambda x: x.items())
00409 
00410     def helper_keys_contained(self, fn):
00411         # Test rich comparisons against dict key views, which should behave the
00412         # same as sets.
00413         empty = fn(dict())
00414         empty2 = fn(dict())
00415         smaller = fn({1:1, 2:2})
00416         larger = fn({1:1, 2:2, 3:3})
00417         larger2 = fn({1:1, 2:2, 3:3})
00418         larger3 = fn({4:1, 2:2, 3:3})
00419 
00420         self.assertTrue(smaller <  larger)
00421         self.assertTrue(smaller <= larger)
00422         self.assertTrue(larger >  smaller)
00423         self.assertTrue(larger >= smaller)
00424 
00425         self.assertFalse(smaller >= larger)
00426         self.assertFalse(smaller >  larger)
00427         self.assertFalse(larger  <= smaller)
00428         self.assertFalse(larger  <  smaller)
00429 
00430         self.assertFalse(smaller <  larger3)
00431         self.assertFalse(smaller <= larger3)
00432         self.assertFalse(larger3 >  smaller)
00433         self.assertFalse(larger3 >= smaller)
00434 
00435         # Inequality strictness
00436         self.assertTrue(larger2 >= larger)
00437         self.assertTrue(larger2 <= larger)
00438         self.assertFalse(larger2 > larger)
00439         self.assertFalse(larger2 < larger)
00440 
00441         self.assertTrue(larger == larger2)
00442         self.assertTrue(smaller != larger)
00443 
00444         # There is an optimization on the zero-element case.
00445         self.assertTrue(empty == empty2)
00446         self.assertFalse(empty != empty2)
00447         self.assertFalse(empty == smaller)
00448         self.assertTrue(empty != smaller)
00449 
00450         # With the same size, an elementwise compare happens
00451         self.assertTrue(larger != larger3)
00452         self.assertFalse(larger == larger3)
00453 
00454     def test_errors_in_view_containment_check(self):
00455         class C:
00456             def __eq__(self, other):
00457                 raise RuntimeError
00458 
00459         d1 = {1: C()}
00460         d2 = {1: C()}
00461         with self.assertRaises(RuntimeError):
00462             d1.items() == d2.items()
00463         with self.assertRaises(RuntimeError):
00464             d1.items() != d2.items()
00465         with self.assertRaises(RuntimeError):
00466             d1.items() <= d2.items()
00467         with self.assertRaises(RuntimeError):
00468             d1.items() >= d2.items()
00469 
00470         d3 = {1: C(), 2: C()}
00471         with self.assertRaises(RuntimeError):
00472             d2.items() < d3.items()
00473         with self.assertRaises(RuntimeError):
00474             d3.items() > d2.items()
00475 
00476     def test_dictview_set_operations_on_keys(self):
00477         k1 = {1:1, 2:2}.keys()
00478         k2 = {1:1, 2:2, 3:3}.keys()
00479         k3 = {4:4}.keys()
00480 
00481         self.assertEqual(k1 - k2, set())
00482         self.assertEqual(k1 - k3, {1,2})
00483         self.assertEqual(k2 - k1, {3})
00484         self.assertEqual(k3 - k1, {4})
00485         self.assertEqual(k1 & k2, {1,2})
00486         self.assertEqual(k1 & k3, set())
00487         self.assertEqual(k1 | k2, {1,2,3})
00488         self.assertEqual(k1 ^ k2, {3})
00489         self.assertEqual(k1 ^ k3, {1,2,4})
00490 
00491     def test_dictview_set_operations_on_items(self):
00492         k1 = {1:1, 2:2}.items()
00493         k2 = {1:1, 2:2, 3:3}.items()
00494         k3 = {4:4}.items()
00495 
00496         self.assertEqual(k1 - k2, set())
00497         self.assertEqual(k1 - k3, {(1,1), (2,2)})
00498         self.assertEqual(k2 - k1, {(3,3)})
00499         self.assertEqual(k3 - k1, {(4,4)})
00500         self.assertEqual(k1 & k2, {(1,1), (2,2)})
00501         self.assertEqual(k1 & k3, set())
00502         self.assertEqual(k1 | k2, {(1,1), (2,2), (3,3)})
00503         self.assertEqual(k1 ^ k2, {(3,3)})
00504         self.assertEqual(k1 ^ k3, {(1,1), (2,2), (4,4)})
00505 
00506     def test_dictview_mixed_set_operations(self):
00507         # Just a few for .keys()
00508         self.assertTrue({1:1}.keys() == {1})
00509         self.assertTrue({1} == {1:1}.keys())
00510         self.assertEqual({1:1}.keys() | {2}, {1, 2})
00511         self.assertEqual({2} | {1:1}.keys(), {1, 2})
00512         # And a few for .items()
00513         self.assertTrue({1:1}.items() == {(1,1)})
00514         self.assertTrue({(1,1)} == {1:1}.items())
00515         self.assertEqual({1:1}.items() | {2}, {(1,1), 2})
00516         self.assertEqual({2} | {1:1}.items(), {(1,1), 2})
00517 
00518     def test_missing(self):
00519         # Make sure dict doesn't have a __missing__ method
00520         self.assertFalse(hasattr(dict, "__missing__"))
00521         self.assertFalse(hasattr({}, "__missing__"))
00522         # Test several cases:
00523         # (D) subclass defines __missing__ method returning a value
00524         # (E) subclass defines __missing__ method raising RuntimeError
00525         # (F) subclass sets __missing__ instance variable (no effect)
00526         # (G) subclass doesn't define __missing__ at a all
00527         class D(dict):
00528             def __missing__(self, key):
00529                 return 42
00530         d = D({1: 2, 3: 4})
00531         self.assertEqual(d[1], 2)
00532         self.assertEqual(d[3], 4)
00533         self.assertNotIn(2, d)
00534         self.assertNotIn(2, d.keys())
00535         self.assertEqual(d[2], 42)
00536 
00537         class E(dict):
00538             def __missing__(self, key):
00539                 raise RuntimeError(key)
00540         e = E()
00541         with self.assertRaises(RuntimeError) as c:
00542             e[42]
00543         self.assertEqual(c.exception.args, (42,))
00544 
00545         class F(dict):
00546             def __init__(self):
00547                 # An instance variable __missing__ should have no effect
00548                 self.__missing__ = lambda key: None
00549         f = F()
00550         with self.assertRaises(KeyError) as c:
00551             f[42]
00552         self.assertEqual(c.exception.args, (42,))
00553 
00554         class G(dict):
00555             pass
00556         g = G()
00557         with self.assertRaises(KeyError) as c:
00558             g[42]
00559         self.assertEqual(c.exception.args, (42,))
00560 
00561     def test_tuple_keyerror(self):
00562         # SF #1576657
00563         d = {}
00564         with self.assertRaises(KeyError) as c:
00565             d[(1,)]
00566         self.assertEqual(c.exception.args, ((1,),))
00567 
00568     def test_bad_key(self):
00569         # Dictionary lookups should fail if __eq__() raises an exception.
00570         class CustomException(Exception):
00571             pass
00572 
00573         class BadDictKey:
00574             def __hash__(self):
00575                 return hash(self.__class__)
00576 
00577             def __eq__(self, other):
00578                 if isinstance(other, self.__class__):
00579                     raise CustomException
00580                 return other
00581 
00582         d = {}
00583         x1 = BadDictKey()
00584         x2 = BadDictKey()
00585         d[x1] = 1
00586         for stmt in ['d[x2] = 2',
00587                      'z = d[x2]',
00588                      'x2 in d',
00589                      'd.get(x2)',
00590                      'd.setdefault(x2, 42)',
00591                      'd.pop(x2)',
00592                      'd.update({x2: 2})']:
00593             with self.assertRaises(CustomException):
00594                 exec(stmt, locals())
00595 
00596     def test_resize1(self):
00597         # Dict resizing bug, found by Jack Jansen in 2.2 CVS development.
00598         # This version got an assert failure in debug build, infinite loop in
00599         # release build.  Unfortunately, provoking this kind of stuff requires
00600         # a mix of inserts and deletes hitting exactly the right hash codes in
00601         # exactly the right order, and I can't think of a randomized approach
00602         # that would be *likely* to hit a failing case in reasonable time.
00603 
00604         d = {}
00605         for i in range(5):
00606             d[i] = i
00607         for i in range(5):
00608             del d[i]
00609         for i in range(5, 9):  # i==8 was the problem
00610             d[i] = i
00611 
00612     def test_resize2(self):
00613         # Another dict resizing bug (SF bug #1456209).
00614         # This caused Segmentation faults or Illegal instructions.
00615 
00616         class X(object):
00617             def __hash__(self):
00618                 return 5
00619             def __eq__(self, other):
00620                 if resizing:
00621                     d.clear()
00622                 return False
00623         d = {}
00624         resizing = False
00625         d[X()] = 1
00626         d[X()] = 2
00627         d[X()] = 3
00628         d[X()] = 4
00629         d[X()] = 5
00630         # now trigger a resize
00631         resizing = True
00632         d[9] = 6
00633 
00634     def test_empty_presized_dict_in_freelist(self):
00635         # Bug #3537: if an empty but presized dict with a size larger
00636         # than 7 was in the freelist, it triggered an assertion failure
00637         with self.assertRaises(ZeroDivisionError):
00638             d = {'a': 1 // 0, 'b': None, 'c': None, 'd': None, 'e': None,
00639                  'f': None, 'g': None, 'h': None}
00640         d = {}
00641 
00642     def test_container_iterator(self):
00643         # Bug #3680: tp_traverse was not implemented for dictiter and
00644         # dictview objects.
00645         class C(object):
00646             pass
00647         views = (dict.items, dict.values, dict.keys)
00648         for v in views:
00649             obj = C()
00650             ref = weakref.ref(obj)
00651             container = {obj: 1}
00652             obj.v = v(container)
00653             obj.x = iter(obj.v)
00654             del obj, container
00655             gc.collect()
00656             self.assertIs(ref(), None, "Cycle was not collected")
00657 
00658     def _not_tracked(self, t):
00659         # Nested containers can take several collections to untrack
00660         gc.collect()
00661         gc.collect()
00662         self.assertFalse(gc.is_tracked(t), t)
00663 
00664     def _tracked(self, t):
00665         self.assertTrue(gc.is_tracked(t), t)
00666         gc.collect()
00667         gc.collect()
00668         self.assertTrue(gc.is_tracked(t), t)
00669 
00670     @support.cpython_only
00671     def test_track_literals(self):
00672         # Test GC-optimization of dict literals
00673         x, y, z, w = 1.5, "a", (1, None), []
00674 
00675         self._not_tracked({})
00676         self._not_tracked({x:(), y:x, z:1})
00677         self._not_tracked({1: "a", "b": 2})
00678         self._not_tracked({1: 2, (None, True, False, ()): int})
00679         self._not_tracked({1: object()})
00680 
00681         # Dicts with mutable elements are always tracked, even if those
00682         # elements are not tracked right now.
00683         self._tracked({1: []})
00684         self._tracked({1: ([],)})
00685         self._tracked({1: {}})
00686         self._tracked({1: set()})
00687 
00688     @support.cpython_only
00689     def test_track_dynamic(self):
00690         # Test GC-optimization of dynamically-created dicts
00691         class MyObject(object):
00692             pass
00693         x, y, z, w, o = 1.5, "a", (1, object()), [], MyObject()
00694 
00695         d = dict()
00696         self._not_tracked(d)
00697         d[1] = "a"
00698         self._not_tracked(d)
00699         d[y] = 2
00700         self._not_tracked(d)
00701         d[z] = 3
00702         self._not_tracked(d)
00703         self._not_tracked(d.copy())
00704         d[4] = w
00705         self._tracked(d)
00706         self._tracked(d.copy())
00707         d[4] = None
00708         self._not_tracked(d)
00709         self._not_tracked(d.copy())
00710 
00711         # dd isn't tracked right now, but it may mutate and therefore d
00712         # which contains it must be tracked.
00713         d = dict()
00714         dd = dict()
00715         d[1] = dd
00716         self._not_tracked(dd)
00717         self._tracked(d)
00718         dd[1] = d
00719         self._tracked(dd)
00720 
00721         d = dict.fromkeys([x, y, z])
00722         self._not_tracked(d)
00723         dd = dict()
00724         dd.update(d)
00725         self._not_tracked(dd)
00726         d = dict.fromkeys([x, y, z, o])
00727         self._tracked(d)
00728         dd = dict()
00729         dd.update(d)
00730         self._tracked(dd)
00731 
00732         d = dict(x=x, y=y, z=z)
00733         self._not_tracked(d)
00734         d = dict(x=x, y=y, z=z, w=w)
00735         self._tracked(d)
00736         d = dict()
00737         d.update(x=x, y=y, z=z)
00738         self._not_tracked(d)
00739         d.update(w=w)
00740         self._tracked(d)
00741 
00742         d = dict([(x, y), (z, 1)])
00743         self._not_tracked(d)
00744         d = dict([(x, y), (z, w)])
00745         self._tracked(d)
00746         d = dict()
00747         d.update([(x, y), (z, 1)])
00748         self._not_tracked(d)
00749         d.update([(x, y), (z, w)])
00750         self._tracked(d)
00751 
00752     @support.cpython_only
00753     def test_track_subtypes(self):
00754         # Dict subtypes are always tracked
00755         class MyDict(dict):
00756             pass
00757         self._tracked(MyDict())
00758 
00759 
00760 from test import mapping_tests
00761 
00762 class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
00763     type2test = dict
00764 
00765 class Dict(dict):
00766     pass
00767 
00768 class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
00769     type2test = Dict
00770 
00771 def test_main():
00772     support.run_unittest(
00773         DictTest,
00774         GeneralMappingTests,
00775         SubclassMappingTests,
00776     )
00777 
00778 if __name__ == "__main__":
00779     test_main()