cython

Форк
0
/
test_genericclass.py 
288 строк · 9.2 Кб
1
# mode: run
2
# tag: pure3.7
3
# cython: language_level=3
4

5
# COPIED FROM CPython 3.7
6

7
import contextlib
8
import unittest
9
import sys
10

11
class TestMROEntry(unittest.TestCase):
12
    def test_mro_entry_signature(self):
13
        tested = []
14
        class B: ...
15
        class C:
16
            def __mro_entries__(self, *args, **kwargs):
17
                tested.extend([args, kwargs])
18
                return (C,)
19
        c = C()
20
        self.assertEqual(tested, [])
21
        class D(B, c): ...
22
        self.assertEqual(tested[0], ((B, c),))
23
        self.assertEqual(tested[1], {})
24

25
    def test_mro_entry(self):
26
        tested = []
27
        class A: ...
28
        class B: ...
29
        class C:
30
            def __mro_entries__(self, bases):
31
                tested.append(bases)
32
                return (self.__class__,)
33
        c = C()
34
        self.assertEqual(tested, [])
35
        class D(A, c, B): ...
36
        self.assertEqual(tested[-1], (A, c, B))
37
        self.assertEqual(D.__bases__, (A, C, B))
38
        self.assertEqual(D.__orig_bases__, (A, c, B))
39
        self.assertEqual(D.__mro__, (D, A, C, B, object))
40
        d = D()
41
        class E(d): ...
42
        self.assertEqual(tested[-1], (d,))
43
        self.assertEqual(E.__bases__, (D,))
44

45
    def test_mro_entry_none(self):
46
        tested = []
47
        class A: ...
48
        class B: ...
49
        class C:
50
            def __mro_entries__(self, bases):
51
                tested.append(bases)
52
                return ()
53
        c = C()
54
        self.assertEqual(tested, [])
55
        class D(A, c, B): ...
56
        self.assertEqual(tested[-1], (A, c, B))
57
        self.assertEqual(D.__bases__, (A, B))
58
        self.assertEqual(D.__orig_bases__, (A, c, B))
59
        self.assertEqual(D.__mro__, (D, A, B, object))
60
        class E(c): ...
61
        self.assertEqual(tested[-1], (c,))
62
        self.assertEqual(E.__bases__, (object,))
63
        self.assertEqual(E.__orig_bases__, (c,))
64
        self.assertEqual(E.__mro__, (E, object))
65

66
    def test_mro_entry_with_builtins(self):
67
        tested = []
68
        class A: ...
69
        class C:
70
            def __mro_entries__(self, bases):
71
                tested.append(bases)
72
                return (dict,)
73
        c = C()
74
        self.assertEqual(tested, [])
75
        class D(A, c): ...
76
        self.assertEqual(tested[-1], (A, c))
77
        self.assertEqual(D.__bases__, (A, dict))
78
        self.assertEqual(D.__orig_bases__, (A, c))
79
        self.assertEqual(D.__mro__, (D, A, dict, object))
80

81
    def test_mro_entry_with_builtins_2(self):
82
        tested = []
83
        class C:
84
            def __mro_entries__(self, bases):
85
                tested.append(bases)
86
                return (C,)
87
        c = C()
88
        self.assertEqual(tested, [])
89
        class D(c, dict): ...
90
        self.assertEqual(tested[-1], (c, dict))
91
        self.assertEqual(D.__bases__, (C, dict))
92
        self.assertEqual(D.__orig_bases__, (c, dict))
93
        self.assertEqual(D.__mro__, (D, C, dict, object))
94

95
    def test_mro_entry_errors(self):
96
        class C_too_many:
97
            def __mro_entries__(self, bases, something, other):
98
                return ()
99
        c = C_too_many()
100
        with self.assertRaises(TypeError):
101
            class D(c): ...
102
        class C_too_few:
103
            def __mro_entries__(self):
104
                return ()
105
        d = C_too_few()
106
        with self.assertRaises(TypeError):
107
            class D(d): ...
108

109
    def test_mro_entry_errors_2(self):
110
        class C_not_callable:
111
            __mro_entries__ = "Surprise!"
112
        c = C_not_callable()
113
        with self.assertRaises(TypeError):
114
            class D(c): ...
115
        class C_not_tuple:
116
            def __mro_entries__(self):
117
                return object
118
        c = C_not_tuple()
119
        with self.assertRaises(TypeError):
120
            class D(c): ...
121

122
    def test_mro_entry_metaclass(self):
123
        meta_args = []
124
        class Meta(type):
125
            def __new__(mcls, name, bases, ns):
126
                meta_args.extend([mcls, name, bases, ns])
127
                return super().__new__(mcls, name, bases, ns)
128
        class A: ...
129
        class C:
130
            def __mro_entries__(self, bases):
131
                return (A,)
132
        c = C()
133
        class D(c, metaclass=Meta):
134
            x = 1
135
        self.assertEqual(meta_args[0], Meta)
136
        self.assertEqual(meta_args[1], 'D')
137
        self.assertEqual(meta_args[2], (A,))
138
        self.assertEqual(meta_args[3]['x'], 1)
139
        self.assertEqual(D.__bases__, (A,))
140
        self.assertEqual(D.__orig_bases__, (c,))
141
        self.assertEqual(D.__mro__, (D, A, object))
