test_genericclass.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. import unittest
  2. from test import support
  3. class TestMROEntry(unittest.TestCase):
  4. def test_mro_entry_signature(self):
  5. tested = []
  6. class B: ...
  7. class C:
  8. def __mro_entries__(self, *args, **kwargs):
  9. tested.extend([args, kwargs])
  10. return (C,)
  11. c = C()
  12. self.assertEqual(tested, [])
  13. class D(B, c): ...
  14. self.assertEqual(tested[0], ((B, c),))
  15. self.assertEqual(tested[1], {})
  16. def test_mro_entry(self):
  17. tested = []
  18. class A: ...
  19. class B: ...
  20. class C:
  21. def __mro_entries__(self, bases):
  22. tested.append(bases)
  23. return (self.__class__,)
  24. c = C()
  25. self.assertEqual(tested, [])
  26. class D(A, c, B): ...
  27. self.assertEqual(tested[-1], (A, c, B))
  28. self.assertEqual(D.__bases__, (A, C, B))
  29. self.assertEqual(D.__orig_bases__, (A, c, B))
  30. self.assertEqual(D.__mro__, (D, A, C, B, object))
  31. d = D()
  32. class E(d): ...
  33. self.assertEqual(tested[-1], (d,))
  34. self.assertEqual(E.__bases__, (D,))
  35. def test_mro_entry_none(self):
  36. tested = []
  37. class A: ...
  38. class B: ...
  39. class C:
  40. def __mro_entries__(self, bases):
  41. tested.append(bases)
  42. return ()
  43. c = C()
  44. self.assertEqual(tested, [])
  45. class D(A, c, B): ...
  46. self.assertEqual(tested[-1], (A, c, B))
  47. self.assertEqual(D.__bases__, (A, B))
  48. self.assertEqual(D.__orig_bases__, (A, c, B))
  49. self.assertEqual(D.__mro__, (D, A, B, object))
  50. class E(c): ...
  51. self.assertEqual(tested[-1], (c,))
  52. self.assertEqual(E.__bases__, (object,))
  53. self.assertEqual(E.__orig_bases__, (c,))
  54. self.assertEqual(E.__mro__, (E, object))
  55. def test_mro_entry_with_builtins(self):
  56. tested = []
  57. class A: ...
  58. class C:
  59. def __mro_entries__(self, bases):
  60. tested.append(bases)
  61. return (dict,)
  62. c = C()
  63. self.assertEqual(tested, [])
  64. class D(A, c): ...
  65. self.assertEqual(tested[-1], (A, c))
  66. self.assertEqual(D.__bases__, (A, dict))
  67. self.assertEqual(D.__orig_bases__, (A, c))
  68. self.assertEqual(D.__mro__, (D, A, dict, object))
  69. def test_mro_entry_with_builtins_2(self):
  70. tested = []
  71. class C:
  72. def __mro_entries__(self, bases):
  73. tested.append(bases)
  74. return (C,)
  75. c = C()
  76. self.assertEqual(tested, [])
  77. class D(c, dict): ...
  78. self.assertEqual(tested[-1], (c, dict))
  79. self.assertEqual(D.__bases__, (C, dict))
  80. self.assertEqual(D.__orig_bases__, (c, dict))
  81. self.assertEqual(D.__mro__, (D, C, dict, object))
  82. def test_mro_entry_errors(self):
  83. class C_too_many:
  84. def __mro_entries__(self, bases, something, other):
  85. return ()
  86. c = C_too_many()
  87. with self.assertRaises(TypeError):
  88. class D(c): ...
  89. class C_too_few:
  90. def __mro_entries__(self):
  91. return ()
  92. d = C_too_few()
  93. with self.assertRaises(TypeError):
  94. class D(d): ...
  95. def test_mro_entry_errors_2(self):
  96. class C_not_callable:
  97. __mro_entries__ = "Surprise!"
  98. c = C_not_callable()
  99. with self.assertRaises(TypeError):
  100. class D(c): ...
  101. class C_not_tuple:
  102. def __mro_entries__(self):
  103. return object
  104. c = C_not_tuple()
  105. with self.assertRaises(TypeError):
  106. class D(c): ...
  107. def test_mro_entry_metaclass(self):
  108. meta_args = []
  109. class Meta(type):
  110. def __new__(mcls, name, bases, ns):
  111. meta_args.extend([mcls, name, bases, ns])
  112. return super().__new__(mcls, name, bases, ns)
  113. class A: ...
  114. class C:
  115. def __mro_entries__(self, bases):
  116. return (A,)
  117. c = C()
  118. class D(c, metaclass=Meta):
  119. x = 1
  120. self.assertEqual(meta_args[0], Meta)
  121. self.assertEqual(meta_args[1], 'D')
  122. self.assertEqual(meta_args[2], (A,))
  123. self.assertEqual(meta_args[3]['x'], 1)
  124. self.assertEqual(D.__bases__, (A,))
  125. self.assertEqual(D.__orig_bases__, (c,))
  126. self.assertEqual(D.__mro__, (D, A, object))
  127. self.assertEqual(D.__class__, Meta)
  128. def test_mro_entry_type_call(self):
  129. # Substitution should _not_ happen in direct type call
  130. class C:
  131. def __mro_entries__(self, bases):
  132. return ()
  133. c = C()
  134. with self.assertRaisesRegex(TypeError,
  135. "MRO entry resolution; "
  136. "use types.new_class()"):
  137. type('Bad', (c,), {})
  138. class TestClassGetitem(unittest.TestCase):
  139. def test_class_getitem(self):
  140. getitem_args = []
  141. class C:
  142. def __class_getitem__(*args, **kwargs):
  143. getitem_args.extend([args, kwargs])
  144. return None
  145. C[int, str]
  146. self.assertEqual(getitem_args[0], (C, (int, str)))
  147. self.assertEqual(getitem_args[1], {})
  148. def test_class_getitem_format(self):
  149. class C:
  150. def __class_getitem__(cls, item):
  151. return f'C[{item.__name__}]'
  152. self.assertEqual(C[int], 'C[int]')
  153. self.assertEqual(C[C], 'C[C]')
  154. def test_class_getitem_inheritance(self):
  155. class C:
  156. def __class_getitem__(cls, item):
  157. return f'{cls.__name__}[{item.__name__}]'
  158. class D(C): ...
  159. self.assertEqual(D[int], 'D[int]')
  160. self.assertEqual(D[D], 'D[D]')
  161. def test_class_getitem_inheritance_2(self):
  162. class C:
  163. def __class_getitem__(cls, item):
  164. return 'Should not see this'
  165. class D(C):
  166. def __class_getitem__(cls, item):
  167. return f'{cls.__name__}[{item.__name__}]'
  168. self.assertEqual(D[int], 'D[int]')
  169. self.assertEqual(D[D], 'D[D]')
  170. def test_class_getitem_classmethod(self):
  171. class C:
  172. @classmethod
  173. def __class_getitem__(cls, item):
  174. return f'{cls.__name__}[{item.__name__}]'
  175. class D(C): ...
  176. self.assertEqual(D[int], 'D[int]')
  177. self.assertEqual(D[D], 'D[D]')
  178. def test_class_getitem_patched(self):
  179. class C:
  180. def __init_subclass__(cls):
  181. def __class_getitem__(cls, item):
  182. return f'{cls.__name__}[{item.__name__}]'
  183. cls.__class_getitem__ = classmethod(__class_getitem__)
  184. class D(C): ...
  185. self.assertEqual(D[int], 'D[int]')
  186. self.assertEqual(D[D], 'D[D]')
  187. def test_class_getitem_with_builtins(self):
  188. class A(dict):
  189. called_with = None
  190. def __class_getitem__(cls, item):
  191. cls.called_with = item
  192. class B(A):
  193. pass
  194. self.assertIs(B.called_with, None)
  195. B[int]
  196. self.assertIs(B.called_with, int)
  197. def test_class_getitem_errors(self):
  198. class C_too_few:
  199. def __class_getitem__(cls):
  200. return None
  201. with self.assertRaises(TypeError):
  202. C_too_few[int]
  203. class C_too_many:
  204. def __class_getitem__(cls, one, two):
  205. return None
  206. with self.assertRaises(TypeError):
  207. C_too_many[int]
  208. def test_class_getitem_errors_2(self):
  209. class C:
  210. def __class_getitem__(cls, item):
  211. return None
  212. with self.assertRaises(TypeError):
  213. C()[int]
  214. class E: ...
  215. e = E()
  216. e.__class_getitem__ = lambda cls, item: 'This will not work'
  217. with self.assertRaises(TypeError):
  218. e[int]
  219. class C_not_callable:
  220. __class_getitem__ = "Surprise!"
  221. with self.assertRaises(TypeError):
  222. C_not_callable[int]
  223. class C_is_none(tuple):
  224. __class_getitem__ = None
  225. with self.assertRaisesRegex(TypeError, "C_is_none"):
  226. C_is_none[int]
  227. def test_class_getitem_metaclass(self):
  228. class Meta(type):
  229. def __class_getitem__(cls, item):
  230. return f'{cls.__name__}[{item.__name__}]'
  231. self.assertEqual(Meta[int], 'Meta[int]')
  232. def test_class_getitem_with_metaclass(self):
  233. class Meta(type): pass
  234. class C(metaclass=Meta):
  235. def __class_getitem__(cls, item):
  236. return f'{cls.__name__}[{item.__name__}]'
  237. self.assertEqual(C[int], 'C[int]')
  238. def test_class_getitem_metaclass_first(self):
  239. class Meta(type):
  240. def __getitem__(cls, item):
  241. return 'from metaclass'
  242. class C(metaclass=Meta):
  243. def __class_getitem__(cls, item):
  244. return 'from __class_getitem__'
  245. self.assertEqual(C[int], 'from metaclass')
  246. @support.cpython_only
  247. class CAPITest(unittest.TestCase):
  248. def test_c_class(self):
  249. from _testcapi import Generic, GenericAlias
  250. self.assertIsInstance(Generic.__class_getitem__(int), GenericAlias)
  251. IntGeneric = Generic[int]
  252. self.assertIs(type(IntGeneric), GenericAlias)
  253. self.assertEqual(IntGeneric.__mro_entries__(()), (int,))
  254. class C(IntGeneric):
  255. pass
  256. self.assertEqual(C.__bases__, (int,))
  257. self.assertEqual(C.__orig_bases__, (IntGeneric,))
  258. self.assertEqual(C.__mro__, (C, int, object))
  259. if __name__ == "__main__":
  260. unittest.main()