17db96d56Sopenharmony_ciimport unittest
27db96d56Sopenharmony_cifrom test import support
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_ciclass TestMROEntry(unittest.TestCase):
67db96d56Sopenharmony_ci    def test_mro_entry_signature(self):
77db96d56Sopenharmony_ci        tested = []
87db96d56Sopenharmony_ci        class B: ...
97db96d56Sopenharmony_ci        class C:
107db96d56Sopenharmony_ci            def __mro_entries__(self, *args, **kwargs):
117db96d56Sopenharmony_ci                tested.extend([args, kwargs])
127db96d56Sopenharmony_ci                return (C,)
137db96d56Sopenharmony_ci        c = C()
147db96d56Sopenharmony_ci        self.assertEqual(tested, [])
157db96d56Sopenharmony_ci        class D(B, c): ...
167db96d56Sopenharmony_ci        self.assertEqual(tested[0], ((B, c),))
177db96d56Sopenharmony_ci        self.assertEqual(tested[1], {})
187db96d56Sopenharmony_ci
197db96d56Sopenharmony_ci    def test_mro_entry(self):
207db96d56Sopenharmony_ci        tested = []
217db96d56Sopenharmony_ci        class A: ...
227db96d56Sopenharmony_ci        class B: ...
237db96d56Sopenharmony_ci        class C:
247db96d56Sopenharmony_ci            def __mro_entries__(self, bases):
257db96d56Sopenharmony_ci                tested.append(bases)
267db96d56Sopenharmony_ci                return (self.__class__,)
277db96d56Sopenharmony_ci        c = C()
287db96d56Sopenharmony_ci        self.assertEqual(tested, [])
297db96d56Sopenharmony_ci        class D(A, c, B): ...
307db96d56Sopenharmony_ci        self.assertEqual(tested[-1], (A, c, B))
317db96d56Sopenharmony_ci        self.assertEqual(D.__bases__, (A, C, B))
327db96d56Sopenharmony_ci        self.assertEqual(D.__orig_bases__, (A, c, B))
337db96d56Sopenharmony_ci        self.assertEqual(D.__mro__, (D, A, C, B, object))
347db96d56Sopenharmony_ci        d = D()
357db96d56Sopenharmony_ci        class E(d): ...
367db96d56Sopenharmony_ci        self.assertEqual(tested[-1], (d,))
377db96d56Sopenharmony_ci        self.assertEqual(E.__bases__, (D,))
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ci    def test_mro_entry_none(self):
407db96d56Sopenharmony_ci        tested = []
417db96d56Sopenharmony_ci        class A: ...
427db96d56Sopenharmony_ci        class B: ...
437db96d56Sopenharmony_ci        class C:
447db96d56Sopenharmony_ci            def __mro_entries__(self, bases):
457db96d56Sopenharmony_ci                tested.append(bases)
467db96d56Sopenharmony_ci                return ()
477db96d56Sopenharmony_ci        c = C()
487db96d56Sopenharmony_ci        self.assertEqual(tested, [])
497db96d56Sopenharmony_ci        class D(A, c, B): ...
507db96d56Sopenharmony_ci        self.assertEqual(tested[-1], (A, c, B))
517db96d56Sopenharmony_ci        self.assertEqual(D.__bases__, (A, B))
527db96d56Sopenharmony_ci        self.assertEqual(D.__orig_bases__, (A, c, B))
537db96d56Sopenharmony_ci        self.assertEqual(D.__mro__, (D, A, B, object))
547db96d56Sopenharmony_ci        class E(c): ...
557db96d56Sopenharmony_ci        self.assertEqual(tested[-1], (c,))
567db96d56Sopenharmony_ci        self.assertEqual(E.__bases__, (object,))
577db96d56Sopenharmony_ci        self.assertEqual(E.__orig_bases__, (c,))
587db96d56Sopenharmony_ci        self.assertEqual(E.__mro__, (E, object))
597db96d56Sopenharmony_ci
607db96d56Sopenharmony_ci    def test_mro_entry_with_builtins(self):
617db96d56Sopenharmony_ci        tested = []
627db96d56Sopenharmony_ci        class A: ...
637db96d56Sopenharmony_ci        class C:
647db96d56Sopenharmony_ci            def __mro_entries__(self, bases):
657db96d56Sopenharmony_ci                tested.append(bases)
667db96d56Sopenharmony_ci                return (dict,)
677db96d56Sopenharmony_ci        c = C()
687db96d56Sopenharmony_ci        self.assertEqual(tested, [])
697db96d56Sopenharmony_ci        class D(A, c): ...
707db96d56Sopenharmony_ci        self.assertEqual(tested[-1], (A, c))
717db96d56Sopenharmony_ci        self.assertEqual(D.__bases__, (A, dict))
727db96d56Sopenharmony_ci        self.assertEqual(D.__orig_bases__, (A, c))
737db96d56Sopenharmony_ci        self.assertEqual(D.__mro__, (D, A, dict, object))
747db96d56Sopenharmony_ci
757db96d56Sopenharmony_ci    def test_mro_entry_with_builtins_2(self):
767db96d56Sopenharmony_ci        tested = []
777db96d56Sopenharmony_ci        class C:
787db96d56Sopenharmony_ci            def __mro_entries__(self, bases):
797db96d56Sopenharmony_ci                tested.append(bases)
807db96d56Sopenharmony_ci                return (C,)
817db96d56Sopenharmony_ci        c = C()
827db96d56Sopenharmony_ci        self.assertEqual(tested, [])
837db96d56Sopenharmony_ci        class D(c, dict): ...
847db96d56Sopenharmony_ci        self.assertEqual(tested[-1], (c, dict))
857db96d56Sopenharmony_ci        self.assertEqual(D.__bases__, (C, dict))
867db96d56Sopenharmony_ci        self.assertEqual(D.__orig_bases__, (c, dict))
877db96d56Sopenharmony_ci        self.assertEqual(D.__mro__, (D, C, dict, object))
887db96d56Sopenharmony_ci
897db96d56Sopenharmony_ci    def test_mro_entry_errors(self):
907db96d56Sopenharmony_ci        class C_too_many:
917db96d56Sopenharmony_ci            def __mro_entries__(self, bases, something, other):
927db96d56Sopenharmony_ci                return ()
937db96d56Sopenharmony_ci        c = C_too_many()
947db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
957db96d56Sopenharmony_ci            class D(c): ...
967db96d56Sopenharmony_ci        class C_too_few:
977db96d56Sopenharmony_ci            def __mro_entries__(self):
987db96d56Sopenharmony_ci                return ()
997db96d56Sopenharmony_ci        d = C_too_few()
1007db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
1017db96d56Sopenharmony_ci            class D(d): ...
1027db96d56Sopenharmony_ci
1037db96d56Sopenharmony_ci    def test_mro_entry_errors_2(self):
1047db96d56Sopenharmony_ci        class C_not_callable:
1057db96d56Sopenharmony_ci            __mro_entries__ = "Surprise!"
1067db96d56Sopenharmony_ci        c = C_not_callable()
1077db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
1087db96d56Sopenharmony_ci            class D(c): ...
1097db96d56Sopenharmony_ci        class C_not_tuple:
1107db96d56Sopenharmony_ci            def __mro_entries__(self):
1117db96d56Sopenharmony_ci                return object
1127db96d56Sopenharmony_ci        c = C_not_tuple()
1137db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
1147db96d56Sopenharmony_ci            class D(c): ...
1157db96d56Sopenharmony_ci
1167db96d56Sopenharmony_ci    def test_mro_entry_metaclass(self):
1177db96d56Sopenharmony_ci        meta_args = []
1187db96d56Sopenharmony_ci        class Meta(type):
1197db96d56Sopenharmony_ci            def __new__(mcls, name, bases, ns):
1207db96d56Sopenharmony_ci                meta_args.extend([mcls, name, bases, ns])
1217db96d56Sopenharmony_ci                return super().__new__(mcls, name, bases, ns)
1227db96d56Sopenharmony_ci        class A: ...
1237db96d56Sopenharmony_ci        class C:
1247db96d56Sopenharmony_ci            def __mro_entries__(self, bases):
1257db96d56Sopenharmony_ci                return (A,)
1267db96d56Sopenharmony_ci        c = C()
1277db96d56Sopenharmony_ci        class D(c, metaclass=Meta):
1287db96d56Sopenharmony_ci            x = 1
1297db96d56Sopenharmony_ci        self.assertEqual(meta_args[0], Meta)
1307db96d56Sopenharmony_ci        self.assertEqual(meta_args[1], 'D')
1317db96d56Sopenharmony_ci        self.assertEqual(meta_args[2], (A,))
1327db96d56Sopenharmony_ci        self.assertEqual(meta_args[3]['x'], 1)
1337db96d56Sopenharmony_ci        self.assertEqual(D.__bases__, (A,))
1347db96d56Sopenharmony_ci        self.assertEqual(D.__orig_bases__, (c,))
1357db96d56Sopenharmony_ci        self.assertEqual(D.__mro__, (D, A, object))
1367db96d56Sopenharmony_ci        self.assertEqual(D.__class__, Meta)
1377db96d56Sopenharmony_ci
1387db96d56Sopenharmony_ci    def test_mro_entry_type_call(self):
1397db96d56Sopenharmony_ci        # Substitution should _not_ happen in direct type call
1407db96d56Sopenharmony_ci        class C:
1417db96d56Sopenharmony_ci            def __mro_entries__(self, bases):
1427db96d56Sopenharmony_ci                return ()
1437db96d56Sopenharmony_ci        c = C()
1447db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError,
1457db96d56Sopenharmony_ci                                    "MRO entry resolution; "
1467db96d56Sopenharmony_ci                                    "use types.new_class()"):
1477db96d56Sopenharmony_ci            type('Bad', (c,), {})
1487db96d56Sopenharmony_ci
1497db96d56Sopenharmony_ci
1507db96d56Sopenharmony_ciclass TestClassGetitem(unittest.TestCase):
1517db96d56Sopenharmony_ci    def test_class_getitem(self):
1527db96d56Sopenharmony_ci        getitem_args = []
1537db96d56Sopenharmony_ci        class C:
1547db96d56Sopenharmony_ci            def __class_getitem__(*args, **kwargs):
1557db96d56Sopenharmony_ci                getitem_args.extend([args, kwargs])
1567db96d56Sopenharmony_ci                return None
1577db96d56Sopenharmony_ci        C[int, str]
1587db96d56Sopenharmony_ci        self.assertEqual(getitem_args[0], (C, (int, str)))
1597db96d56Sopenharmony_ci        self.assertEqual(getitem_args[1], {})
1607db96d56Sopenharmony_ci
1617db96d56Sopenharmony_ci    def test_class_getitem_format(self):
1627db96d56Sopenharmony_ci        class C:
1637db96d56Sopenharmony_ci            def __class_getitem__(cls, item):
1647db96d56Sopenharmony_ci                return f'C[{item.__name__}]'
1657db96d56Sopenharmony_ci        self.assertEqual(C[int], 'C[int]')
1667db96d56Sopenharmony_ci        self.assertEqual(C[C], 'C[C]')
1677db96d56Sopenharmony_ci
1687db96d56Sopenharmony_ci    def test_class_getitem_inheritance(self):
1697db96d56Sopenharmony_ci        class C:
1707db96d56Sopenharmony_ci            def __class_getitem__(cls, item):
1717db96d56Sopenharmony_ci                return f'{cls.__name__}[{item.__name__}]'
1727db96d56Sopenharmony_ci        class D(C): ...
1737db96d56Sopenharmony_ci        self.assertEqual(D[int], 'D[int]')
1747db96d56Sopenharmony_ci        self.assertEqual(D[D], 'D[D]')
1757db96d56Sopenharmony_ci
1767db96d56Sopenharmony_ci    def test_class_getitem_inheritance_2(self):
1777db96d56Sopenharmony_ci        class C:
1787db96d56Sopenharmony_ci            def __class_getitem__(cls, item):
1797db96d56Sopenharmony_ci                return 'Should not see this'
1807db96d56Sopenharmony_ci        class D(C):
1817db96d56Sopenharmony_ci            def __class_getitem__(cls, item):
1827db96d56Sopenharmony_ci                return f'{cls.__name__}[{item.__name__}]'
1837db96d56Sopenharmony_ci        self.assertEqual(D[int], 'D[int]')
1847db96d56Sopenharmony_ci        self.assertEqual(D[D], 'D[D]')
1857db96d56Sopenharmony_ci
1867db96d56Sopenharmony_ci    def test_class_getitem_classmethod(self):
1877db96d56Sopenharmony_ci        class C:
1887db96d56Sopenharmony_ci            @classmethod
1897db96d56Sopenharmony_ci            def __class_getitem__(cls, item):
1907db96d56Sopenharmony_ci                return f'{cls.__name__}[{item.__name__}]'
1917db96d56Sopenharmony_ci        class D(C): ...
1927db96d56Sopenharmony_ci        self.assertEqual(D[int], 'D[int]')
1937db96d56Sopenharmony_ci        self.assertEqual(D[D], 'D[D]')
1947db96d56Sopenharmony_ci
1957db96d56Sopenharmony_ci    def test_class_getitem_patched(self):
1967db96d56Sopenharmony_ci        class C:
1977db96d56Sopenharmony_ci            def __init_subclass__(cls):
1987db96d56Sopenharmony_ci                def __class_getitem__(cls, item):
1997db96d56Sopenharmony_ci                    return f'{cls.__name__}[{item.__name__}]'
2007db96d56Sopenharmony_ci                cls.__class_getitem__ = classmethod(__class_getitem__)
2017db96d56Sopenharmony_ci        class D(C): ...
2027db96d56Sopenharmony_ci        self.assertEqual(D[int], 'D[int]')
2037db96d56Sopenharmony_ci        self.assertEqual(D[D], 'D[D]')
2047db96d56Sopenharmony_ci
2057db96d56Sopenharmony_ci    def test_class_getitem_with_builtins(self):
2067db96d56Sopenharmony_ci        class A(dict):
2077db96d56Sopenharmony_ci            called_with = None
2087db96d56Sopenharmony_ci
2097db96d56Sopenharmony_ci            def __class_getitem__(cls, item):
2107db96d56Sopenharmony_ci                cls.called_with = item
2117db96d56Sopenharmony_ci        class B(A):
2127db96d56Sopenharmony_ci            pass
2137db96d56Sopenharmony_ci        self.assertIs(B.called_with, None)
2147db96d56Sopenharmony_ci        B[int]
2157db96d56Sopenharmony_ci        self.assertIs(B.called_with, int)
2167db96d56Sopenharmony_ci
2177db96d56Sopenharmony_ci    def test_class_getitem_errors(self):
2187db96d56Sopenharmony_ci        class C_too_few:
2197db96d56Sopenharmony_ci            def __class_getitem__(cls):
2207db96d56Sopenharmony_ci                return None
2217db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
2227db96d56Sopenharmony_ci            C_too_few[int]
2237db96d56Sopenharmony_ci
2247db96d56Sopenharmony_ci        class C_too_many:
2257db96d56Sopenharmony_ci            def __class_getitem__(cls, one, two):
2267db96d56Sopenharmony_ci                return None
2277db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
2287db96d56Sopenharmony_ci            C_too_many[int]
2297db96d56Sopenharmony_ci
2307db96d56Sopenharmony_ci    def test_class_getitem_errors_2(self):
2317db96d56Sopenharmony_ci        class C:
2327db96d56Sopenharmony_ci            def __class_getitem__(cls, item):
2337db96d56Sopenharmony_ci                return None
2347db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
2357db96d56Sopenharmony_ci            C()[int]
2367db96d56Sopenharmony_ci
2377db96d56Sopenharmony_ci        class E: ...
2387db96d56Sopenharmony_ci        e = E()
2397db96d56Sopenharmony_ci        e.__class_getitem__ = lambda cls, item: 'This will not work'
2407db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
2417db96d56Sopenharmony_ci            e[int]
2427db96d56Sopenharmony_ci
2437db96d56Sopenharmony_ci        class C_not_callable:
2447db96d56Sopenharmony_ci            __class_getitem__ = "Surprise!"
2457db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
2467db96d56Sopenharmony_ci            C_not_callable[int]
2477db96d56Sopenharmony_ci
2487db96d56Sopenharmony_ci        class C_is_none(tuple):
2497db96d56Sopenharmony_ci            __class_getitem__ = None
2507db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "C_is_none"):
2517db96d56Sopenharmony_ci            C_is_none[int]
2527db96d56Sopenharmony_ci
2537db96d56Sopenharmony_ci    def test_class_getitem_metaclass(self):
2547db96d56Sopenharmony_ci        class Meta(type):
2557db96d56Sopenharmony_ci            def __class_getitem__(cls, item):
2567db96d56Sopenharmony_ci                return f'{cls.__name__}[{item.__name__}]'
2577db96d56Sopenharmony_ci        self.assertEqual(Meta[int], 'Meta[int]')
2587db96d56Sopenharmony_ci
2597db96d56Sopenharmony_ci    def test_class_getitem_with_metaclass(self):
2607db96d56Sopenharmony_ci        class Meta(type): pass
2617db96d56Sopenharmony_ci        class C(metaclass=Meta):
2627db96d56Sopenharmony_ci            def __class_getitem__(cls, item):
2637db96d56Sopenharmony_ci                return f'{cls.__name__}[{item.__name__}]'
2647db96d56Sopenharmony_ci        self.assertEqual(C[int], 'C[int]')
2657db96d56Sopenharmony_ci
2667db96d56Sopenharmony_ci    def test_class_getitem_metaclass_first(self):
2677db96d56Sopenharmony_ci        class Meta(type):
2687db96d56Sopenharmony_ci            def __getitem__(cls, item):
2697db96d56Sopenharmony_ci                return 'from metaclass'
2707db96d56Sopenharmony_ci        class C(metaclass=Meta):
2717db96d56Sopenharmony_ci            def __class_getitem__(cls, item):
2727db96d56Sopenharmony_ci                return 'from __class_getitem__'
2737db96d56Sopenharmony_ci        self.assertEqual(C[int], 'from metaclass')
2747db96d56Sopenharmony_ci
2757db96d56Sopenharmony_ci
2767db96d56Sopenharmony_ci@support.cpython_only
2777db96d56Sopenharmony_ciclass CAPITest(unittest.TestCase):
2787db96d56Sopenharmony_ci
2797db96d56Sopenharmony_ci    def test_c_class(self):
2807db96d56Sopenharmony_ci        from _testcapi import Generic, GenericAlias
2817db96d56Sopenharmony_ci        self.assertIsInstance(Generic.__class_getitem__(int), GenericAlias)
2827db96d56Sopenharmony_ci
2837db96d56Sopenharmony_ci        IntGeneric = Generic[int]
2847db96d56Sopenharmony_ci        self.assertIs(type(IntGeneric), GenericAlias)
2857db96d56Sopenharmony_ci        self.assertEqual(IntGeneric.__mro_entries__(()), (int,))
2867db96d56Sopenharmony_ci        class C(IntGeneric):
2877db96d56Sopenharmony_ci            pass
2887db96d56Sopenharmony_ci        self.assertEqual(C.__bases__, (int,))
2897db96d56Sopenharmony_ci        self.assertEqual(C.__orig_bases__, (IntGeneric,))
2907db96d56Sopenharmony_ci        self.assertEqual(C.__mro__, (C, int, object))
2917db96d56Sopenharmony_ci
2927db96d56Sopenharmony_ci
2937db96d56Sopenharmony_ciif __name__ == "__main__":
2947db96d56Sopenharmony_ci    unittest.main()
295