1 import types
2 import unittest
3
4
5 class ESC[4;38;5;81mTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
6 def test_init_subclass(self):
7 class ESC[4;38;5;81mA:
8 initialized = False
9
10 def __init_subclass__(cls):
11 super().__init_subclass__()
12 cls.initialized = True
13
14 class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
15 pass
16
17 self.assertFalse(A.initialized)
18 self.assertTrue(B.initialized)
19
20 def test_init_subclass_dict(self):
21 class ESC[4;38;5;81mA(ESC[4;38;5;149mdict):
22 initialized = False
23
24 def __init_subclass__(cls):
25 super().__init_subclass__()
26 cls.initialized = True
27
28 class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
29 pass
30
31 self.assertFalse(A.initialized)
32 self.assertTrue(B.initialized)
33
34 def test_init_subclass_kwargs(self):
35 class ESC[4;38;5;81mA:
36 def __init_subclass__(cls, **kwargs):
37 cls.kwargs = kwargs
38
39 class ESC[4;38;5;81mB(ESC[4;38;5;149mA, x=3):
40 pass
41
42 self.assertEqual(B.kwargs, dict(x=3))
43
44 def test_init_subclass_error(self):
45 class ESC[4;38;5;81mA:
46 def __init_subclass__(cls):
47 raise RuntimeError
48
49 with self.assertRaises(RuntimeError):
50 class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
51 pass
52
53 def test_init_subclass_wrong(self):
54 class ESC[4;38;5;81mA:
55 def __init_subclass__(cls, whatever):
56 pass
57
58 with self.assertRaises(TypeError):
59 class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
60 pass
61
62 def test_init_subclass_skipped(self):
63 class ESC[4;38;5;81mBaseWithInit:
64 def __init_subclass__(cls, **kwargs):
65 super().__init_subclass__(**kwargs)
66 cls.initialized = cls
67
68 class ESC[4;38;5;81mBaseWithoutInit(ESC[4;38;5;149mBaseWithInit):
69 pass
70
71 class ESC[4;38;5;81mA(ESC[4;38;5;149mBaseWithoutInit):
72 pass
73
74 self.assertIs(A.initialized, A)
75 self.assertIs(BaseWithoutInit.initialized, BaseWithoutInit)
76
77 def test_init_subclass_diamond(self):
78 class ESC[4;38;5;81mBase:
79 def __init_subclass__(cls, **kwargs):
80 super().__init_subclass__(**kwargs)
81 cls.calls = []
82
83 class ESC[4;38;5;81mLeft(ESC[4;38;5;149mBase):
84 pass
85
86 class ESC[4;38;5;81mMiddle:
87 def __init_subclass__(cls, middle, **kwargs):
88 super().__init_subclass__(**kwargs)
89 cls.calls += [middle]
90
91 class ESC[4;38;5;81mRight(ESC[4;38;5;149mBase):
92 def __init_subclass__(cls, right="right", **kwargs):
93 super().__init_subclass__(**kwargs)
94 cls.calls += [right]
95
96 class ESC[4;38;5;81mA(ESC[4;38;5;149mLeft, ESC[4;38;5;149mMiddle, ESC[4;38;5;149mRight, middle="middle"):
97 pass
98
99 self.assertEqual(A.calls, ["right", "middle"])
100 self.assertEqual(Left.calls, [])
101 self.assertEqual(Right.calls, [])
102
103 def test_set_name(self):
104 class ESC[4;38;5;81mDescriptor:
105 def __set_name__(self, owner, name):
106 self.owner = owner
107 self.name = name
108
109 class ESC[4;38;5;81mA:
110 d = Descriptor()
111
112 self.assertEqual(A.d.name, "d")
113 self.assertIs(A.d.owner, A)
114
115 def test_set_name_metaclass(self):
116 class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
117 def __new__(cls, name, bases, ns):
118 ret = super().__new__(cls, name, bases, ns)
119 self.assertEqual(ret.d.name, "d")
120 self.assertIs(ret.d.owner, ret)
121 return 0
122
123 class ESC[4;38;5;81mDescriptor:
124 def __set_name__(self, owner, name):
125 self.owner = owner
126 self.name = name
127
128 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mMeta):
129 d = Descriptor()
130 self.assertEqual(A, 0)
131
132 def test_set_name_error(self):
133 class ESC[4;38;5;81mDescriptor:
134 def __set_name__(self, owner, name):
135 1/0
136
137 with self.assertRaises(RuntimeError) as cm:
138 class ESC[4;38;5;81mNotGoingToWork:
139 attr = Descriptor()
140
141 exc = cm.exception
142 self.assertRegex(str(exc), r'\bNotGoingToWork\b')
143 self.assertRegex(str(exc), r'\battr\b')
144 self.assertRegex(str(exc), r'\bDescriptor\b')
145 self.assertIsInstance(exc.__cause__, ZeroDivisionError)
146
147 def test_set_name_wrong(self):
148 class ESC[4;38;5;81mDescriptor:
149 def __set_name__(self):
150 pass
151
152 with self.assertRaises(RuntimeError) as cm:
153 class ESC[4;38;5;81mNotGoingToWork:
154 attr = Descriptor()
155
156 exc = cm.exception
157 self.assertRegex(str(exc), r'\bNotGoingToWork\b')
158 self.assertRegex(str(exc), r'\battr\b')
159 self.assertRegex(str(exc), r'\bDescriptor\b')
160 self.assertIsInstance(exc.__cause__, TypeError)
161
162 def test_set_name_lookup(self):
163 resolved = []
164 class ESC[4;38;5;81mNonDescriptor:
165 def __getattr__(self, name):
166 resolved.append(name)
167
168 class ESC[4;38;5;81mA:
169 d = NonDescriptor()
170
171 self.assertNotIn('__set_name__', resolved,
172 '__set_name__ is looked up in instance dict')
173
174 def test_set_name_init_subclass(self):
175 class ESC[4;38;5;81mDescriptor:
176 def __set_name__(self, owner, name):
177 self.owner = owner
178 self.name = name
179
180 class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
181 def __new__(cls, name, bases, ns):
182 self = super().__new__(cls, name, bases, ns)
183 self.meta_owner = self.owner
184 self.meta_name = self.name
185 return self
186
187 class ESC[4;38;5;81mA:
188 def __init_subclass__(cls):
189 cls.owner = cls.d.owner
190 cls.name = cls.d.name
191
192 class ESC[4;38;5;81mB(ESC[4;38;5;149mA, metaclass=ESC[4;38;5;149mMeta):
193 d = Descriptor()
194
195 self.assertIs(B.owner, B)
196 self.assertEqual(B.name, 'd')
197 self.assertIs(B.meta_owner, B)
198 self.assertEqual(B.name, 'd')
199
200 def test_set_name_modifying_dict(self):
201 notified = []
202 class ESC[4;38;5;81mDescriptor:
203 def __set_name__(self, owner, name):
204 setattr(owner, name + 'x', None)
205 notified.append(name)
206
207 class ESC[4;38;5;81mA:
208 a = Descriptor()
209 b = Descriptor()
210 c = Descriptor()
211 d = Descriptor()
212 e = Descriptor()
213
214 self.assertCountEqual(notified, ['a', 'b', 'c', 'd', 'e'])
215
216 def test_errors(self):
217 class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
218 pass
219
220 with self.assertRaises(TypeError):
221 class ESC[4;38;5;81mMyClass(metaclass=ESC[4;38;5;149mMyMeta, otherarg=1):
222 pass
223
224 with self.assertRaises(TypeError):
225 types.new_class("MyClass", (object,),
226 dict(metaclass=MyMeta, otherarg=1))
227 types.prepare_class("MyClass", (object,),
228 dict(metaclass=MyMeta, otherarg=1))
229
230 class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
231 def __init__(self, name, bases, namespace, otherarg):
232 super().__init__(name, bases, namespace)
233
234 with self.assertRaises(TypeError):
235 class ESC[4;38;5;81mMyClass2(metaclass=ESC[4;38;5;149mMyMeta, otherarg=1):
236 pass
237
238 class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
239 def __new__(cls, name, bases, namespace, otherarg):
240 return super().__new__(cls, name, bases, namespace)
241
242 def __init__(self, name, bases, namespace, otherarg):
243 super().__init__(name, bases, namespace)
244 self.otherarg = otherarg
245
246 class ESC[4;38;5;81mMyClass3(metaclass=ESC[4;38;5;149mMyMeta, otherarg=1):
247 pass
248
249 self.assertEqual(MyClass3.otherarg, 1)
250
251 def test_errors_changed_pep487(self):
252 # These tests failed before Python 3.6, PEP 487
253 class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
254 def __new__(cls, name, bases, namespace):
255 return super().__new__(cls, name=name, bases=bases,
256 dict=namespace)
257
258 with self.assertRaises(TypeError):
259 class ESC[4;38;5;81mMyClass(metaclass=ESC[4;38;5;149mMyMeta):
260 pass
261
262 class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
263 def __new__(cls, name, bases, namespace, otherarg):
264 self = super().__new__(cls, name, bases, namespace)
265 self.otherarg = otherarg
266 return self
267
268 class ESC[4;38;5;81mMyClass2(metaclass=ESC[4;38;5;149mMyMeta, otherarg=1):
269 pass
270
271 self.assertEqual(MyClass2.otherarg, 1)
272
273 def test_type(self):
274 t = type('NewClass', (object,), {})
275 self.assertIsInstance(t, type)
276 self.assertEqual(t.__name__, 'NewClass')
277
278 with self.assertRaises(TypeError):
279 type(name='NewClass', bases=(object,), dict={})
280
281
282 if __name__ == "__main__":
283 unittest.main()