142
        self.assertEqual(D.__class__, Meta)
143

144
    def test_mro_entry_type_call(self):
145
        # Substitution should _not_ happen in direct type call
146
        class C:
147
            def __mro_entries__(self, bases):
148
                return ()
149
        c = C()
150
        with self.assertRaisesRegex(TypeError,
151
                                    "MRO entry resolution; "
152
                                    "use types.new_class()"):
153
            type('Bad', (c,), {})
154

155

156
class TestClassGetitem(unittest.TestCase):
157
    # BEGIN - Additional tests from cython
158
    def test_no_class_getitem(self):
159
        class C: ...
160
        # PyPy<7.3.8 raises AttributeError on __class_getitem__
161
        if hasattr(sys, "pypy_version_info")  and sys.pypy_version_info < (7, 3, 8):
162
            err = AttributeError
163
        else:
164
            err = TypeError
165
        with self.assertRaises(err):
166
            C[int]
167

168
    # END - Additional tests from cython
169

170
    def test_class_getitem(self):
171
        getitem_args = []
172
        class C:
173
            def __class_getitem__(*args, **kwargs):
174
                getitem_args.extend([args, kwargs])
175
                return None
176
        C[int, str]
177
        self.assertEqual(getitem_args[0], (C, (int, str)))
178
        self.assertEqual(getitem_args[1], {})
179

180
    def test_class_getitem_format(self):
181
        class C:
182
            def __class_getitem__(cls, item):
183
                return f'C[{item.__name__}]'
184
        self.assertEqual(C[int], 'C[int]')
185
        self.assertEqual(C[C], 'C[C]')
186

187
    def test_class_getitem_inheritance(self):
188
        class C:
189
            def __class_getitem__(cls, item):
190
                return f'{cls.__name__}[{item.__name__}]'
191
        class D(C): ...
192
        self.assertEqual(D[int], 'D[int]')
193
        self.assertEqual(D[D], 'D[D]')
194

195
    def test_class_getitem_inheritance_2(self):
196
        class C:
197
            def __class_getitem__(cls, item):
198
                return 'Should not see this'
199
        class D(C):
200
            def __class_getitem__(cls, item):
201
                return f'{cls.__name__}[{item.__name__}]'
202
        self.assertEqual(D[int], 'D[int]')
203
        self.assertEqual(D[D], 'D[D]')
204

205
    def test_class_getitem_classmethod(self):
206
        class C:
207
            @classmethod
208
            def __class_getitem__(cls, item):
209
                return f'{cls.__name__}[{item.__name__}]'
210
        class D(C): ...
211
        self.assertEqual(D[int], 'D[int]')
212
        self.assertEqual(D[D], 'D[D]')
213

214
    def test_class_getitem_patched(self):
215
        class C:
216
            def __init_subclass__(cls):
217
                def __class_getitem__(cls, item):
218
                    return f'{cls.__name__}[{item.__name__}]'
219
                cls.__class_getitem__ = classmethod(__class_getitem__)
220
        class D(C): ...
221
        self.assertEqual(D[int], 'D[int]')
222
        self.assertEqual(D[D], 'D[D]')
223

224
    def test_class_getitem_with_builtins(self):
225
        class A(dict):
226
            called_with = None
227

228
            def __class_getitem__(cls, item):
229
                cls.called_with = item
230
        class B(A):
231
            pass
232
        self.assertIs(B.called_with, None)
233
        B[int]
234
        self.assertIs(B.called_with, int)
235

236
    def test_class_getitem_errors(self):
237
        class C_too_few:
238
            def __class_getitem__(cls):
239
                return None
240
        with self.assertRaises(TypeError):
241
            C_too_few[int]
242
        class C_too_many:
243
            def __class_getitem__(cls, one, two):
244
                return None
245
        with self.assertRaises(TypeError):
246
            C_too_many[int]
247

248
    def test_class_getitem_errors_2(self):
249
        class C:
250
            def __class_getitem__(cls, item):
251
                return None
252
        with self.assertRaises(TypeError):
253
            C()[int]
254
        class E: ...
255
        e = E()
256
        e.__class_getitem__ = lambda cls, item: 'This will not work'
257
        with self.assertRaises(TypeError):
258
            e[int]
259
        class C_not_callable:
260
            __class_getitem__ = "Surprise!"
261
        with self.assertRaises(TypeError):
262
            C_not_callable[int]
263

264
    def test_class_getitem_metaclass(self):
265
        class Meta(type):
266
            def __class_getitem__(cls, item):
267
                return f'{cls.__name__}[{item.__name__}]'
268
        self.assertEqual(Meta[int], 'Meta[int]')
269

270
    def test_class_getitem_with_metaclass(self):
271
        class Meta(type): pass
272
        class C(metaclass=Meta):
273
            def __class_getitem__(cls, item):
274
                return f'{cls.__name__}[{item.__name__}]'
275
        self.assertEqual(C[int], 'C[int]')
276

277
    def test_class_getitem_metaclass_first(self):
278
        class Meta(type):
279
            def __getitem__(cls, item):
280
                return 'from metaclass'
281
        class C(metaclass=Meta):
282
            def __class_getitem__(cls, item):
283
                return 'from __class_getitem__'
284
        self.assertEqual(C[int], 'from metaclass')
285

286

287
if __name__ == '__main__':
288
    unittest.main()
289

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.