17db96d56Sopenharmony_ciimport collections
27db96d56Sopenharmony_ciimport collections.abc
37db96d56Sopenharmony_ciimport gc
47db96d56Sopenharmony_ciimport pickle
57db96d56Sopenharmony_ciimport random
67db96d56Sopenharmony_ciimport string
77db96d56Sopenharmony_ciimport sys
87db96d56Sopenharmony_ciimport unittest
97db96d56Sopenharmony_ciimport weakref
107db96d56Sopenharmony_cifrom test import support
117db96d56Sopenharmony_cifrom test.support import import_helper
127db96d56Sopenharmony_ci
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ciclass DictTest(unittest.TestCase):
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ci    def test_invalid_keyword_arguments(self):
177db96d56Sopenharmony_ci        class Custom(dict):
187db96d56Sopenharmony_ci            pass
197db96d56Sopenharmony_ci        for invalid in {1 : 2}, Custom({1 : 2}):
207db96d56Sopenharmony_ci            with self.assertRaises(TypeError):
217db96d56Sopenharmony_ci                dict(**invalid)
227db96d56Sopenharmony_ci            with self.assertRaises(TypeError):
237db96d56Sopenharmony_ci                {}.update(**invalid)
247db96d56Sopenharmony_ci
257db96d56Sopenharmony_ci    def test_constructor(self):
267db96d56Sopenharmony_ci        # calling built-in types without argument must return empty
277db96d56Sopenharmony_ci        self.assertEqual(dict(), {})
287db96d56Sopenharmony_ci        self.assertIsNot(dict(), {})
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci    def test_literal_constructor(self):
317db96d56Sopenharmony_ci        # check literal constructor for different sized dicts
327db96d56Sopenharmony_ci        # (to exercise the BUILD_MAP oparg).
337db96d56Sopenharmony_ci        for n in (0, 1, 6, 256, 400):
347db96d56Sopenharmony_ci            items = [(''.join(random.sample(string.ascii_letters, 8)), i)
357db96d56Sopenharmony_ci                     for i in range(n)]
367db96d56Sopenharmony_ci            random.shuffle(items)
377db96d56Sopenharmony_ci            formatted_items = ('{!r}: {:d}'.format(k, v) for k, v in items)
387db96d56Sopenharmony_ci            dictliteral = '{' + ', '.join(formatted_items) + '}'
397db96d56Sopenharmony_ci            self.assertEqual(eval(dictliteral), dict(items))
407db96d56Sopenharmony_ci
417db96d56Sopenharmony_ci    def test_merge_operator(self):
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_ci        a = {0: 0, 1: 1, 2: 1}
447db96d56Sopenharmony_ci        b = {1: 1, 2: 2, 3: 3}
457db96d56Sopenharmony_ci
467db96d56Sopenharmony_ci        c = a.copy()
477db96d56Sopenharmony_ci        c |= b
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_ci        self.assertEqual(a | b, {0: 0, 1: 1, 2: 2, 3: 3})
507db96d56Sopenharmony_ci        self.assertEqual(c, {0: 0, 1: 1, 2: 2, 3: 3})
517db96d56Sopenharmony_ci
527db96d56Sopenharmony_ci        c = b.copy()
537db96d56Sopenharmony_ci        c |= a
547db96d56Sopenharmony_ci
557db96d56Sopenharmony_ci        self.assertEqual(b | a, {1: 1, 2: 1, 3: 3, 0: 0})
567db96d56Sopenharmony_ci        self.assertEqual(c, {1: 1, 2: 1, 3: 3, 0: 0})
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ci        c = a.copy()
597db96d56Sopenharmony_ci        c |= [(1, 1), (2, 2), (3, 3)]
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ci        self.assertEqual(c, {0: 0, 1: 1, 2: 2, 3: 3})
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_ci        self.assertIs(a.__or__(None), NotImplemented)
647db96d56Sopenharmony_ci        self.assertIs(a.__or__(()), NotImplemented)
657db96d56Sopenharmony_ci        self.assertIs(a.__or__("BAD"), NotImplemented)
667db96d56Sopenharmony_ci        self.assertIs(a.__or__(""), NotImplemented)
677db96d56Sopenharmony_ci
687db96d56Sopenharmony_ci        self.assertRaises(TypeError, a.__ior__, None)
697db96d56Sopenharmony_ci        self.assertEqual(a.__ior__(()), {0: 0, 1: 1, 2: 1})
707db96d56Sopenharmony_ci        self.assertRaises(ValueError, a.__ior__, "BAD")
717db96d56Sopenharmony_ci        self.assertEqual(a.__ior__(""), {0: 0, 1: 1, 2: 1})
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_ci    def test_bool(self):
747db96d56Sopenharmony_ci        self.assertIs(not {}, True)
757db96d56Sopenharmony_ci        self.assertTrue({1: 2})
767db96d56Sopenharmony_ci        self.assertIs(bool({}), False)
777db96d56Sopenharmony_ci        self.assertIs(bool({1: 2}), True)
787db96d56Sopenharmony_ci
797db96d56Sopenharmony_ci    def test_keys(self):
807db96d56Sopenharmony_ci        d = {}
817db96d56Sopenharmony_ci        self.assertEqual(set(d.keys()), set())
827db96d56Sopenharmony_ci        d = {'a': 1, 'b': 2}
837db96d56Sopenharmony_ci        k = d.keys()
847db96d56Sopenharmony_ci        self.assertEqual(set(k), {'a', 'b'})
857db96d56Sopenharmony_ci        self.assertIn('a', k)
867db96d56Sopenharmony_ci        self.assertIn('b', k)
877db96d56Sopenharmony_ci        self.assertIn('a', d)
887db96d56Sopenharmony_ci        self.assertIn('b', d)
897db96d56Sopenharmony_ci        self.assertRaises(TypeError, d.keys, None)
907db96d56Sopenharmony_ci        self.assertEqual(repr(dict(a=1).keys()), "dict_keys(['a'])")
917db96d56Sopenharmony_ci
927db96d56Sopenharmony_ci    def test_values(self):
937db96d56Sopenharmony_ci        d = {}
947db96d56Sopenharmony_ci        self.assertEqual(set(d.values()), set())
957db96d56Sopenharmony_ci        d = {1:2}
967db96d56Sopenharmony_ci        self.assertEqual(set(d.values()), {2})
977db96d56Sopenharmony_ci        self.assertRaises(TypeError, d.values, None)
987db96d56Sopenharmony_ci        self.assertEqual(repr(dict(a=1).values()), "dict_values([1])")
997db96d56Sopenharmony_ci
1007db96d56Sopenharmony_ci    def test_items(self):
1017db96d56Sopenharmony_ci        d = {}
1027db96d56Sopenharmony_ci        self.assertEqual(set(d.items()), set())
1037db96d56Sopenharmony_ci
1047db96d56Sopenharmony_ci        d = {1:2}
1057db96d56Sopenharmony_ci        self.assertEqual(set(d.items()), {(1, 2)})
1067db96d56Sopenharmony_ci        self.assertRaises(TypeError, d.items, None)
1077db96d56Sopenharmony_ci        self.assertEqual(repr(dict(a=1).items()), "dict_items([('a', 1)])")
1087db96d56Sopenharmony_ci
1097db96d56Sopenharmony_ci    def test_views_mapping(self):
1107db96d56Sopenharmony_ci        mappingproxy = type(type.__dict__)
1117db96d56Sopenharmony_ci        class Dict(dict):
1127db96d56Sopenharmony_ci            pass
1137db96d56Sopenharmony_ci        for cls in [dict, Dict]:
1147db96d56Sopenharmony_ci            d = cls()
1157db96d56Sopenharmony_ci            m1 = d.keys().mapping
1167db96d56Sopenharmony_ci            m2 = d.values().mapping
1177db96d56Sopenharmony_ci            m3 = d.items().mapping
1187db96d56Sopenharmony_ci
1197db96d56Sopenharmony_ci            for m in [m1, m2, m3]:
1207db96d56Sopenharmony_ci                self.assertIsInstance(m, mappingproxy)
1217db96d56Sopenharmony_ci                self.assertEqual(m, d)
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_ci            d["foo"] = "bar"
1247db96d56Sopenharmony_ci
1257db96d56Sopenharmony_ci            for m in [m1, m2, m3]:
1267db96d56Sopenharmony_ci                self.assertIsInstance(m, mappingproxy)
1277db96d56Sopenharmony_ci                self.assertEqual(m, d)
1287db96d56Sopenharmony_ci
1297db96d56Sopenharmony_ci    def test_contains(self):
1307db96d56Sopenharmony_ci        d = {}
1317db96d56Sopenharmony_ci        self.assertNotIn('a', d)
1327db96d56Sopenharmony_ci        self.assertFalse('a' in d)
1337db96d56Sopenharmony_ci        self.assertTrue('a' not in d)
1347db96d56Sopenharmony_ci        d = {'a': 1, 'b': 2}
1357db96d56Sopenharmony_ci        self.assertIn('a', d)
1367db96d56Sopenharmony_ci        self.assertIn('b', d)
1377db96d56Sopenharmony_ci        self.assertNotIn('c', d)
1387db96d56Sopenharmony_ci
1397db96d56Sopenharmony_ci        self.assertRaises(TypeError, d.__contains__)
1407db96d56Sopenharmony_ci
1417db96d56Sopenharmony_ci    def test_len(self):
1427db96d56Sopenharmony_ci        d = {}
1437db96d56Sopenharmony_ci        self.assertEqual(len(d), 0)
1447db96d56Sopenharmony_ci        d = {'a': 1, 'b': 2}
1457db96d56Sopenharmony_ci        self.assertEqual(len(d), 2)
1467db96d56Sopenharmony_ci
1477db96d56Sopenharmony_ci    def test_getitem(self):
1487db96d56Sopenharmony_ci        d = {'a': 1, 'b': 2}
1497db96d56Sopenharmony_ci        self.assertEqual(d['a'], 1)
1507db96d56Sopenharmony_ci        self.assertEqual(d['b'], 2)
1517db96d56Sopenharmony_ci        d['c'] = 3
1527db96d56Sopenharmony_ci        d['a'] = 4
1537db96d56Sopenharmony_ci        self.assertEqual(d['c'], 3)
1547db96d56Sopenharmony_ci        self.assertEqual(d['a'], 4)
1557db96d56Sopenharmony_ci        del d['b']
1567db96d56Sopenharmony_ci        self.assertEqual(d, {'a': 4, 'c': 3})
1577db96d56Sopenharmony_ci
1587db96d56Sopenharmony_ci        self.assertRaises(TypeError, d.__getitem__)
1597db96d56Sopenharmony_ci
1607db96d56Sopenharmony_ci        class BadEq(object):
1617db96d56Sopenharmony_ci            def __eq__(self, other):
1627db96d56Sopenharmony_ci                raise Exc()
1637db96d56Sopenharmony_ci            def __hash__(self):
1647db96d56Sopenharmony_ci                return 24
1657db96d56Sopenharmony_ci
1667db96d56Sopenharmony_ci        d = {}
1677db96d56Sopenharmony_ci        d[BadEq()] = 42
1687db96d56Sopenharmony_ci        self.assertRaises(KeyError, d.__getitem__, 23)
1697db96d56Sopenharmony_ci
1707db96d56Sopenharmony_ci        class Exc(Exception): pass
1717db96d56Sopenharmony_ci
1727db96d56Sopenharmony_ci        class BadHash(object):
1737db96d56Sopenharmony_ci            fail = False
1747db96d56Sopenharmony_ci            def __hash__(self):
1757db96d56Sopenharmony_ci                if self.fail:
1767db96d56Sopenharmony_ci                    raise Exc()
1777db96d56Sopenharmony_ci                else:
1787db96d56Sopenharmony_ci                    return 42
1797db96d56Sopenharmony_ci
1807db96d56Sopenharmony_ci        x = BadHash()
1817db96d56Sopenharmony_ci        d[x] = 42
1827db96d56Sopenharmony_ci        x.fail = True
1837db96d56Sopenharmony_ci        self.assertRaises(Exc, d.__getitem__, x)
1847db96d56Sopenharmony_ci
1857db96d56Sopenharmony_ci    def test_clear(self):
1867db96d56Sopenharmony_ci        d = {1:1, 2:2, 3:3}
1877db96d56Sopenharmony_ci        d.clear()
1887db96d56Sopenharmony_ci        self.assertEqual(d, {})
1897db96d56Sopenharmony_ci
1907db96d56Sopenharmony_ci        self.assertRaises(TypeError, d.clear, None)
1917db96d56Sopenharmony_ci
1927db96d56Sopenharmony_ci    def test_update(self):
1937db96d56Sopenharmony_ci        d = {}
1947db96d56Sopenharmony_ci        d.update({1:100})
1957db96d56Sopenharmony_ci        d.update({2:20})
1967db96d56Sopenharmony_ci        d.update({1:1, 2:2, 3:3})
1977db96d56Sopenharmony_ci        self.assertEqual(d, {1:1, 2:2, 3:3})
1987db96d56Sopenharmony_ci
1997db96d56Sopenharmony_ci        d.update()
2007db96d56Sopenharmony_ci        self.assertEqual(d, {1:1, 2:2, 3:3})
2017db96d56Sopenharmony_ci
2027db96d56Sopenharmony_ci        self.assertRaises((TypeError, AttributeError), d.update, None)
2037db96d56Sopenharmony_ci
2047db96d56Sopenharmony_ci        class SimpleUserDict:
2057db96d56Sopenharmony_ci            def __init__(self):
2067db96d56Sopenharmony_ci                self.d = {1:1, 2:2, 3:3}
2077db96d56Sopenharmony_ci            def keys(self):
2087db96d56Sopenharmony_ci                return self.d.keys()
2097db96d56Sopenharmony_ci            def __getitem__(self, i):
2107db96d56Sopenharmony_ci                return self.d[i]
2117db96d56Sopenharmony_ci        d.clear()
2127db96d56Sopenharmony_ci        d.update(SimpleUserDict())
2137db96d56Sopenharmony_ci        self.assertEqual(d, {1:1, 2:2, 3:3})
2147db96d56Sopenharmony_ci
2157db96d56Sopenharmony_ci        class Exc(Exception): pass
2167db96d56Sopenharmony_ci
2177db96d56Sopenharmony_ci        d.clear()
2187db96d56Sopenharmony_ci        class FailingUserDict:
2197db96d56Sopenharmony_ci            def keys(self):
2207db96d56Sopenharmony_ci                raise Exc
2217db96d56Sopenharmony_ci        self.assertRaises(Exc, d.update, FailingUserDict())
2227db96d56Sopenharmony_ci
2237db96d56Sopenharmony_ci        class FailingUserDict:
2247db96d56Sopenharmony_ci            def keys(self):
2257db96d56Sopenharmony_ci                class BogonIter:
2267db96d56Sopenharmony_ci                    def __init__(self):
2277db96d56Sopenharmony_ci                        self.i = 1
2287db96d56Sopenharmony_ci                    def __iter__(self):
2297db96d56Sopenharmony_ci                        return self
2307db96d56Sopenharmony_ci                    def __next__(self):
2317db96d56Sopenharmony_ci                        if self.i:
2327db96d56Sopenharmony_ci                            self.i = 0
2337db96d56Sopenharmony_ci                            return 'a'
2347db96d56Sopenharmony_ci                        raise Exc
2357db96d56Sopenharmony_ci                return BogonIter()
2367db96d56Sopenharmony_ci            def __getitem__(self, key):
2377db96d56Sopenharmony_ci                return key
2387db96d56Sopenharmony_ci        self.assertRaises(Exc, d.update, FailingUserDict())
2397db96d56Sopenharmony_ci
2407db96d56Sopenharmony_ci        class FailingUserDict:
2417db96d56Sopenharmony_ci            def keys(self):
2427db96d56Sopenharmony_ci                class BogonIter:
2437db96d56Sopenharmony_ci                    def __init__(self):
2447db96d56Sopenharmony_ci                        self.i = ord('a')
2457db96d56Sopenharmony_ci                    def __iter__(self):
2467db96d56Sopenharmony_ci                        return self
2477db96d56Sopenharmony_ci                    def __next__(self):
2487db96d56Sopenharmony_ci                        if self.i <= ord('z'):
2497db96d56Sopenharmony_ci                            rtn = chr(self.i)
2507db96d56Sopenharmony_ci                            self.i += 1
2517db96d56Sopenharmony_ci                            return rtn
2527db96d56Sopenharmony_ci                        raise StopIteration
2537db96d56Sopenharmony_ci                return BogonIter()
2547db96d56Sopenharmony_ci            def __getitem__(self, key):
2557db96d56Sopenharmony_ci                raise Exc
2567db96d56Sopenharmony_ci        self.assertRaises(Exc, d.update, FailingUserDict())
2577db96d56Sopenharmony_ci
2587db96d56Sopenharmony_ci        class badseq(object):
2597db96d56Sopenharmony_ci            def __iter__(self):
2607db96d56Sopenharmony_ci                return self
2617db96d56Sopenharmony_ci            def __next__(self):
2627db96d56Sopenharmony_ci                raise Exc()
2637db96d56Sopenharmony_ci
2647db96d56Sopenharmony_ci        self.assertRaises(Exc, {}.update, badseq())
2657db96d56Sopenharmony_ci
2667db96d56Sopenharmony_ci        self.assertRaises(ValueError, {}.update, [(1, 2, 3)])
2677db96d56Sopenharmony_ci
2687db96d56Sopenharmony_ci    def test_fromkeys(self):
2697db96d56Sopenharmony_ci        self.assertEqual(dict.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
2707db96d56Sopenharmony_ci        d = {}
2717db96d56Sopenharmony_ci        self.assertIsNot(d.fromkeys('abc'), d)
2727db96d56Sopenharmony_ci        self.assertEqual(d.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
2737db96d56Sopenharmony_ci        self.assertEqual(d.fromkeys((4,5),0), {4:0, 5:0})
2747db96d56Sopenharmony_ci        self.assertEqual(d.fromkeys([]), {})
2757db96d56Sopenharmony_ci        def g():
2767db96d56Sopenharmony_ci            yield 1
2777db96d56Sopenharmony_ci        self.assertEqual(d.fromkeys(g()), {1:None})
2787db96d56Sopenharmony_ci        self.assertRaises(TypeError, {}.fromkeys, 3)
2797db96d56Sopenharmony_ci        class dictlike(dict): pass
2807db96d56Sopenharmony_ci        self.assertEqual(dictlike.fromkeys('a'), {'a':None})
2817db96d56Sopenharmony_ci        self.assertEqual(dictlike().fromkeys('a'), {'a':None})
2827db96d56Sopenharmony_ci        self.assertIsInstance(dictlike.fromkeys('a'), dictlike)
2837db96d56Sopenharmony_ci        self.assertIsInstance(dictlike().fromkeys('a'), dictlike)
2847db96d56Sopenharmony_ci        class mydict(dict):
2857db96d56Sopenharmony_ci            def __new__(cls):
2867db96d56Sopenharmony_ci                return collections.UserDict()
2877db96d56Sopenharmony_ci        ud = mydict.fromkeys('ab')
2887db96d56Sopenharmony_ci        self.assertEqual(ud, {'a':None, 'b':None})
2897db96d56Sopenharmony_ci        self.assertIsInstance(ud, collections.UserDict)
2907db96d56Sopenharmony_ci        self.assertRaises(TypeError, dict.fromkeys)
2917db96d56Sopenharmony_ci
2927db96d56Sopenharmony_ci        class Exc(Exception): pass
2937db96d56Sopenharmony_ci
2947db96d56Sopenharmony_ci        class baddict1(dict):
2957db96d56Sopenharmony_ci            def __init__(self):
2967db96d56Sopenharmony_ci                raise Exc()
2977db96d56Sopenharmony_ci
2987db96d56Sopenharmony_ci        self.assertRaises(Exc, baddict1.fromkeys, [1])
2997db96d56Sopenharmony_ci
3007db96d56Sopenharmony_ci        class BadSeq(object):
3017db96d56Sopenharmony_ci            def __iter__(self):
3027db96d56Sopenharmony_ci                return self
3037db96d56Sopenharmony_ci            def __next__(self):
3047db96d56Sopenharmony_ci                raise Exc()
3057db96d56Sopenharmony_ci
3067db96d56Sopenharmony_ci        self.assertRaises(Exc, dict.fromkeys, BadSeq())
3077db96d56Sopenharmony_ci
3087db96d56Sopenharmony_ci        class baddict2(dict):
3097db96d56Sopenharmony_ci            def __setitem__(self, key, value):
3107db96d56Sopenharmony_ci                raise Exc()
3117db96d56Sopenharmony_ci
3127db96d56Sopenharmony_ci        self.assertRaises(Exc, baddict2.fromkeys, [1])
3137db96d56Sopenharmony_ci
3147db96d56Sopenharmony_ci        # test fast path for dictionary inputs
3157db96d56Sopenharmony_ci        d = dict(zip(range(6), range(6)))
3167db96d56Sopenharmony_ci        self.assertEqual(dict.fromkeys(d, 0), dict(zip(range(6), [0]*6)))
3177db96d56Sopenharmony_ci
3187db96d56Sopenharmony_ci        class baddict3(dict):
3197db96d56Sopenharmony_ci            def __new__(cls):
3207db96d56Sopenharmony_ci                return d
3217db96d56Sopenharmony_ci        d = {i : i for i in range(10)}
3227db96d56Sopenharmony_ci        res = d.copy()
3237db96d56Sopenharmony_ci        res.update(a=None, b=None, c=None)
3247db96d56Sopenharmony_ci        self.assertEqual(baddict3.fromkeys({"a", "b", "c"}), res)
3257db96d56Sopenharmony_ci
3267db96d56Sopenharmony_ci    def test_copy(self):
3277db96d56Sopenharmony_ci        d = {1: 1, 2: 2, 3: 3}
3287db96d56Sopenharmony_ci        self.assertIsNot(d.copy(), d)
3297db96d56Sopenharmony_ci        self.assertEqual(d.copy(), d)
3307db96d56Sopenharmony_ci        self.assertEqual(d.copy(), {1: 1, 2: 2, 3: 3})
3317db96d56Sopenharmony_ci
3327db96d56Sopenharmony_ci        copy = d.copy()
3337db96d56Sopenharmony_ci        d[4] = 4
3347db96d56Sopenharmony_ci        self.assertNotEqual(copy, d)
3357db96d56Sopenharmony_ci
3367db96d56Sopenharmony_ci        self.assertEqual({}.copy(), {})
3377db96d56Sopenharmony_ci        self.assertRaises(TypeError, d.copy, None)
3387db96d56Sopenharmony_ci
3397db96d56Sopenharmony_ci    def test_copy_fuzz(self):
3407db96d56Sopenharmony_ci        for dict_size in [10, 100, 1000, 10000, 100000]:
3417db96d56Sopenharmony_ci            dict_size = random.randrange(
3427db96d56Sopenharmony_ci                dict_size // 2, dict_size + dict_size // 2)
3437db96d56Sopenharmony_ci            with self.subTest(dict_size=dict_size):
3447db96d56Sopenharmony_ci                d = {}
3457db96d56Sopenharmony_ci                for i in range(dict_size):
3467db96d56Sopenharmony_ci                    d[i] = i
3477db96d56Sopenharmony_ci
3487db96d56Sopenharmony_ci                d2 = d.copy()
3497db96d56Sopenharmony_ci                self.assertIsNot(d2, d)
3507db96d56Sopenharmony_ci                self.assertEqual(d, d2)
3517db96d56Sopenharmony_ci                d2['key'] = 'value'
3527db96d56Sopenharmony_ci                self.assertNotEqual(d, d2)
3537db96d56Sopenharmony_ci                self.assertEqual(len(d2), len(d) + 1)
3547db96d56Sopenharmony_ci
3557db96d56Sopenharmony_ci    def test_copy_maintains_tracking(self):
3567db96d56Sopenharmony_ci        class A:
3577db96d56Sopenharmony_ci            pass
3587db96d56Sopenharmony_ci
3597db96d56Sopenharmony_ci        key = A()
3607db96d56Sopenharmony_ci
3617db96d56Sopenharmony_ci        for d in ({}, {'a': 1}, {key: 'val'}):
3627db96d56Sopenharmony_ci            d2 = d.copy()
3637db96d56Sopenharmony_ci            self.assertEqual(gc.is_tracked(d), gc.is_tracked(d2))
3647db96d56Sopenharmony_ci
3657db96d56Sopenharmony_ci    def test_copy_noncompact(self):
3667db96d56Sopenharmony_ci        # Dicts don't compact themselves on del/pop operations.
3677db96d56Sopenharmony_ci        # Copy will use a slow merging strategy that produces
3687db96d56Sopenharmony_ci        # a compacted copy when roughly 33% of dict is a non-used
3697db96d56Sopenharmony_ci        # keys-space (to optimize memory footprint).
3707db96d56Sopenharmony_ci        # In this test we want to hit the slow/compacting
3717db96d56Sopenharmony_ci        # branch of dict.copy() and make sure it works OK.
3727db96d56Sopenharmony_ci        d = {k: k for k in range(1000)}
3737db96d56Sopenharmony_ci        for k in range(950):
3747db96d56Sopenharmony_ci            del d[k]
3757db96d56Sopenharmony_ci        d2 = d.copy()
3767db96d56Sopenharmony_ci        self.assertEqual(d2, d)
3777db96d56Sopenharmony_ci
3787db96d56Sopenharmony_ci    def test_get(self):
3797db96d56Sopenharmony_ci        d = {}
3807db96d56Sopenharmony_ci        self.assertIs(d.get('c'), None)
3817db96d56Sopenharmony_ci        self.assertEqual(d.get('c', 3), 3)
3827db96d56Sopenharmony_ci        d = {'a': 1, 'b': 2}
3837db96d56Sopenharmony_ci        self.assertIs(d.get('c'), None)
3847db96d56Sopenharmony_ci        self.assertEqual(d.get('c', 3), 3)
3857db96d56Sopenharmony_ci        self.assertEqual(d.get('a'), 1)
3867db96d56Sopenharmony_ci        self.assertEqual(d.get('a', 3), 1)
3877db96d56Sopenharmony_ci        self.assertRaises(TypeError, d.get)
3887db96d56Sopenharmony_ci        self.assertRaises(TypeError, d.get, None, None, None)
3897db96d56Sopenharmony_ci
3907db96d56Sopenharmony_ci    def test_setdefault(self):
3917db96d56Sopenharmony_ci        # dict.setdefault()
3927db96d56Sopenharmony_ci        d = {}
3937db96d56Sopenharmony_ci        self.assertIs(d.setdefault('key0'), None)
3947db96d56Sopenharmony_ci        d.setdefault('key0', [])
3957db96d56Sopenharmony_ci        self.assertIs(d.setdefault('key0'), None)
3967db96d56Sopenharmony_ci        d.setdefault('key', []).append(3)
3977db96d56Sopenharmony_ci        self.assertEqual(d['key'][0], 3)
3987db96d56Sopenharmony_ci        d.setdefault('key', []).append(4)
3997db96d56Sopenharmony_ci        self.assertEqual(len(d['key']), 2)
4007db96d56Sopenharmony_ci        self.assertRaises(TypeError, d.setdefault)
4017db96d56Sopenharmony_ci
4027db96d56Sopenharmony_ci        class Exc(Exception): pass
4037db96d56Sopenharmony_ci
4047db96d56Sopenharmony_ci        class BadHash(object):
4057db96d56Sopenharmony_ci            fail = False
4067db96d56Sopenharmony_ci            def __hash__(self):
4077db96d56Sopenharmony_ci                if self.fail:
4087db96d56Sopenharmony_ci                    raise Exc()
4097db96d56Sopenharmony_ci                else:
4107db96d56Sopenharmony_ci                    return 42
4117db96d56Sopenharmony_ci
4127db96d56Sopenharmony_ci        x = BadHash()
4137db96d56Sopenharmony_ci        d[x] = 42
4147db96d56Sopenharmony_ci        x.fail = True
4157db96d56Sopenharmony_ci        self.assertRaises(Exc, d.setdefault, x, [])
4167db96d56Sopenharmony_ci
4177db96d56Sopenharmony_ci    def test_setdefault_atomic(self):
4187db96d56Sopenharmony_ci        # Issue #13521: setdefault() calls __hash__ and __eq__ only once.
4197db96d56Sopenharmony_ci        class Hashed(object):
4207db96d56Sopenharmony_ci            def __init__(self):
4217db96d56Sopenharmony_ci                self.hash_count = 0
4227db96d56Sopenharmony_ci                self.eq_count = 0
4237db96d56Sopenharmony_ci            def __hash__(self):
4247db96d56Sopenharmony_ci                self.hash_count += 1
4257db96d56Sopenharmony_ci                return 42
4267db96d56Sopenharmony_ci            def __eq__(self, other):
4277db96d56Sopenharmony_ci                self.eq_count += 1
4287db96d56Sopenharmony_ci                return id(self) == id(other)
4297db96d56Sopenharmony_ci        hashed1 = Hashed()
4307db96d56Sopenharmony_ci        y = {hashed1: 5}
4317db96d56Sopenharmony_ci        hashed2 = Hashed()
4327db96d56Sopenharmony_ci        y.setdefault(hashed2, [])
4337db96d56Sopenharmony_ci        self.assertEqual(hashed1.hash_count, 1)
4347db96d56Sopenharmony_ci        self.assertEqual(hashed2.hash_count, 1)
4357db96d56Sopenharmony_ci        self.assertEqual(hashed1.eq_count + hashed2.eq_count, 1)
4367db96d56Sopenharmony_ci
4377db96d56Sopenharmony_ci    def test_setitem_atomic_at_resize(self):
4387db96d56Sopenharmony_ci        class Hashed(object):
4397db96d56Sopenharmony_ci            def __init__(self):
4407db96d56Sopenharmony_ci                self.hash_count = 0
4417db96d56Sopenharmony_ci                self.eq_count = 0
4427db96d56Sopenharmony_ci            def __hash__(self):
4437db96d56Sopenharmony_ci                self.hash_count += 1
4447db96d56Sopenharmony_ci                return 42
4457db96d56Sopenharmony_ci            def __eq__(self, other):
4467db96d56Sopenharmony_ci                self.eq_count += 1
4477db96d56Sopenharmony_ci                return id(self) == id(other)
4487db96d56Sopenharmony_ci        hashed1 = Hashed()
4497db96d56Sopenharmony_ci        # 5 items
4507db96d56Sopenharmony_ci        y = {hashed1: 5, 0: 0, 1: 1, 2: 2, 3: 3}
4517db96d56Sopenharmony_ci        hashed2 = Hashed()
4527db96d56Sopenharmony_ci        # 6th item forces a resize
4537db96d56Sopenharmony_ci        y[hashed2] = []
4547db96d56Sopenharmony_ci        self.assertEqual(hashed1.hash_count, 1)
4557db96d56Sopenharmony_ci        self.assertEqual(hashed2.hash_count, 1)
4567db96d56Sopenharmony_ci        self.assertEqual(hashed1.eq_count + hashed2.eq_count, 1)
4577db96d56Sopenharmony_ci
4587db96d56Sopenharmony_ci    def test_popitem(self):
4597db96d56Sopenharmony_ci        # dict.popitem()
4607db96d56Sopenharmony_ci        for copymode in -1, +1:
4617db96d56Sopenharmony_ci            # -1: b has same structure as a
4627db96d56Sopenharmony_ci            # +1: b is a.copy()
4637db96d56Sopenharmony_ci            for log2size in range(12):
4647db96d56Sopenharmony_ci                size = 2**log2size
4657db96d56Sopenharmony_ci                a = {}
4667db96d56Sopenharmony_ci                b = {}
4677db96d56Sopenharmony_ci                for i in range(size):
4687db96d56Sopenharmony_ci                    a[repr(i)] = i
4697db96d56Sopenharmony_ci                    if copymode < 0:
4707db96d56Sopenharmony_ci                        b[repr(i)] = i
4717db96d56Sopenharmony_ci                if copymode > 0:
4727db96d56Sopenharmony_ci                    b = a.copy()
4737db96d56Sopenharmony_ci                for i in range(size):
4747db96d56Sopenharmony_ci                    ka, va = ta = a.popitem()
4757db96d56Sopenharmony_ci                    self.assertEqual(va, int(ka))
4767db96d56Sopenharmony_ci                    kb, vb = tb = b.popitem()
4777db96d56Sopenharmony_ci                    self.assertEqual(vb, int(kb))
4787db96d56Sopenharmony_ci                    self.assertFalse(copymode < 0 and ta != tb)
4797db96d56Sopenharmony_ci                self.assertFalse(a)
4807db96d56Sopenharmony_ci                self.assertFalse(b)
4817db96d56Sopenharmony_ci
4827db96d56Sopenharmony_ci        d = {}
4837db96d56Sopenharmony_ci        self.assertRaises(KeyError, d.popitem)
4847db96d56Sopenharmony_ci
4857db96d56Sopenharmony_ci    def test_pop(self):
4867db96d56Sopenharmony_ci        # Tests for pop with specified key
4877db96d56Sopenharmony_ci        d = {}
4887db96d56Sopenharmony_ci        k, v = 'abc', 'def'
4897db96d56Sopenharmony_ci        d[k] = v
4907db96d56Sopenharmony_ci        self.assertRaises(KeyError, d.pop, 'ghi')
4917db96d56Sopenharmony_ci
4927db96d56Sopenharmony_ci        self.assertEqual(d.pop(k), v)
4937db96d56Sopenharmony_ci        self.assertEqual(len(d), 0)
4947db96d56Sopenharmony_ci
4957db96d56Sopenharmony_ci        self.assertRaises(KeyError, d.pop, k)
4967db96d56Sopenharmony_ci
4977db96d56Sopenharmony_ci        self.assertEqual(d.pop(k, v), v)
4987db96d56Sopenharmony_ci        d[k] = v
4997db96d56Sopenharmony_ci        self.assertEqual(d.pop(k, 1), v)
5007db96d56Sopenharmony_ci
5017db96d56Sopenharmony_ci        self.assertRaises(TypeError, d.pop)
5027db96d56Sopenharmony_ci
5037db96d56Sopenharmony_ci        class Exc(Exception): pass
5047db96d56Sopenharmony_ci
5057db96d56Sopenharmony_ci        class BadHash(object):
5067db96d56Sopenharmony_ci            fail = False
5077db96d56Sopenharmony_ci            def __hash__(self):
5087db96d56Sopenharmony_ci                if self.fail:
5097db96d56Sopenharmony_ci                    raise Exc()
5107db96d56Sopenharmony_ci                else:
5117db96d56Sopenharmony_ci                    return 42
5127db96d56Sopenharmony_ci
5137db96d56Sopenharmony_ci        x = BadHash()
5147db96d56Sopenharmony_ci        d[x] = 42
5157db96d56Sopenharmony_ci        x.fail = True
5167db96d56Sopenharmony_ci        self.assertRaises(Exc, d.pop, x)
5177db96d56Sopenharmony_ci
5187db96d56Sopenharmony_ci    def test_mutating_iteration(self):
5197db96d56Sopenharmony_ci        # changing dict size during iteration
5207db96d56Sopenharmony_ci        d = {}
5217db96d56Sopenharmony_ci        d[1] = 1
5227db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError):
5237db96d56Sopenharmony_ci            for i in d:
5247db96d56Sopenharmony_ci                d[i+1] = 1
5257db96d56Sopenharmony_ci
5267db96d56Sopenharmony_ci    def test_mutating_iteration_delete(self):
5277db96d56Sopenharmony_ci        # change dict content during iteration
5287db96d56Sopenharmony_ci        d = {}
5297db96d56Sopenharmony_ci        d[0] = 0
5307db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError):
5317db96d56Sopenharmony_ci            for i in d:
5327db96d56Sopenharmony_ci                del d[0]
5337db96d56Sopenharmony_ci                d[0] = 0
5347db96d56Sopenharmony_ci
5357db96d56Sopenharmony_ci    def test_mutating_iteration_delete_over_values(self):
5367db96d56Sopenharmony_ci        # change dict content during iteration
5377db96d56Sopenharmony_ci        d = {}
5387db96d56Sopenharmony_ci        d[0] = 0
5397db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError):
5407db96d56Sopenharmony_ci            for i in d.values():
5417db96d56Sopenharmony_ci                del d[0]
5427db96d56Sopenharmony_ci                d[0] = 0
5437db96d56Sopenharmony_ci
5447db96d56Sopenharmony_ci    def test_mutating_iteration_delete_over_items(self):
5457db96d56Sopenharmony_ci        # change dict content during iteration
5467db96d56Sopenharmony_ci        d = {}
5477db96d56Sopenharmony_ci        d[0] = 0
5487db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError):
5497db96d56Sopenharmony_ci            for i in d.items():
5507db96d56Sopenharmony_ci                del d[0]
5517db96d56Sopenharmony_ci                d[0] = 0
5527db96d56Sopenharmony_ci
5537db96d56Sopenharmony_ci    def test_mutating_lookup(self):
5547db96d56Sopenharmony_ci        # changing dict during a lookup (issue #14417)
5557db96d56Sopenharmony_ci        class NastyKey:
5567db96d56Sopenharmony_ci            mutate_dict = None
5577db96d56Sopenharmony_ci
5587db96d56Sopenharmony_ci            def __init__(self, value):
5597db96d56Sopenharmony_ci                self.value = value
5607db96d56Sopenharmony_ci
5617db96d56Sopenharmony_ci            def __hash__(self):
5627db96d56Sopenharmony_ci                # hash collision!
5637db96d56Sopenharmony_ci                return 1
5647db96d56Sopenharmony_ci
5657db96d56Sopenharmony_ci            def __eq__(self, other):
5667db96d56Sopenharmony_ci                if NastyKey.mutate_dict:
5677db96d56Sopenharmony_ci                    mydict, key = NastyKey.mutate_dict
5687db96d56Sopenharmony_ci                    NastyKey.mutate_dict = None
5697db96d56Sopenharmony_ci                    del mydict[key]
5707db96d56Sopenharmony_ci                return self.value == other.value
5717db96d56Sopenharmony_ci
5727db96d56Sopenharmony_ci        key1 = NastyKey(1)
5737db96d56Sopenharmony_ci        key2 = NastyKey(2)
5747db96d56Sopenharmony_ci        d = {key1: 1}
5757db96d56Sopenharmony_ci        NastyKey.mutate_dict = (d, key1)
5767db96d56Sopenharmony_ci        d[key2] = 2
5777db96d56Sopenharmony_ci        self.assertEqual(d, {key2: 2})
5787db96d56Sopenharmony_ci
5797db96d56Sopenharmony_ci    def test_repr(self):
5807db96d56Sopenharmony_ci        d = {}
5817db96d56Sopenharmony_ci        self.assertEqual(repr(d), '{}')
5827db96d56Sopenharmony_ci        d[1] = 2
5837db96d56Sopenharmony_ci        self.assertEqual(repr(d), '{1: 2}')
5847db96d56Sopenharmony_ci        d = {}
5857db96d56Sopenharmony_ci        d[1] = d
5867db96d56Sopenharmony_ci        self.assertEqual(repr(d), '{1: {...}}')
5877db96d56Sopenharmony_ci
5887db96d56Sopenharmony_ci        class Exc(Exception): pass
5897db96d56Sopenharmony_ci
5907db96d56Sopenharmony_ci        class BadRepr(object):
5917db96d56Sopenharmony_ci            def __repr__(self):
5927db96d56Sopenharmony_ci                raise Exc()
5937db96d56Sopenharmony_ci
5947db96d56Sopenharmony_ci        d = {1: BadRepr()}
5957db96d56Sopenharmony_ci        self.assertRaises(Exc, repr, d)
5967db96d56Sopenharmony_ci
5977db96d56Sopenharmony_ci    def test_repr_deep(self):
5987db96d56Sopenharmony_ci        d = {}
5997db96d56Sopenharmony_ci        for i in range(sys.getrecursionlimit() + 100):
6007db96d56Sopenharmony_ci            d = {1: d}
6017db96d56Sopenharmony_ci        self.assertRaises(RecursionError, repr, d)
6027db96d56Sopenharmony_ci
6037db96d56Sopenharmony_ci    def test_eq(self):
6047db96d56Sopenharmony_ci        self.assertEqual({}, {})
6057db96d56Sopenharmony_ci        self.assertEqual({1: 2}, {1: 2})
6067db96d56Sopenharmony_ci
6077db96d56Sopenharmony_ci        class Exc(Exception): pass
6087db96d56Sopenharmony_ci
6097db96d56Sopenharmony_ci        class BadCmp(object):
6107db96d56Sopenharmony_ci            def __eq__(self, other):
6117db96d56Sopenharmony_ci                raise Exc()
6127db96d56Sopenharmony_ci            def __hash__(self):
6137db96d56Sopenharmony_ci                return 1
6147db96d56Sopenharmony_ci
6157db96d56Sopenharmony_ci        d1 = {BadCmp(): 1}
6167db96d56Sopenharmony_ci        d2 = {1: 1}
6177db96d56Sopenharmony_ci
6187db96d56Sopenharmony_ci        with self.assertRaises(Exc):
6197db96d56Sopenharmony_ci            d1 == d2
6207db96d56Sopenharmony_ci
6217db96d56Sopenharmony_ci    def test_keys_contained(self):
6227db96d56Sopenharmony_ci        self.helper_keys_contained(lambda x: x.keys())
6237db96d56Sopenharmony_ci        self.helper_keys_contained(lambda x: x.items())
6247db96d56Sopenharmony_ci
6257db96d56Sopenharmony_ci    def helper_keys_contained(self, fn):
6267db96d56Sopenharmony_ci        # Test rich comparisons against dict key views, which should behave the
6277db96d56Sopenharmony_ci        # same as sets.
6287db96d56Sopenharmony_ci        empty = fn(dict())
6297db96d56Sopenharmony_ci        empty2 = fn(dict())
6307db96d56Sopenharmony_ci        smaller = fn({1:1, 2:2})
6317db96d56Sopenharmony_ci        larger = fn({1:1, 2:2, 3:3})
6327db96d56Sopenharmony_ci        larger2 = fn({1:1, 2:2, 3:3})
6337db96d56Sopenharmony_ci        larger3 = fn({4:1, 2:2, 3:3})
6347db96d56Sopenharmony_ci
6357db96d56Sopenharmony_ci        self.assertTrue(smaller <  larger)
6367db96d56Sopenharmony_ci        self.assertTrue(smaller <= larger)
6377db96d56Sopenharmony_ci        self.assertTrue(larger >  smaller)
6387db96d56Sopenharmony_ci        self.assertTrue(larger >= smaller)
6397db96d56Sopenharmony_ci
6407db96d56Sopenharmony_ci        self.assertFalse(smaller >= larger)
6417db96d56Sopenharmony_ci        self.assertFalse(smaller >  larger)
6427db96d56Sopenharmony_ci        self.assertFalse(larger  <= smaller)
6437db96d56Sopenharmony_ci        self.assertFalse(larger  <  smaller)
6447db96d56Sopenharmony_ci
6457db96d56Sopenharmony_ci        self.assertFalse(smaller <  larger3)
6467db96d56Sopenharmony_ci        self.assertFalse(smaller <= larger3)
6477db96d56Sopenharmony_ci        self.assertFalse(larger3 >  smaller)
6487db96d56Sopenharmony_ci        self.assertFalse(larger3 >= smaller)
6497db96d56Sopenharmony_ci
6507db96d56Sopenharmony_ci        # Inequality strictness
6517db96d56Sopenharmony_ci        self.assertTrue(larger2 >= larger)
6527db96d56Sopenharmony_ci        self.assertTrue(larger2 <= larger)
6537db96d56Sopenharmony_ci        self.assertFalse(larger2 > larger)
6547db96d56Sopenharmony_ci        self.assertFalse(larger2 < larger)
6557db96d56Sopenharmony_ci
6567db96d56Sopenharmony_ci        self.assertTrue(larger == larger2)
6577db96d56Sopenharmony_ci        self.assertTrue(smaller != larger)
6587db96d56Sopenharmony_ci
6597db96d56Sopenharmony_ci        # There is an optimization on the zero-element case.
6607db96d56Sopenharmony_ci        self.assertTrue(empty == empty2)
6617db96d56Sopenharmony_ci        self.assertFalse(empty != empty2)
6627db96d56Sopenharmony_ci        self.assertFalse(empty == smaller)
6637db96d56Sopenharmony_ci        self.assertTrue(empty != smaller)
6647db96d56Sopenharmony_ci
6657db96d56Sopenharmony_ci        # With the same size, an elementwise compare happens
6667db96d56Sopenharmony_ci        self.assertTrue(larger != larger3)
6677db96d56Sopenharmony_ci        self.assertFalse(larger == larger3)
6687db96d56Sopenharmony_ci
6697db96d56Sopenharmony_ci    def test_errors_in_view_containment_check(self):
6707db96d56Sopenharmony_ci        class C:
6717db96d56Sopenharmony_ci            def __eq__(self, other):
6727db96d56Sopenharmony_ci                raise RuntimeError
6737db96d56Sopenharmony_ci
6747db96d56Sopenharmony_ci        d1 = {1: C()}
6757db96d56Sopenharmony_ci        d2 = {1: C()}
6767db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError):
6777db96d56Sopenharmony_ci            d1.items() == d2.items()
6787db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError):
6797db96d56Sopenharmony_ci            d1.items() != d2.items()
6807db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError):
6817db96d56Sopenharmony_ci            d1.items() <= d2.items()
6827db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError):
6837db96d56Sopenharmony_ci            d1.items() >= d2.items()
6847db96d56Sopenharmony_ci
6857db96d56Sopenharmony_ci        d3 = {1: C(), 2: C()}
6867db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError):
6877db96d56Sopenharmony_ci            d2.items() < d3.items()
6887db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError):
6897db96d56Sopenharmony_ci            d3.items() > d2.items()
6907db96d56Sopenharmony_ci
6917db96d56Sopenharmony_ci    def test_dictview_set_operations_on_keys(self):
6927db96d56Sopenharmony_ci        k1 = {1:1, 2:2}.keys()
6937db96d56Sopenharmony_ci        k2 = {1:1, 2:2, 3:3}.keys()
6947db96d56Sopenharmony_ci        k3 = {4:4}.keys()
6957db96d56Sopenharmony_ci
6967db96d56Sopenharmony_ci        self.assertEqual(k1 - k2, set())
6977db96d56Sopenharmony_ci        self.assertEqual(k1 - k3, {1,2})
6987db96d56Sopenharmony_ci        self.assertEqual(k2 - k1, {3})
6997db96d56Sopenharmony_ci        self.assertEqual(k3 - k1, {4})
7007db96d56Sopenharmony_ci        self.assertEqual(k1 & k2, {1,2})
7017db96d56Sopenharmony_ci        self.assertEqual(k1 & k3, set())
7027db96d56Sopenharmony_ci        self.assertEqual(k1 | k2, {1,2,3})
7037db96d56Sopenharmony_ci        self.assertEqual(k1 ^ k2, {3})
7047db96d56Sopenharmony_ci        self.assertEqual(k1 ^ k3, {1,2,4})
7057db96d56Sopenharmony_ci
7067db96d56Sopenharmony_ci    def test_dictview_set_operations_on_items(self):
7077db96d56Sopenharmony_ci        k1 = {1:1, 2:2}.items()
7087db96d56Sopenharmony_ci        k2 = {1:1, 2:2, 3:3}.items()
7097db96d56Sopenharmony_ci        k3 = {4:4}.items()
7107db96d56Sopenharmony_ci
7117db96d56Sopenharmony_ci        self.assertEqual(k1 - k2, set())
7127db96d56Sopenharmony_ci        self.assertEqual(k1 - k3, {(1,1), (2,2)})
7137db96d56Sopenharmony_ci        self.assertEqual(k2 - k1, {(3,3)})
7147db96d56Sopenharmony_ci        self.assertEqual(k3 - k1, {(4,4)})
7157db96d56Sopenharmony_ci        self.assertEqual(k1 & k2, {(1,1), (2,2)})
7167db96d56Sopenharmony_ci        self.assertEqual(k1 & k3, set())
7177db96d56Sopenharmony_ci        self.assertEqual(k1 | k2, {(1,1), (2,2), (3,3)})
7187db96d56Sopenharmony_ci        self.assertEqual(k1 ^ k2, {(3,3)})
7197db96d56Sopenharmony_ci        self.assertEqual(k1 ^ k3, {(1,1), (2,2), (4,4)})
7207db96d56Sopenharmony_ci
7217db96d56Sopenharmony_ci    def test_items_symmetric_difference(self):
7227db96d56Sopenharmony_ci        rr = random.randrange
7237db96d56Sopenharmony_ci        for _ in range(100):
7247db96d56Sopenharmony_ci            left = {x:rr(3) for x in range(20) if rr(2)}
7257db96d56Sopenharmony_ci            right = {x:rr(3) for x in range(20) if rr(2)}
7267db96d56Sopenharmony_ci            with self.subTest(left=left, right=right):
7277db96d56Sopenharmony_ci                expected = set(left.items()) ^ set(right.items())
7287db96d56Sopenharmony_ci                actual = left.items() ^ right.items()
7297db96d56Sopenharmony_ci                self.assertEqual(actual, expected)
7307db96d56Sopenharmony_ci
7317db96d56Sopenharmony_ci    def test_dictview_mixed_set_operations(self):
7327db96d56Sopenharmony_ci        # Just a few for .keys()
7337db96d56Sopenharmony_ci        self.assertTrue({1:1}.keys() == {1})
7347db96d56Sopenharmony_ci        self.assertTrue({1} == {1:1}.keys())
7357db96d56Sopenharmony_ci        self.assertEqual({1:1}.keys() | {2}, {1, 2})
7367db96d56Sopenharmony_ci        self.assertEqual({2} | {1:1}.keys(), {1, 2})
7377db96d56Sopenharmony_ci        # And a few for .items()
7387db96d56Sopenharmony_ci        self.assertTrue({1:1}.items() == {(1,1)})
7397db96d56Sopenharmony_ci        self.assertTrue({(1,1)} == {1:1}.items())
7407db96d56Sopenharmony_ci        self.assertEqual({1:1}.items() | {2}, {(1,1), 2})
7417db96d56Sopenharmony_ci        self.assertEqual({2} | {1:1}.items(), {(1,1), 2})
7427db96d56Sopenharmony_ci
7437db96d56Sopenharmony_ci    def test_missing(self):
7447db96d56Sopenharmony_ci        # Make sure dict doesn't have a __missing__ method
7457db96d56Sopenharmony_ci        self.assertFalse(hasattr(dict, "__missing__"))
7467db96d56Sopenharmony_ci        self.assertFalse(hasattr({}, "__missing__"))
7477db96d56Sopenharmony_ci        # Test several cases:
7487db96d56Sopenharmony_ci        # (D) subclass defines __missing__ method returning a value
7497db96d56Sopenharmony_ci        # (E) subclass defines __missing__ method raising RuntimeError
7507db96d56Sopenharmony_ci        # (F) subclass sets __missing__ instance variable (no effect)
7517db96d56Sopenharmony_ci        # (G) subclass doesn't define __missing__ at all
7527db96d56Sopenharmony_ci        class D(dict):
7537db96d56Sopenharmony_ci            def __missing__(self, key):
7547db96d56Sopenharmony_ci                return 42
7557db96d56Sopenharmony_ci        d = D({1: 2, 3: 4})
7567db96d56Sopenharmony_ci        self.assertEqual(d[1], 2)
7577db96d56Sopenharmony_ci        self.assertEqual(d[3], 4)
7587db96d56Sopenharmony_ci        self.assertNotIn(2, d)
7597db96d56Sopenharmony_ci        self.assertNotIn(2, d.keys())
7607db96d56Sopenharmony_ci        self.assertEqual(d[2], 42)
7617db96d56Sopenharmony_ci
7627db96d56Sopenharmony_ci        class E(dict):
7637db96d56Sopenharmony_ci            def __missing__(self, key):
7647db96d56Sopenharmony_ci                raise RuntimeError(key)
7657db96d56Sopenharmony_ci        e = E()
7667db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError) as c:
7677db96d56Sopenharmony_ci            e[42]
7687db96d56Sopenharmony_ci        self.assertEqual(c.exception.args, (42,))
7697db96d56Sopenharmony_ci
7707db96d56Sopenharmony_ci        class F(dict):
7717db96d56Sopenharmony_ci            def __init__(self):
7727db96d56Sopenharmony_ci                # An instance variable __missing__ should have no effect
7737db96d56Sopenharmony_ci                self.__missing__ = lambda key: None
7747db96d56Sopenharmony_ci        f = F()
7757db96d56Sopenharmony_ci        with self.assertRaises(KeyError) as c:
7767db96d56Sopenharmony_ci            f[42]
7777db96d56Sopenharmony_ci        self.assertEqual(c.exception.args, (42,))
7787db96d56Sopenharmony_ci
7797db96d56Sopenharmony_ci        class G(dict):
7807db96d56Sopenharmony_ci            pass
7817db96d56Sopenharmony_ci        g = G()
7827db96d56Sopenharmony_ci        with self.assertRaises(KeyError) as c:
7837db96d56Sopenharmony_ci            g[42]
7847db96d56Sopenharmony_ci        self.assertEqual(c.exception.args, (42,))
7857db96d56Sopenharmony_ci
7867db96d56Sopenharmony_ci    def test_tuple_keyerror(self):
7877db96d56Sopenharmony_ci        # SF #1576657
7887db96d56Sopenharmony_ci        d = {}
7897db96d56Sopenharmony_ci        with self.assertRaises(KeyError) as c:
7907db96d56Sopenharmony_ci            d[(1,)]
7917db96d56Sopenharmony_ci        self.assertEqual(c.exception.args, ((1,),))
7927db96d56Sopenharmony_ci
7937db96d56Sopenharmony_ci    def test_bad_key(self):
7947db96d56Sopenharmony_ci        # Dictionary lookups should fail if __eq__() raises an exception.
7957db96d56Sopenharmony_ci        class CustomException(Exception):
7967db96d56Sopenharmony_ci            pass
7977db96d56Sopenharmony_ci
7987db96d56Sopenharmony_ci        class BadDictKey:
7997db96d56Sopenharmony_ci            def __hash__(self):
8007db96d56Sopenharmony_ci                return hash(self.__class__)
8017db96d56Sopenharmony_ci
8027db96d56Sopenharmony_ci            def __eq__(self, other):
8037db96d56Sopenharmony_ci                if isinstance(other, self.__class__):
8047db96d56Sopenharmony_ci                    raise CustomException
8057db96d56Sopenharmony_ci                return other
8067db96d56Sopenharmony_ci
8077db96d56Sopenharmony_ci        d = {}
8087db96d56Sopenharmony_ci        x1 = BadDictKey()
8097db96d56Sopenharmony_ci        x2 = BadDictKey()
8107db96d56Sopenharmony_ci        d[x1] = 1
8117db96d56Sopenharmony_ci        for stmt in ['d[x2] = 2',
8127db96d56Sopenharmony_ci                     'z = d[x2]',
8137db96d56Sopenharmony_ci                     'x2 in d',
8147db96d56Sopenharmony_ci                     'd.get(x2)',
8157db96d56Sopenharmony_ci                     'd.setdefault(x2, 42)',
8167db96d56Sopenharmony_ci                     'd.pop(x2)',
8177db96d56Sopenharmony_ci                     'd.update({x2: 2})']:
8187db96d56Sopenharmony_ci            with self.assertRaises(CustomException):
8197db96d56Sopenharmony_ci                exec(stmt, locals())
8207db96d56Sopenharmony_ci
8217db96d56Sopenharmony_ci    def test_resize1(self):
8227db96d56Sopenharmony_ci        # Dict resizing bug, found by Jack Jansen in 2.2 CVS development.
8237db96d56Sopenharmony_ci        # This version got an assert failure in debug build, infinite loop in
8247db96d56Sopenharmony_ci        # release build.  Unfortunately, provoking this kind of stuff requires
8257db96d56Sopenharmony_ci        # a mix of inserts and deletes hitting exactly the right hash codes in
8267db96d56Sopenharmony_ci        # exactly the right order, and I can't think of a randomized approach
8277db96d56Sopenharmony_ci        # that would be *likely* to hit a failing case in reasonable time.
8287db96d56Sopenharmony_ci
8297db96d56Sopenharmony_ci        d = {}
8307db96d56Sopenharmony_ci        for i in range(5):
8317db96d56Sopenharmony_ci            d[i] = i
8327db96d56Sopenharmony_ci        for i in range(5):
8337db96d56Sopenharmony_ci            del d[i]
8347db96d56Sopenharmony_ci        for i in range(5, 9):  # i==8 was the problem
8357db96d56Sopenharmony_ci            d[i] = i
8367db96d56Sopenharmony_ci
8377db96d56Sopenharmony_ci    def test_resize2(self):
8387db96d56Sopenharmony_ci        # Another dict resizing bug (SF bug #1456209).
8397db96d56Sopenharmony_ci        # This caused Segmentation faults or Illegal instructions.
8407db96d56Sopenharmony_ci
8417db96d56Sopenharmony_ci        class X(object):
8427db96d56Sopenharmony_ci            def __hash__(self):
8437db96d56Sopenharmony_ci                return 5
8447db96d56Sopenharmony_ci            def __eq__(self, other):
8457db96d56Sopenharmony_ci                if resizing:
8467db96d56Sopenharmony_ci                    d.clear()
8477db96d56Sopenharmony_ci                return False
8487db96d56Sopenharmony_ci        d = {}
8497db96d56Sopenharmony_ci        resizing = False
8507db96d56Sopenharmony_ci        d[X()] = 1
8517db96d56Sopenharmony_ci        d[X()] = 2
8527db96d56Sopenharmony_ci        d[X()] = 3
8537db96d56Sopenharmony_ci        d[X()] = 4
8547db96d56Sopenharmony_ci        d[X()] = 5
8557db96d56Sopenharmony_ci        # now trigger a resize
8567db96d56Sopenharmony_ci        resizing = True
8577db96d56Sopenharmony_ci        d[9] = 6
8587db96d56Sopenharmony_ci
8597db96d56Sopenharmony_ci    def test_empty_presized_dict_in_freelist(self):
8607db96d56Sopenharmony_ci        # Bug #3537: if an empty but presized dict with a size larger
8617db96d56Sopenharmony_ci        # than 7 was in the freelist, it triggered an assertion failure
8627db96d56Sopenharmony_ci        with self.assertRaises(ZeroDivisionError):
8637db96d56Sopenharmony_ci            d = {'a': 1 // 0, 'b': None, 'c': None, 'd': None, 'e': None,
8647db96d56Sopenharmony_ci                 'f': None, 'g': None, 'h': None}
8657db96d56Sopenharmony_ci        d = {}
8667db96d56Sopenharmony_ci
8677db96d56Sopenharmony_ci    def test_container_iterator(self):
8687db96d56Sopenharmony_ci        # Bug #3680: tp_traverse was not implemented for dictiter and
8697db96d56Sopenharmony_ci        # dictview objects.
8707db96d56Sopenharmony_ci        class C(object):
8717db96d56Sopenharmony_ci            pass
8727db96d56Sopenharmony_ci        views = (dict.items, dict.values, dict.keys)
8737db96d56Sopenharmony_ci        for v in views:
8747db96d56Sopenharmony_ci            obj = C()
8757db96d56Sopenharmony_ci            ref = weakref.ref(obj)
8767db96d56Sopenharmony_ci            container = {obj: 1}
8777db96d56Sopenharmony_ci            obj.v = v(container)
8787db96d56Sopenharmony_ci            obj.x = iter(obj.v)
8797db96d56Sopenharmony_ci            del obj, container
8807db96d56Sopenharmony_ci            gc.collect()
8817db96d56Sopenharmony_ci            self.assertIs(ref(), None, "Cycle was not collected")
8827db96d56Sopenharmony_ci
8837db96d56Sopenharmony_ci    def _not_tracked(self, t):
8847db96d56Sopenharmony_ci        # Nested containers can take several collections to untrack
8857db96d56Sopenharmony_ci        gc.collect()
8867db96d56Sopenharmony_ci        gc.collect()
8877db96d56Sopenharmony_ci        self.assertFalse(gc.is_tracked(t), t)
8887db96d56Sopenharmony_ci
8897db96d56Sopenharmony_ci    def _tracked(self, t):
8907db96d56Sopenharmony_ci        self.assertTrue(gc.is_tracked(t), t)
8917db96d56Sopenharmony_ci        gc.collect()
8927db96d56Sopenharmony_ci        gc.collect()
8937db96d56Sopenharmony_ci        self.assertTrue(gc.is_tracked(t), t)
8947db96d56Sopenharmony_ci
8957db96d56Sopenharmony_ci    def test_string_keys_can_track_values(self):
8967db96d56Sopenharmony_ci        # Test that this doesn't leak.
8977db96d56Sopenharmony_ci        for i in range(10):
8987db96d56Sopenharmony_ci            d = {}
8997db96d56Sopenharmony_ci            for j in range(10):
9007db96d56Sopenharmony_ci                d[str(j)] = j
9017db96d56Sopenharmony_ci            d["foo"] = d
9027db96d56Sopenharmony_ci
9037db96d56Sopenharmony_ci    @support.cpython_only
9047db96d56Sopenharmony_ci    def test_track_literals(self):
9057db96d56Sopenharmony_ci        # Test GC-optimization of dict literals
9067db96d56Sopenharmony_ci        x, y, z, w = 1.5, "a", (1, None), []
9077db96d56Sopenharmony_ci
9087db96d56Sopenharmony_ci        self._not_tracked({})
9097db96d56Sopenharmony_ci        self._not_tracked({x:(), y:x, z:1})
9107db96d56Sopenharmony_ci        self._not_tracked({1: "a", "b": 2})
9117db96d56Sopenharmony_ci        self._not_tracked({1: 2, (None, True, False, ()): int})
9127db96d56Sopenharmony_ci        self._not_tracked({1: object()})
9137db96d56Sopenharmony_ci
9147db96d56Sopenharmony_ci        # Dicts with mutable elements are always tracked, even if those
9157db96d56Sopenharmony_ci        # elements are not tracked right now.
9167db96d56Sopenharmony_ci        self._tracked({1: []})
9177db96d56Sopenharmony_ci        self._tracked({1: ([],)})
9187db96d56Sopenharmony_ci        self._tracked({1: {}})
9197db96d56Sopenharmony_ci        self._tracked({1: set()})
9207db96d56Sopenharmony_ci
9217db96d56Sopenharmony_ci    @support.cpython_only
9227db96d56Sopenharmony_ci    def test_track_dynamic(self):
9237db96d56Sopenharmony_ci        # Test GC-optimization of dynamically-created dicts
9247db96d56Sopenharmony_ci        class MyObject(object):
9257db96d56Sopenharmony_ci            pass
9267db96d56Sopenharmony_ci        x, y, z, w, o = 1.5, "a", (1, object()), [], MyObject()
9277db96d56Sopenharmony_ci
9287db96d56Sopenharmony_ci        d = dict()
9297db96d56Sopenharmony_ci        self._not_tracked(d)
9307db96d56Sopenharmony_ci        d[1] = "a"
9317db96d56Sopenharmony_ci        self._not_tracked(d)
9327db96d56Sopenharmony_ci        d[y] = 2
9337db96d56Sopenharmony_ci        self._not_tracked(d)
9347db96d56Sopenharmony_ci        d[z] = 3
9357db96d56Sopenharmony_ci        self._not_tracked(d)
9367db96d56Sopenharmony_ci        self._not_tracked(d.copy())
9377db96d56Sopenharmony_ci        d[4] = w
9387db96d56Sopenharmony_ci        self._tracked(d)
9397db96d56Sopenharmony_ci        self._tracked(d.copy())
9407db96d56Sopenharmony_ci        d[4] = None
9417db96d56Sopenharmony_ci        self._not_tracked(d)
9427db96d56Sopenharmony_ci        self._not_tracked(d.copy())
9437db96d56Sopenharmony_ci
9447db96d56Sopenharmony_ci        # dd isn't tracked right now, but it may mutate and therefore d
9457db96d56Sopenharmony_ci        # which contains it must be tracked.
9467db96d56Sopenharmony_ci        d = dict()
9477db96d56Sopenharmony_ci        dd = dict()
9487db96d56Sopenharmony_ci        d[1] = dd
9497db96d56Sopenharmony_ci        self._not_tracked(dd)
9507db96d56Sopenharmony_ci        self._tracked(d)
9517db96d56Sopenharmony_ci        dd[1] = d
9527db96d56Sopenharmony_ci        self._tracked(dd)
9537db96d56Sopenharmony_ci
9547db96d56Sopenharmony_ci        d = dict.fromkeys([x, y, z])
9557db96d56Sopenharmony_ci        self._not_tracked(d)
9567db96d56Sopenharmony_ci        dd = dict()
9577db96d56Sopenharmony_ci        dd.update(d)
9587db96d56Sopenharmony_ci        self._not_tracked(dd)
9597db96d56Sopenharmony_ci        d = dict.fromkeys([x, y, z, o])
9607db96d56Sopenharmony_ci        self._tracked(d)
9617db96d56Sopenharmony_ci        dd = dict()
9627db96d56Sopenharmony_ci        dd.update(d)
9637db96d56Sopenharmony_ci        self._tracked(dd)
9647db96d56Sopenharmony_ci
9657db96d56Sopenharmony_ci        d = dict(x=x, y=y, z=z)
9667db96d56Sopenharmony_ci        self._not_tracked(d)
9677db96d56Sopenharmony_ci        d = dict(x=x, y=y, z=z, w=w)
9687db96d56Sopenharmony_ci        self._tracked(d)
9697db96d56Sopenharmony_ci        d = dict()
9707db96d56Sopenharmony_ci        d.update(x=x, y=y, z=z)
9717db96d56Sopenharmony_ci        self._not_tracked(d)
9727db96d56Sopenharmony_ci        d.update(w=w)
9737db96d56Sopenharmony_ci        self._tracked(d)
9747db96d56Sopenharmony_ci
9757db96d56Sopenharmony_ci        d = dict([(x, y), (z, 1)])
9767db96d56Sopenharmony_ci        self._not_tracked(d)
9777db96d56Sopenharmony_ci        d = dict([(x, y), (z, w)])
9787db96d56Sopenharmony_ci        self._tracked(d)
9797db96d56Sopenharmony_ci        d = dict()
9807db96d56Sopenharmony_ci        d.update([(x, y), (z, 1)])
9817db96d56Sopenharmony_ci        self._not_tracked(d)
9827db96d56Sopenharmony_ci        d.update([(x, y), (z, w)])
9837db96d56Sopenharmony_ci        self._tracked(d)
9847db96d56Sopenharmony_ci
9857db96d56Sopenharmony_ci    @support.cpython_only
9867db96d56Sopenharmony_ci    def test_track_subtypes(self):
9877db96d56Sopenharmony_ci        # Dict subtypes are always tracked
9887db96d56Sopenharmony_ci        class MyDict(dict):
9897db96d56Sopenharmony_ci            pass
9907db96d56Sopenharmony_ci        self._tracked(MyDict())
9917db96d56Sopenharmony_ci
9927db96d56Sopenharmony_ci    def make_shared_key_dict(self, n):
9937db96d56Sopenharmony_ci        class C:
9947db96d56Sopenharmony_ci            pass
9957db96d56Sopenharmony_ci
9967db96d56Sopenharmony_ci        dicts = []
9977db96d56Sopenharmony_ci        for i in range(n):
9987db96d56Sopenharmony_ci            a = C()
9997db96d56Sopenharmony_ci            a.x, a.y, a.z = 1, 2, 3
10007db96d56Sopenharmony_ci            dicts.append(a.__dict__)
10017db96d56Sopenharmony_ci
10027db96d56Sopenharmony_ci        return dicts
10037db96d56Sopenharmony_ci
10047db96d56Sopenharmony_ci    @support.cpython_only
10057db96d56Sopenharmony_ci    def test_splittable_setdefault(self):
10067db96d56Sopenharmony_ci        """split table must keep correct insertion
10077db96d56Sopenharmony_ci        order when attributes are adding using setdefault()"""
10087db96d56Sopenharmony_ci        a, b = self.make_shared_key_dict(2)
10097db96d56Sopenharmony_ci
10107db96d56Sopenharmony_ci        a['a'] = 1
10117db96d56Sopenharmony_ci        size_a = sys.getsizeof(a)
10127db96d56Sopenharmony_ci        a['b'] = 2
10137db96d56Sopenharmony_ci        b.setdefault('b', 2)
10147db96d56Sopenharmony_ci        size_b = sys.getsizeof(b)
10157db96d56Sopenharmony_ci        b['a'] = 1
10167db96d56Sopenharmony_ci
10177db96d56Sopenharmony_ci        self.assertEqual(list(a), ['x', 'y', 'z', 'a', 'b'])
10187db96d56Sopenharmony_ci        self.assertEqual(list(b), ['x', 'y', 'z', 'b', 'a'])
10197db96d56Sopenharmony_ci
10207db96d56Sopenharmony_ci    @support.cpython_only
10217db96d56Sopenharmony_ci    def test_splittable_del(self):
10227db96d56Sopenharmony_ci        """split table must be combined when del d[k]"""
10237db96d56Sopenharmony_ci        a, b = self.make_shared_key_dict(2)
10247db96d56Sopenharmony_ci
10257db96d56Sopenharmony_ci        orig_size = sys.getsizeof(a)
10267db96d56Sopenharmony_ci
10277db96d56Sopenharmony_ci        del a['y']  # split table is combined
10287db96d56Sopenharmony_ci        with self.assertRaises(KeyError):
10297db96d56Sopenharmony_ci            del a['y']
10307db96d56Sopenharmony_ci
10317db96d56Sopenharmony_ci        self.assertEqual(list(a), ['x', 'z'])
10327db96d56Sopenharmony_ci        self.assertEqual(list(b), ['x', 'y', 'z'])
10337db96d56Sopenharmony_ci
10347db96d56Sopenharmony_ci        # Two dicts have different insertion order.
10357db96d56Sopenharmony_ci        a['y'] = 42
10367db96d56Sopenharmony_ci        self.assertEqual(list(a), ['x', 'z', 'y'])
10377db96d56Sopenharmony_ci        self.assertEqual(list(b), ['x', 'y', 'z'])
10387db96d56Sopenharmony_ci
10397db96d56Sopenharmony_ci    @support.cpython_only
10407db96d56Sopenharmony_ci    def test_splittable_pop(self):
10417db96d56Sopenharmony_ci        a, b = self.make_shared_key_dict(2)
10427db96d56Sopenharmony_ci
10437db96d56Sopenharmony_ci        a.pop('y')
10447db96d56Sopenharmony_ci        with self.assertRaises(KeyError):
10457db96d56Sopenharmony_ci            a.pop('y')
10467db96d56Sopenharmony_ci
10477db96d56Sopenharmony_ci        self.assertEqual(list(a), ['x', 'z'])
10487db96d56Sopenharmony_ci        self.assertEqual(list(b), ['x', 'y', 'z'])
10497db96d56Sopenharmony_ci
10507db96d56Sopenharmony_ci        # Two dicts have different insertion order.
10517db96d56Sopenharmony_ci        a['y'] = 42
10527db96d56Sopenharmony_ci        self.assertEqual(list(a), ['x', 'z', 'y'])
10537db96d56Sopenharmony_ci        self.assertEqual(list(b), ['x', 'y', 'z'])
10547db96d56Sopenharmony_ci
10557db96d56Sopenharmony_ci    @support.cpython_only
10567db96d56Sopenharmony_ci    def test_splittable_pop_pending(self):
10577db96d56Sopenharmony_ci        """pop a pending key in a split table should not crash"""
10587db96d56Sopenharmony_ci        a, b = self.make_shared_key_dict(2)
10597db96d56Sopenharmony_ci
10607db96d56Sopenharmony_ci        a['a'] = 4
10617db96d56Sopenharmony_ci        with self.assertRaises(KeyError):
10627db96d56Sopenharmony_ci            b.pop('a')
10637db96d56Sopenharmony_ci
10647db96d56Sopenharmony_ci    @support.cpython_only
10657db96d56Sopenharmony_ci    def test_splittable_popitem(self):
10667db96d56Sopenharmony_ci        """split table must be combined when d.popitem()"""
10677db96d56Sopenharmony_ci        a, b = self.make_shared_key_dict(2)
10687db96d56Sopenharmony_ci
10697db96d56Sopenharmony_ci        orig_size = sys.getsizeof(a)
10707db96d56Sopenharmony_ci
10717db96d56Sopenharmony_ci        item = a.popitem()  # split table is combined
10727db96d56Sopenharmony_ci        self.assertEqual(item, ('z', 3))
10737db96d56Sopenharmony_ci        with self.assertRaises(KeyError):
10747db96d56Sopenharmony_ci            del a['z']
10757db96d56Sopenharmony_ci
10767db96d56Sopenharmony_ci        self.assertGreater(sys.getsizeof(a), orig_size)
10777db96d56Sopenharmony_ci        self.assertEqual(list(a), ['x', 'y'])
10787db96d56Sopenharmony_ci        self.assertEqual(list(b), ['x', 'y', 'z'])
10797db96d56Sopenharmony_ci
10807db96d56Sopenharmony_ci    @support.cpython_only
10817db96d56Sopenharmony_ci    def test_splittable_update(self):
10827db96d56Sopenharmony_ci        """dict.update(other) must preserve order in other."""
10837db96d56Sopenharmony_ci        class C:
10847db96d56Sopenharmony_ci            def __init__(self, order):
10857db96d56Sopenharmony_ci                if order:
10867db96d56Sopenharmony_ci                    self.a, self.b, self.c = 1, 2, 3
10877db96d56Sopenharmony_ci                else:
10887db96d56Sopenharmony_ci                    self.c, self.b, self.a = 1, 2, 3
10897db96d56Sopenharmony_ci        o = C(True)
10907db96d56Sopenharmony_ci        o = C(False)  # o.__dict__ has reversed order.
10917db96d56Sopenharmony_ci        self.assertEqual(list(o.__dict__), ["c", "b", "a"])
10927db96d56Sopenharmony_ci
10937db96d56Sopenharmony_ci        d = {}
10947db96d56Sopenharmony_ci        d.update(o.__dict__)
10957db96d56Sopenharmony_ci        self.assertEqual(list(d), ["c", "b", "a"])
10967db96d56Sopenharmony_ci
10977db96d56Sopenharmony_ci    def test_iterator_pickling(self):
10987db96d56Sopenharmony_ci        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
10997db96d56Sopenharmony_ci            data = {1:"a", 2:"b", 3:"c"}
11007db96d56Sopenharmony_ci            it = iter(data)
11017db96d56Sopenharmony_ci            d = pickle.dumps(it, proto)
11027db96d56Sopenharmony_ci            it = pickle.loads(d)
11037db96d56Sopenharmony_ci            self.assertEqual(list(it), list(data))
11047db96d56Sopenharmony_ci
11057db96d56Sopenharmony_ci            it = pickle.loads(d)
11067db96d56Sopenharmony_ci            try:
11077db96d56Sopenharmony_ci                drop = next(it)
11087db96d56Sopenharmony_ci            except StopIteration:
11097db96d56Sopenharmony_ci                continue
11107db96d56Sopenharmony_ci            d = pickle.dumps(it, proto)
11117db96d56Sopenharmony_ci            it = pickle.loads(d)
11127db96d56Sopenharmony_ci            del data[drop]
11137db96d56Sopenharmony_ci            self.assertEqual(list(it), list(data))
11147db96d56Sopenharmony_ci
11157db96d56Sopenharmony_ci    def test_itemiterator_pickling(self):
11167db96d56Sopenharmony_ci        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
11177db96d56Sopenharmony_ci            data = {1:"a", 2:"b", 3:"c"}
11187db96d56Sopenharmony_ci            # dictviews aren't picklable, only their iterators
11197db96d56Sopenharmony_ci            itorg = iter(data.items())
11207db96d56Sopenharmony_ci            d = pickle.dumps(itorg, proto)
11217db96d56Sopenharmony_ci            it = pickle.loads(d)
11227db96d56Sopenharmony_ci            # note that the type of the unpickled iterator
11237db96d56Sopenharmony_ci            # is not necessarily the same as the original.  It is
11247db96d56Sopenharmony_ci            # merely an object supporting the iterator protocol, yielding
11257db96d56Sopenharmony_ci            # the same objects as the original one.
11267db96d56Sopenharmony_ci            # self.assertEqual(type(itorg), type(it))
11277db96d56Sopenharmony_ci            self.assertIsInstance(it, collections.abc.Iterator)
11287db96d56Sopenharmony_ci            self.assertEqual(dict(it), data)
11297db96d56Sopenharmony_ci
11307db96d56Sopenharmony_ci            it = pickle.loads(d)
11317db96d56Sopenharmony_ci            drop = next(it)
11327db96d56Sopenharmony_ci            d = pickle.dumps(it, proto)
11337db96d56Sopenharmony_ci            it = pickle.loads(d)
11347db96d56Sopenharmony_ci            del data[drop[0]]
11357db96d56Sopenharmony_ci            self.assertEqual(dict(it), data)
11367db96d56Sopenharmony_ci
11377db96d56Sopenharmony_ci    def test_valuesiterator_pickling(self):
11387db96d56Sopenharmony_ci        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
11397db96d56Sopenharmony_ci            data = {1:"a", 2:"b", 3:"c"}
11407db96d56Sopenharmony_ci            # data.values() isn't picklable, only its iterator
11417db96d56Sopenharmony_ci            it = iter(data.values())
11427db96d56Sopenharmony_ci            d = pickle.dumps(it, proto)
11437db96d56Sopenharmony_ci            it = pickle.loads(d)
11447db96d56Sopenharmony_ci            self.assertEqual(list(it), list(data.values()))
11457db96d56Sopenharmony_ci
11467db96d56Sopenharmony_ci            it = pickle.loads(d)
11477db96d56Sopenharmony_ci            drop = next(it)
11487db96d56Sopenharmony_ci            d = pickle.dumps(it, proto)
11497db96d56Sopenharmony_ci            it = pickle.loads(d)
11507db96d56Sopenharmony_ci            values = list(it) + [drop]
11517db96d56Sopenharmony_ci            self.assertEqual(sorted(values), sorted(list(data.values())))
11527db96d56Sopenharmony_ci
11537db96d56Sopenharmony_ci    def test_reverseiterator_pickling(self):
11547db96d56Sopenharmony_ci        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
11557db96d56Sopenharmony_ci            data = {1:"a", 2:"b", 3:"c"}
11567db96d56Sopenharmony_ci            it = reversed(data)
11577db96d56Sopenharmony_ci            d = pickle.dumps(it, proto)
11587db96d56Sopenharmony_ci            it = pickle.loads(d)
11597db96d56Sopenharmony_ci            self.assertEqual(list(it), list(reversed(data)))
11607db96d56Sopenharmony_ci
11617db96d56Sopenharmony_ci            it = pickle.loads(d)
11627db96d56Sopenharmony_ci            try:
11637db96d56Sopenharmony_ci                drop = next(it)
11647db96d56Sopenharmony_ci            except StopIteration:
11657db96d56Sopenharmony_ci                continue
11667db96d56Sopenharmony_ci            d = pickle.dumps(it, proto)
11677db96d56Sopenharmony_ci            it = pickle.loads(d)
11687db96d56Sopenharmony_ci            del data[drop]
11697db96d56Sopenharmony_ci            self.assertEqual(list(it), list(reversed(data)))
11707db96d56Sopenharmony_ci
11717db96d56Sopenharmony_ci    def test_reverseitemiterator_pickling(self):
11727db96d56Sopenharmony_ci        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
11737db96d56Sopenharmony_ci            data = {1:"a", 2:"b", 3:"c"}
11747db96d56Sopenharmony_ci            # dictviews aren't picklable, only their iterators
11757db96d56Sopenharmony_ci            itorg = reversed(data.items())
11767db96d56Sopenharmony_ci            d = pickle.dumps(itorg, proto)
11777db96d56Sopenharmony_ci            it = pickle.loads(d)
11787db96d56Sopenharmony_ci            # note that the type of the unpickled iterator
11797db96d56Sopenharmony_ci            # is not necessarily the same as the original.  It is
11807db96d56Sopenharmony_ci            # merely an object supporting the iterator protocol, yielding
11817db96d56Sopenharmony_ci            # the same objects as the original one.
11827db96d56Sopenharmony_ci            # self.assertEqual(type(itorg), type(it))
11837db96d56Sopenharmony_ci            self.assertIsInstance(it, collections.abc.Iterator)
11847db96d56Sopenharmony_ci            self.assertEqual(dict(it), data)
11857db96d56Sopenharmony_ci
11867db96d56Sopenharmony_ci            it = pickle.loads(d)
11877db96d56Sopenharmony_ci            drop = next(it)
11887db96d56Sopenharmony_ci            d = pickle.dumps(it, proto)
11897db96d56Sopenharmony_ci            it = pickle.loads(d)
11907db96d56Sopenharmony_ci            del data[drop[0]]
11917db96d56Sopenharmony_ci            self.assertEqual(dict(it), data)
11927db96d56Sopenharmony_ci
11937db96d56Sopenharmony_ci    def test_reversevaluesiterator_pickling(self):
11947db96d56Sopenharmony_ci        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
11957db96d56Sopenharmony_ci            data = {1:"a", 2:"b", 3:"c"}
11967db96d56Sopenharmony_ci            # data.values() isn't picklable, only its iterator
11977db96d56Sopenharmony_ci            it = reversed(data.values())
11987db96d56Sopenharmony_ci            d = pickle.dumps(it, proto)
11997db96d56Sopenharmony_ci            it = pickle.loads(d)
12007db96d56Sopenharmony_ci            self.assertEqual(list(it), list(reversed(data.values())))
12017db96d56Sopenharmony_ci
12027db96d56Sopenharmony_ci            it = pickle.loads(d)
12037db96d56Sopenharmony_ci            drop = next(it)
12047db96d56Sopenharmony_ci            d = pickle.dumps(it, proto)
12057db96d56Sopenharmony_ci            it = pickle.loads(d)
12067db96d56Sopenharmony_ci            values = list(it) + [drop]
12077db96d56Sopenharmony_ci            self.assertEqual(sorted(values), sorted(data.values()))
12087db96d56Sopenharmony_ci
12097db96d56Sopenharmony_ci    def test_instance_dict_getattr_str_subclass(self):
12107db96d56Sopenharmony_ci        class Foo:
12117db96d56Sopenharmony_ci            def __init__(self, msg):
12127db96d56Sopenharmony_ci                self.msg = msg
12137db96d56Sopenharmony_ci        f = Foo('123')
12147db96d56Sopenharmony_ci        class _str(str):
12157db96d56Sopenharmony_ci            pass
12167db96d56Sopenharmony_ci        self.assertEqual(f.msg, getattr(f, _str('msg')))
12177db96d56Sopenharmony_ci        self.assertEqual(f.msg, f.__dict__[_str('msg')])
12187db96d56Sopenharmony_ci
12197db96d56Sopenharmony_ci    def test_object_set_item_single_instance_non_str_key(self):
12207db96d56Sopenharmony_ci        class Foo: pass
12217db96d56Sopenharmony_ci        f = Foo()
12227db96d56Sopenharmony_ci        f.__dict__[1] = 1
12237db96d56Sopenharmony_ci        f.a = 'a'
12247db96d56Sopenharmony_ci        self.assertEqual(f.__dict__, {1:1, 'a':'a'})
12257db96d56Sopenharmony_ci
12267db96d56Sopenharmony_ci    def check_reentrant_insertion(self, mutate):
12277db96d56Sopenharmony_ci        # This object will trigger mutation of the dict when replaced
12287db96d56Sopenharmony_ci        # by another value.  Note this relies on refcounting: the test
12297db96d56Sopenharmony_ci        # won't achieve its purpose on fully-GCed Python implementations.
12307db96d56Sopenharmony_ci        class Mutating:
12317db96d56Sopenharmony_ci            def __del__(self):
12327db96d56Sopenharmony_ci                mutate(d)
12337db96d56Sopenharmony_ci
12347db96d56Sopenharmony_ci        d = {k: Mutating() for k in 'abcdefghijklmnopqr'}
12357db96d56Sopenharmony_ci        for k in list(d):
12367db96d56Sopenharmony_ci            d[k] = k
12377db96d56Sopenharmony_ci
12387db96d56Sopenharmony_ci    def test_reentrant_insertion(self):
12397db96d56Sopenharmony_ci        # Reentrant insertion shouldn't crash (see issue #22653)
12407db96d56Sopenharmony_ci        def mutate(d):
12417db96d56Sopenharmony_ci            d['b'] = 5
12427db96d56Sopenharmony_ci        self.check_reentrant_insertion(mutate)
12437db96d56Sopenharmony_ci
12447db96d56Sopenharmony_ci        def mutate(d):
12457db96d56Sopenharmony_ci            d.update(self.__dict__)
12467db96d56Sopenharmony_ci            d.clear()
12477db96d56Sopenharmony_ci        self.check_reentrant_insertion(mutate)
12487db96d56Sopenharmony_ci
12497db96d56Sopenharmony_ci        def mutate(d):
12507db96d56Sopenharmony_ci            while d:
12517db96d56Sopenharmony_ci                d.popitem()
12527db96d56Sopenharmony_ci        self.check_reentrant_insertion(mutate)
12537db96d56Sopenharmony_ci
12547db96d56Sopenharmony_ci    def test_merge_and_mutate(self):
12557db96d56Sopenharmony_ci        class X:
12567db96d56Sopenharmony_ci            def __hash__(self):
12577db96d56Sopenharmony_ci                return 0
12587db96d56Sopenharmony_ci
12597db96d56Sopenharmony_ci            def __eq__(self, o):
12607db96d56Sopenharmony_ci                other.clear()
12617db96d56Sopenharmony_ci                return False
12627db96d56Sopenharmony_ci
12637db96d56Sopenharmony_ci        l = [(i,0) for i in range(1, 1337)]
12647db96d56Sopenharmony_ci        other = dict(l)
12657db96d56Sopenharmony_ci        other[X()] = 0
12667db96d56Sopenharmony_ci        d = {X(): 0, 1: 1}
12677db96d56Sopenharmony_ci        self.assertRaises(RuntimeError, d.update, other)
12687db96d56Sopenharmony_ci
12697db96d56Sopenharmony_ci    def test_free_after_iterating(self):
12707db96d56Sopenharmony_ci        support.check_free_after_iterating(self, iter, dict)
12717db96d56Sopenharmony_ci        support.check_free_after_iterating(self, lambda d: iter(d.keys()), dict)
12727db96d56Sopenharmony_ci        support.check_free_after_iterating(self, lambda d: iter(d.values()), dict)
12737db96d56Sopenharmony_ci        support.check_free_after_iterating(self, lambda d: iter(d.items()), dict)
12747db96d56Sopenharmony_ci
12757db96d56Sopenharmony_ci    def test_equal_operator_modifying_operand(self):
12767db96d56Sopenharmony_ci        # test fix for seg fault reported in bpo-27945 part 3.
12777db96d56Sopenharmony_ci        class X():
12787db96d56Sopenharmony_ci            def __del__(self):
12797db96d56Sopenharmony_ci                dict_b.clear()
12807db96d56Sopenharmony_ci
12817db96d56Sopenharmony_ci            def __eq__(self, other):
12827db96d56Sopenharmony_ci                dict_a.clear()
12837db96d56Sopenharmony_ci                return True
12847db96d56Sopenharmony_ci
12857db96d56Sopenharmony_ci            def __hash__(self):
12867db96d56Sopenharmony_ci                return 13
12877db96d56Sopenharmony_ci
12887db96d56Sopenharmony_ci        dict_a = {X(): 0}
12897db96d56Sopenharmony_ci        dict_b = {X(): X()}
12907db96d56Sopenharmony_ci        self.assertTrue(dict_a == dict_b)
12917db96d56Sopenharmony_ci
12927db96d56Sopenharmony_ci        # test fix for seg fault reported in bpo-38588 part 1.
12937db96d56Sopenharmony_ci        class Y:
12947db96d56Sopenharmony_ci            def __eq__(self, other):
12957db96d56Sopenharmony_ci                dict_d.clear()
12967db96d56Sopenharmony_ci                return True
12977db96d56Sopenharmony_ci
12987db96d56Sopenharmony_ci        dict_c = {0: Y()}
12997db96d56Sopenharmony_ci        dict_d = {0: set()}
13007db96d56Sopenharmony_ci        self.assertTrue(dict_c == dict_d)
13017db96d56Sopenharmony_ci
13027db96d56Sopenharmony_ci    def test_fromkeys_operator_modifying_dict_operand(self):
13037db96d56Sopenharmony_ci        # test fix for seg fault reported in issue 27945 part 4a.
13047db96d56Sopenharmony_ci        class X(int):
13057db96d56Sopenharmony_ci            def __hash__(self):
13067db96d56Sopenharmony_ci                return 13
13077db96d56Sopenharmony_ci
13087db96d56Sopenharmony_ci            def __eq__(self, other):
13097db96d56Sopenharmony_ci                if len(d) > 1:
13107db96d56Sopenharmony_ci                    d.clear()
13117db96d56Sopenharmony_ci                return False
13127db96d56Sopenharmony_ci
13137db96d56Sopenharmony_ci        d = {}  # this is required to exist so that d can be constructed!
13147db96d56Sopenharmony_ci        d = {X(1): 1, X(2): 2}
13157db96d56Sopenharmony_ci        try:
13167db96d56Sopenharmony_ci            dict.fromkeys(d)  # shouldn't crash
13177db96d56Sopenharmony_ci        except RuntimeError:  # implementation defined
13187db96d56Sopenharmony_ci            pass
13197db96d56Sopenharmony_ci
13207db96d56Sopenharmony_ci    def test_fromkeys_operator_modifying_set_operand(self):
13217db96d56Sopenharmony_ci        # test fix for seg fault reported in issue 27945 part 4b.
13227db96d56Sopenharmony_ci        class X(int):
13237db96d56Sopenharmony_ci            def __hash__(self):
13247db96d56Sopenharmony_ci                return 13
13257db96d56Sopenharmony_ci
13267db96d56Sopenharmony_ci            def __eq__(self, other):
13277db96d56Sopenharmony_ci                if len(d) > 1:
13287db96d56Sopenharmony_ci                    d.clear()
13297db96d56Sopenharmony_ci                return False
13307db96d56Sopenharmony_ci
13317db96d56Sopenharmony_ci        d = {}  # this is required to exist so that d can be constructed!
13327db96d56Sopenharmony_ci        d = {X(1), X(2)}
13337db96d56Sopenharmony_ci        try:
13347db96d56Sopenharmony_ci            dict.fromkeys(d)  # shouldn't crash
13357db96d56Sopenharmony_ci        except RuntimeError:  # implementation defined
13367db96d56Sopenharmony_ci            pass
13377db96d56Sopenharmony_ci
13387db96d56Sopenharmony_ci    def test_dictitems_contains_use_after_free(self):
13397db96d56Sopenharmony_ci        class X:
13407db96d56Sopenharmony_ci            def __eq__(self, other):
13417db96d56Sopenharmony_ci                d.clear()
13427db96d56Sopenharmony_ci                return NotImplemented
13437db96d56Sopenharmony_ci
13447db96d56Sopenharmony_ci        d = {0: set()}
13457db96d56Sopenharmony_ci        (0, X()) in d.items()
13467db96d56Sopenharmony_ci
13477db96d56Sopenharmony_ci    def test_dict_contain_use_after_free(self):
13487db96d56Sopenharmony_ci        # bpo-40489
13497db96d56Sopenharmony_ci        class S(str):
13507db96d56Sopenharmony_ci            def __eq__(self, other):
13517db96d56Sopenharmony_ci                d.clear()
13527db96d56Sopenharmony_ci                return NotImplemented
13537db96d56Sopenharmony_ci
13547db96d56Sopenharmony_ci            def __hash__(self):
13557db96d56Sopenharmony_ci                return hash('test')
13567db96d56Sopenharmony_ci
13577db96d56Sopenharmony_ci        d = {S(): 'value'}
13587db96d56Sopenharmony_ci        self.assertFalse('test' in d)
13597db96d56Sopenharmony_ci
13607db96d56Sopenharmony_ci    def test_init_use_after_free(self):
13617db96d56Sopenharmony_ci        class X:
13627db96d56Sopenharmony_ci            def __hash__(self):
13637db96d56Sopenharmony_ci                pair[:] = []
13647db96d56Sopenharmony_ci                return 13
13657db96d56Sopenharmony_ci
13667db96d56Sopenharmony_ci        pair = [X(), 123]
13677db96d56Sopenharmony_ci        dict([pair])
13687db96d56Sopenharmony_ci
13697db96d56Sopenharmony_ci    def test_oob_indexing_dictiter_iternextitem(self):
13707db96d56Sopenharmony_ci        class X(int):
13717db96d56Sopenharmony_ci            def __del__(self):
13727db96d56Sopenharmony_ci                d.clear()
13737db96d56Sopenharmony_ci
13747db96d56Sopenharmony_ci        d = {i: X(i) for i in range(8)}
13757db96d56Sopenharmony_ci
13767db96d56Sopenharmony_ci        def iter_and_mutate():
13777db96d56Sopenharmony_ci            for result in d.items():
13787db96d56Sopenharmony_ci                if result[0] == 2:
13797db96d56Sopenharmony_ci                    d[2] = None # free d[2] --> X(2).__del__ was called
13807db96d56Sopenharmony_ci
13817db96d56Sopenharmony_ci        self.assertRaises(RuntimeError, iter_and_mutate)
13827db96d56Sopenharmony_ci
13837db96d56Sopenharmony_ci    def test_reversed(self):
13847db96d56Sopenharmony_ci        d = {"a": 1, "b": 2, "foo": 0, "c": 3, "d": 4}
13857db96d56Sopenharmony_ci        del d["foo"]
13867db96d56Sopenharmony_ci        r = reversed(d)
13877db96d56Sopenharmony_ci        self.assertEqual(list(r), list('dcba'))
13887db96d56Sopenharmony_ci        self.assertRaises(StopIteration, next, r)
13897db96d56Sopenharmony_ci
13907db96d56Sopenharmony_ci    def test_reverse_iterator_for_empty_dict(self):
13917db96d56Sopenharmony_ci        # bpo-38525: reversed iterator should work properly
13927db96d56Sopenharmony_ci
13937db96d56Sopenharmony_ci        # empty dict is directly used for reference count test
13947db96d56Sopenharmony_ci        self.assertEqual(list(reversed({})), [])
13957db96d56Sopenharmony_ci        self.assertEqual(list(reversed({}.items())), [])
13967db96d56Sopenharmony_ci        self.assertEqual(list(reversed({}.values())), [])
13977db96d56Sopenharmony_ci        self.assertEqual(list(reversed({}.keys())), [])
13987db96d56Sopenharmony_ci
13997db96d56Sopenharmony_ci        # dict() and {} don't trigger the same code path
14007db96d56Sopenharmony_ci        self.assertEqual(list(reversed(dict())), [])
14017db96d56Sopenharmony_ci        self.assertEqual(list(reversed(dict().items())), [])
14027db96d56Sopenharmony_ci        self.assertEqual(list(reversed(dict().values())), [])
14037db96d56Sopenharmony_ci        self.assertEqual(list(reversed(dict().keys())), [])
14047db96d56Sopenharmony_ci
14057db96d56Sopenharmony_ci    def test_reverse_iterator_for_shared_shared_dicts(self):
14067db96d56Sopenharmony_ci        class A:
14077db96d56Sopenharmony_ci            def __init__(self, x, y):
14087db96d56Sopenharmony_ci                if x: self.x = x
14097db96d56Sopenharmony_ci                if y: self.y = y
14107db96d56Sopenharmony_ci
14117db96d56Sopenharmony_ci        self.assertEqual(list(reversed(A(1, 2).__dict__)), ['y', 'x'])
14127db96d56Sopenharmony_ci        self.assertEqual(list(reversed(A(1, 0).__dict__)), ['x'])
14137db96d56Sopenharmony_ci        self.assertEqual(list(reversed(A(0, 1).__dict__)), ['y'])
14147db96d56Sopenharmony_ci
14157db96d56Sopenharmony_ci    def test_dict_copy_order(self):
14167db96d56Sopenharmony_ci        # bpo-34320
14177db96d56Sopenharmony_ci        od = collections.OrderedDict([('a', 1), ('b', 2)])
14187db96d56Sopenharmony_ci        od.move_to_end('a')
14197db96d56Sopenharmony_ci        expected = list(od.items())
14207db96d56Sopenharmony_ci
14217db96d56Sopenharmony_ci        copy = dict(od)
14227db96d56Sopenharmony_ci        self.assertEqual(list(copy.items()), expected)
14237db96d56Sopenharmony_ci
14247db96d56Sopenharmony_ci        # dict subclass doesn't override __iter__
14257db96d56Sopenharmony_ci        class CustomDict(dict):
14267db96d56Sopenharmony_ci            pass
14277db96d56Sopenharmony_ci
14287db96d56Sopenharmony_ci        pairs = [('a', 1), ('b', 2), ('c', 3)]
14297db96d56Sopenharmony_ci
14307db96d56Sopenharmony_ci        d = CustomDict(pairs)
14317db96d56Sopenharmony_ci        self.assertEqual(pairs, list(dict(d).items()))
14327db96d56Sopenharmony_ci
14337db96d56Sopenharmony_ci        class CustomReversedDict(dict):
14347db96d56Sopenharmony_ci            def keys(self):
14357db96d56Sopenharmony_ci                return reversed(list(dict.keys(self)))
14367db96d56Sopenharmony_ci
14377db96d56Sopenharmony_ci            __iter__ = keys
14387db96d56Sopenharmony_ci
14397db96d56Sopenharmony_ci            def items(self):
14407db96d56Sopenharmony_ci                return reversed(dict.items(self))
14417db96d56Sopenharmony_ci
14427db96d56Sopenharmony_ci        d = CustomReversedDict(pairs)
14437db96d56Sopenharmony_ci        self.assertEqual(pairs[::-1], list(dict(d).items()))
14447db96d56Sopenharmony_ci
14457db96d56Sopenharmony_ci    @support.cpython_only
14467db96d56Sopenharmony_ci    def test_dict_items_result_gc(self):
14477db96d56Sopenharmony_ci        # bpo-42536: dict.items's tuple-reuse speed trick breaks the GC's
14487db96d56Sopenharmony_ci        # assumptions about what can be untracked. Make sure we re-track result
14497db96d56Sopenharmony_ci        # tuples whenever we reuse them.
14507db96d56Sopenharmony_ci        it = iter({None: []}.items())
14517db96d56Sopenharmony_ci        gc.collect()
14527db96d56Sopenharmony_ci        # That GC collection probably untracked the recycled internal result
14537db96d56Sopenharmony_ci        # tuple, which is initialized to (None, None). Make sure it's re-tracked
14547db96d56Sopenharmony_ci        # when it's mutated and returned from __next__:
14557db96d56Sopenharmony_ci        self.assertTrue(gc.is_tracked(next(it)))
14567db96d56Sopenharmony_ci
14577db96d56Sopenharmony_ci    @support.cpython_only
14587db96d56Sopenharmony_ci    def test_dict_items_result_gc_reversed(self):
14597db96d56Sopenharmony_ci        # Same as test_dict_items_result_gc above, but reversed.
14607db96d56Sopenharmony_ci        it = reversed({None: []}.items())
14617db96d56Sopenharmony_ci        gc.collect()
14627db96d56Sopenharmony_ci        self.assertTrue(gc.is_tracked(next(it)))
14637db96d56Sopenharmony_ci
14647db96d56Sopenharmony_ci    def test_str_nonstr(self):
14657db96d56Sopenharmony_ci        # cpython uses a different lookup function if the dict only contains
14667db96d56Sopenharmony_ci        # `str` keys. Make sure the unoptimized path is used when a non-`str`
14677db96d56Sopenharmony_ci        # key appears.
14687db96d56Sopenharmony_ci
14697db96d56Sopenharmony_ci        class StrSub(str):
14707db96d56Sopenharmony_ci            pass
14717db96d56Sopenharmony_ci
14727db96d56Sopenharmony_ci        eq_count = 0
14737db96d56Sopenharmony_ci        # This class compares equal to the string 'key3'
14747db96d56Sopenharmony_ci        class Key3:
14757db96d56Sopenharmony_ci            def __hash__(self):
14767db96d56Sopenharmony_ci                return hash('key3')
14777db96d56Sopenharmony_ci
14787db96d56Sopenharmony_ci            def __eq__(self, other):
14797db96d56Sopenharmony_ci                nonlocal eq_count
14807db96d56Sopenharmony_ci                if isinstance(other, Key3) or isinstance(other, str) and other == 'key3':
14817db96d56Sopenharmony_ci                    eq_count += 1
14827db96d56Sopenharmony_ci                    return True
14837db96d56Sopenharmony_ci                return False
14847db96d56Sopenharmony_ci
14857db96d56Sopenharmony_ci        key3_1 = StrSub('key3')
14867db96d56Sopenharmony_ci        key3_2 = Key3()
14877db96d56Sopenharmony_ci        key3_3 = Key3()
14887db96d56Sopenharmony_ci
14897db96d56Sopenharmony_ci        dicts = []
14907db96d56Sopenharmony_ci
14917db96d56Sopenharmony_ci        # Create dicts of the form `{'key1': 42, 'key2': 43, key3: 44}` in a
14927db96d56Sopenharmony_ci        # bunch of different ways. In all cases, `key3` is not of type `str`.
14937db96d56Sopenharmony_ci        # `key3_1` is a `str` subclass and `key3_2` is a completely unrelated
14947db96d56Sopenharmony_ci        # type.
14957db96d56Sopenharmony_ci        for key3 in (key3_1, key3_2):
14967db96d56Sopenharmony_ci            # A literal
14977db96d56Sopenharmony_ci            dicts.append({'key1': 42, 'key2': 43, key3: 44})
14987db96d56Sopenharmony_ci
14997db96d56Sopenharmony_ci            # key3 inserted via `dict.__setitem__`
15007db96d56Sopenharmony_ci            d = {'key1': 42, 'key2': 43}
15017db96d56Sopenharmony_ci            d[key3] = 44
15027db96d56Sopenharmony_ci            dicts.append(d)
15037db96d56Sopenharmony_ci
15047db96d56Sopenharmony_ci            # key3 inserted via `dict.setdefault`
15057db96d56Sopenharmony_ci            d = {'key1': 42, 'key2': 43}
15067db96d56Sopenharmony_ci            self.assertEqual(d.setdefault(key3, 44), 44)
15077db96d56Sopenharmony_ci            dicts.append(d)
15087db96d56Sopenharmony_ci
15097db96d56Sopenharmony_ci            # key3 inserted via `dict.update`
15107db96d56Sopenharmony_ci            d = {'key1': 42, 'key2': 43}
15117db96d56Sopenharmony_ci            d.update({key3: 44})
15127db96d56Sopenharmony_ci            dicts.append(d)
15137db96d56Sopenharmony_ci
15147db96d56Sopenharmony_ci            # key3 inserted via `dict.__ior__`
15157db96d56Sopenharmony_ci            d = {'key1': 42, 'key2': 43}
15167db96d56Sopenharmony_ci            d |= {key3: 44}
15177db96d56Sopenharmony_ci            dicts.append(d)
15187db96d56Sopenharmony_ci
15197db96d56Sopenharmony_ci            # `dict(iterable)`
15207db96d56Sopenharmony_ci            def make_pairs():
15217db96d56Sopenharmony_ci                yield ('key1', 42)
15227db96d56Sopenharmony_ci                yield ('key2', 43)
15237db96d56Sopenharmony_ci                yield (key3, 44)
15247db96d56Sopenharmony_ci            d = dict(make_pairs())
15257db96d56Sopenharmony_ci            dicts.append(d)
15267db96d56Sopenharmony_ci
15277db96d56Sopenharmony_ci            # `dict.copy`
15287db96d56Sopenharmony_ci            d = d.copy()
15297db96d56Sopenharmony_ci            dicts.append(d)
15307db96d56Sopenharmony_ci
15317db96d56Sopenharmony_ci            # dict comprehension
15327db96d56Sopenharmony_ci            d = {key: 42 + i for i,key in enumerate(['key1', 'key2', key3])}
15337db96d56Sopenharmony_ci            dicts.append(d)
15347db96d56Sopenharmony_ci
15357db96d56Sopenharmony_ci        for d in dicts:
15367db96d56Sopenharmony_ci            with self.subTest(d=d):
15377db96d56Sopenharmony_ci                self.assertEqual(d.get('key1'), 42)
15387db96d56Sopenharmony_ci
15397db96d56Sopenharmony_ci                # Try to make an object that is of type `str` and is equal to
15407db96d56Sopenharmony_ci                # `'key1'`, but (at least on cpython) is a different object.
15417db96d56Sopenharmony_ci                noninterned_key1 = 'ke'
15427db96d56Sopenharmony_ci                noninterned_key1 += 'y1'
15437db96d56Sopenharmony_ci                if support.check_impl_detail(cpython=True):
15447db96d56Sopenharmony_ci                    # suppress a SyntaxWarning
15457db96d56Sopenharmony_ci                    interned_key1 = 'key1'
15467db96d56Sopenharmony_ci                    self.assertFalse(noninterned_key1 is interned_key1)
15477db96d56Sopenharmony_ci                self.assertEqual(d.get(noninterned_key1), 42)
15487db96d56Sopenharmony_ci
15497db96d56Sopenharmony_ci                self.assertEqual(d.get('key3'), 44)
15507db96d56Sopenharmony_ci                self.assertEqual(d.get(key3_1), 44)
15517db96d56Sopenharmony_ci                self.assertEqual(d.get(key3_2), 44)
15527db96d56Sopenharmony_ci
15537db96d56Sopenharmony_ci                # `key3_3` itself is definitely not a dict key, so make sure
15547db96d56Sopenharmony_ci                # that `__eq__` gets called.
15557db96d56Sopenharmony_ci                #
15567db96d56Sopenharmony_ci                # Note that this might not hold for `key3_1` and `key3_2`
15577db96d56Sopenharmony_ci                # because they might be the same object as one of the dict keys,
15587db96d56Sopenharmony_ci                # in which case implementations are allowed to skip the call to
15597db96d56Sopenharmony_ci                # `__eq__`.
15607db96d56Sopenharmony_ci                eq_count = 0
15617db96d56Sopenharmony_ci                self.assertEqual(d.get(key3_3), 44)
15627db96d56Sopenharmony_ci                self.assertGreaterEqual(eq_count, 1)
15637db96d56Sopenharmony_ci
15647db96d56Sopenharmony_ci
15657db96d56Sopenharmony_ciclass CAPITest(unittest.TestCase):
15667db96d56Sopenharmony_ci
15677db96d56Sopenharmony_ci    # Test _PyDict_GetItem_KnownHash()
15687db96d56Sopenharmony_ci    @support.cpython_only
15697db96d56Sopenharmony_ci    def test_getitem_knownhash(self):
15707db96d56Sopenharmony_ci        _testcapi = import_helper.import_module('_testcapi')
15717db96d56Sopenharmony_ci        dict_getitem_knownhash = _testcapi.dict_getitem_knownhash
15727db96d56Sopenharmony_ci
15737db96d56Sopenharmony_ci        d = {'x': 1, 'y': 2, 'z': 3}
15747db96d56Sopenharmony_ci        self.assertEqual(dict_getitem_knownhash(d, 'x', hash('x')), 1)
15757db96d56Sopenharmony_ci        self.assertEqual(dict_getitem_knownhash(d, 'y', hash('y')), 2)
15767db96d56Sopenharmony_ci        self.assertEqual(dict_getitem_knownhash(d, 'z', hash('z')), 3)
15777db96d56Sopenharmony_ci
15787db96d56Sopenharmony_ci        # not a dict
15797db96d56Sopenharmony_ci        self.assertRaises(SystemError, dict_getitem_knownhash, [], 1, hash(1))
15807db96d56Sopenharmony_ci        # key does not exist
15817db96d56Sopenharmony_ci        self.assertRaises(KeyError, dict_getitem_knownhash, {}, 1, hash(1))
15827db96d56Sopenharmony_ci
15837db96d56Sopenharmony_ci        class Exc(Exception): pass
15847db96d56Sopenharmony_ci        class BadEq:
15857db96d56Sopenharmony_ci            def __eq__(self, other):
15867db96d56Sopenharmony_ci                raise Exc
15877db96d56Sopenharmony_ci            def __hash__(self):
15887db96d56Sopenharmony_ci                return 7
15897db96d56Sopenharmony_ci
15907db96d56Sopenharmony_ci        k1, k2 = BadEq(), BadEq()
15917db96d56Sopenharmony_ci        d = {k1: 1}
15927db96d56Sopenharmony_ci        self.assertEqual(dict_getitem_knownhash(d, k1, hash(k1)), 1)
15937db96d56Sopenharmony_ci        self.assertRaises(Exc, dict_getitem_knownhash, d, k2, hash(k2))
15947db96d56Sopenharmony_ci
15957db96d56Sopenharmony_ci
15967db96d56Sopenharmony_cifrom test import mapping_tests
15977db96d56Sopenharmony_ci
15987db96d56Sopenharmony_ciclass GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
15997db96d56Sopenharmony_ci    type2test = dict
16007db96d56Sopenharmony_ci
16017db96d56Sopenharmony_ciclass Dict(dict):
16027db96d56Sopenharmony_ci    pass
16037db96d56Sopenharmony_ci
16047db96d56Sopenharmony_ciclass SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
16057db96d56Sopenharmony_ci    type2test = Dict
16067db96d56Sopenharmony_ci
16077db96d56Sopenharmony_ci
16087db96d56Sopenharmony_ciif __name__ == "__main__":
16097db96d56Sopenharmony_ci    unittest.main()
1610