13
class Test(unittest.TestCase):
14
if not hasattr(unittest.TestCase, 'assertRegex'):
15
def assertRegex(self, value, regex):
16
self.assertTrue(re.search(regex, str(value)),
17
"'%s' did not match '%s'" % (value, regex))
19
if not hasattr(unittest.TestCase, 'assertCountEqual'):
20
def assertCountEqual(self, first, second):
21
self.assertEqual(set(first), set(second))
22
self.assertEqual(len(first), len(second))
24
def test_init_subclass(self):
28
def __init_subclass__(cls):
29
super().__init_subclass__()
30
cls.initialized = True
35
self.assertFalse(A.initialized)
36
self.assertTrue(B.initialized)
38
def test_init_subclass_dict(self):
42
def __init_subclass__(cls):
43
super().__init_subclass__()
44
cls.initialized = True
49
self.assertFalse(A.initialized)
50
self.assertTrue(B.initialized)
52
def test_init_subclass_kwargs(self):
54
def __init_subclass__(cls, **kwargs):
60
self.assertEqual(B.kwargs, dict(x=3))
62
def test_init_subclass_error(self):
64
def __init_subclass__(cls):
67
with self.assertRaises(RuntimeError):
71
def test_init_subclass_wrong(self):
73
def __init_subclass__(cls, whatever):
76
with self.assertRaises(TypeError):
80
def test_init_subclass_skipped(self):
82
def __init_subclass__(cls, **kwargs):
83
super().__init_subclass__(**kwargs)
86
class BaseWithoutInit(BaseWithInit):
89
class A(BaseWithoutInit):
92
self.assertIs(A.initialized, A)
93
self.assertIs(BaseWithoutInit.initialized, BaseWithoutInit)
95
def test_init_subclass_diamond(self):
97
def __init_subclass__(cls, **kwargs):
98
super().__init_subclass__(**kwargs)
105
def __init_subclass__(cls, middle, **kwargs):
106
super().__init_subclass__(**kwargs)
107
cls.calls += [middle]
110
def __init_subclass__(cls, right="right", **kwargs):
111
super().__init_subclass__(**kwargs)
114
class A(Left, Middle, Right, middle="middle"):
117
self.assertEqual(A.calls, ["right", "middle"])
118
self.assertEqual(Left.calls, [])
119
self.assertEqual(Right.calls, [])
121
def test_set_name(self):
123
def __set_name__(self, owner, name):
130
self.assertEqual(A.d.name, "d")
131
self.assertIs(A.d.owner, A)
133
def test_set_name_metaclass(self):
135
def __new__(cls, name, bases, ns):
136
ret = super().__new__(cls, name, bases, ns)
137
self.assertEqual(ret.d.name, "d")
138
self.assertIs(ret.d.owner, ret)
142
def __set_name__(self, owner, name):
146
class A(metaclass=Meta):
148
self.assertEqual(A, 0)
150
def test_set_name_error(self):
152
def __set_name__(self, owner, name):
155
with self.assertRaises((RuntimeError, ZeroDivisionError)) as cm:
156
class NotGoingToWork:
159
if sys.version_info >= (3, 12):
160
notes = cm.exception.__notes__
161
self.assertRegex(str(notes), r'\bNotGoingToWork\b')
162
self.assertRegex(str(notes), r'\battr\b')
163
self.assertRegex(str(notes), r'\bDescriptor\b')
166
self.assertRegex(str(exc), r'\bNotGoingToWork\b')
167
self.assertRegex(str(exc), r'\battr\b')
168
self.assertRegex(str(exc), r'\bDescriptor\b')
169
self.assertIsInstance(exc.__cause__, ZeroDivisionError)
171
def test_set_name_wrong(self):
173
def __set_name__(self):
176
with self.assertRaises((RuntimeError, TypeError)) as cm:
177
class NotGoingToWork:
180
if sys.version_info >= (3, 12):
181
notes = cm.exception.__notes__
182
self.assertRegex(str(notes), r'\bNotGoingToWork\b')
183
self.assertRegex(str(notes), r'\battr\b')
184
self.assertRegex(str(notes), r'\bDescriptor\b')
187
self.assertRegex(str(exc), r'\bNotGoingToWork\b')
188
self.assertRegex(str(exc), r'\battr\b')
189
self.assertRegex(str(exc), r'\bDescriptor\b')
190
self.assertIsInstance(exc.__cause__, TypeError)
192
def test_set_name_lookup(self):
195
def __getattr__(self, name):
196
resolved.append(name)
201
self.assertNotIn('__set_name__', resolved,
202
'__set_name__ is looked up in instance dict')
204
def test_set_name_init_subclass(self):
206
def __set_name__(self, owner, name):
211
def __new__(cls, name, bases, ns):
212
self = super().__new__(cls, name, bases, ns)
213
self.meta_owner = self.owner
214
self.meta_name = self.name
218
def __init_subclass__(cls):
219
cls.owner = cls.d.owner
220
cls.name = cls.d.name
222
class B(A, metaclass=Meta):
225
self.assertIs(B.owner, B)
226
self.assertEqual(B.name, 'd')
227
self.assertIs(B.meta_owner, B)
228
self.assertEqual(B.name, 'd')
230
def test_set_name_modifying_dict(self):
233
def __set_name__(self, owner, name):
234
setattr(owner, name + 'x', None)
235
notified.append(name)
244
self.assertCountEqual(notified, ['a', 'b', 'c', 'd', 'e'])
246
def test_errors(self):
250
with self.assertRaises(TypeError):
251
class MyClass(metaclass=MyMeta, otherarg=1):
254
with self.assertRaises(TypeError):
255
types.new_class("MyClass", (object,),
256
dict(metaclass=MyMeta, otherarg=1))
257
types.prepare_class("MyClass", (object,),
258
dict(metaclass=MyMeta, otherarg=1))
261
def __init__(self, name, bases, namespace, otherarg):
262
super().__init__(name, bases, namespace)
264
with self.assertRaises(TypeError):
265
class MyClass(metaclass=MyMeta, otherarg=1):
269
def __new__(cls, name, bases, namespace, otherarg):
270
return super().__new__(cls, name, bases, namespace)
272
def __init__(self, name, bases, namespace, otherarg):
273
super().__init__(name, bases, namespace)
274
self.otherarg = otherarg
276
class MyClass(metaclass=MyMeta, otherarg=1):
279
self.assertEqual(MyClass.otherarg, 1)
281
def test_errors_changed_pep487(self):
284
def __new__(cls, name, bases, namespace):
285
return super().__new__(cls, name=name, bases=bases,
288
with self.assertRaises(TypeError):
289
class MyClass(metaclass=MyMeta):
293
def __new__(cls, name, bases, namespace, otherarg):
294
self = super().__new__(cls, name, bases, namespace)
295
self.otherarg = otherarg
298
class MyClass(metaclass=MyMeta, otherarg=1):
301
self.assertEqual(MyClass.otherarg, 1)
304
t = type('NewClass', (object,), {})
305
self.assertIsInstance(t, type)
306
self.assertEqual(t.__name__, 'NewClass')
308
with self.assertRaises(TypeError):
309
type(name='NewClass', bases=(object,), dict={})
312
if __name__ == "__main__":