blob: ea6de757c6135480ba8b665914fae7723aed1daa [file] [log] [blame]
Nick Coghland78448e2016-07-30 16:26:03 +10001import sys
2import types
Berker Peksag01d17192016-07-30 14:06:15 +03003import unittest
Nick Coghland78448e2016-07-30 16:26:03 +10004
5
Berker Peksag01d17192016-07-30 14:06:15 +03006class Test(unittest.TestCase):
Nick Coghland78448e2016-07-30 16:26:03 +10007 def test_init_subclass(self):
Berker Peksag01d17192016-07-30 14:06:15 +03008 class A:
Nick Coghland78448e2016-07-30 16:26:03 +10009 initialized = False
10
11 def __init_subclass__(cls):
12 super().__init_subclass__()
13 cls.initialized = True
14
15 class B(A):
16 pass
17
18 self.assertFalse(A.initialized)
19 self.assertTrue(B.initialized)
20
21 def test_init_subclass_dict(self):
Berker Peksag01d17192016-07-30 14:06:15 +030022 class A(dict):
Nick Coghland78448e2016-07-30 16:26:03 +100023 initialized = False
24
25 def __init_subclass__(cls):
26 super().__init_subclass__()
27 cls.initialized = True
28
29 class B(A):
30 pass
31
32 self.assertFalse(A.initialized)
33 self.assertTrue(B.initialized)
34
35 def test_init_subclass_kwargs(self):
Berker Peksag01d17192016-07-30 14:06:15 +030036 class A:
Nick Coghland78448e2016-07-30 16:26:03 +100037 def __init_subclass__(cls, **kwargs):
38 cls.kwargs = kwargs
39
40 class B(A, x=3):
41 pass
42
43 self.assertEqual(B.kwargs, dict(x=3))
44
45 def test_init_subclass_error(self):
Berker Peksag01d17192016-07-30 14:06:15 +030046 class A:
Nick Coghland78448e2016-07-30 16:26:03 +100047 def __init_subclass__(cls):
48 raise RuntimeError
49
50 with self.assertRaises(RuntimeError):
51 class B(A):
52 pass
53
54 def test_init_subclass_wrong(self):
Berker Peksag01d17192016-07-30 14:06:15 +030055 class A:
Nick Coghland78448e2016-07-30 16:26:03 +100056 def __init_subclass__(cls, whatever):
57 pass
58
59 with self.assertRaises(TypeError):
60 class B(A):
61 pass
62
63 def test_init_subclass_skipped(self):
Berker Peksag01d17192016-07-30 14:06:15 +030064 class BaseWithInit:
Nick Coghland78448e2016-07-30 16:26:03 +100065 def __init_subclass__(cls, **kwargs):
66 super().__init_subclass__(**kwargs)
67 cls.initialized = cls
68
69 class BaseWithoutInit(BaseWithInit):
70 pass
71
72 class A(BaseWithoutInit):
73 pass
74
75 self.assertIs(A.initialized, A)
76 self.assertIs(BaseWithoutInit.initialized, BaseWithoutInit)
77
78 def test_init_subclass_diamond(self):
Berker Peksag01d17192016-07-30 14:06:15 +030079 class Base:
Nick Coghland78448e2016-07-30 16:26:03 +100080 def __init_subclass__(cls, **kwargs):
81 super().__init_subclass__(**kwargs)
82 cls.calls = []
83
84 class Left(Base):
85 pass
86
Berker Peksag01d17192016-07-30 14:06:15 +030087 class Middle:
Nick Coghland78448e2016-07-30 16:26:03 +100088 def __init_subclass__(cls, middle, **kwargs):
89 super().__init_subclass__(**kwargs)
90 cls.calls += [middle]
91
92 class Right(Base):
93 def __init_subclass__(cls, right="right", **kwargs):
94 super().__init_subclass__(**kwargs)
95 cls.calls += [right]
96
97 class A(Left, Middle, Right, middle="middle"):
98 pass
99
100 self.assertEqual(A.calls, ["right", "middle"])
101 self.assertEqual(Left.calls, [])
102 self.assertEqual(Right.calls, [])
103
104 def test_set_name(self):
105 class Descriptor:
106 def __set_name__(self, owner, name):
107 self.owner = owner
108 self.name = name
109
Berker Peksag01d17192016-07-30 14:06:15 +0300110 class A:
Nick Coghland78448e2016-07-30 16:26:03 +1000111 d = Descriptor()
112
113 self.assertEqual(A.d.name, "d")
114 self.assertIs(A.d.owner, A)
115
116 def test_set_name_metaclass(self):
117 class Meta(type):
118 def __new__(cls, name, bases, ns):
119 ret = super().__new__(cls, name, bases, ns)
120 self.assertEqual(ret.d.name, "d")
121 self.assertIs(ret.d.owner, ret)
122 return 0
123
Berker Peksag01d17192016-07-30 14:06:15 +0300124 class Descriptor:
Nick Coghland78448e2016-07-30 16:26:03 +1000125 def __set_name__(self, owner, name):
126 self.owner = owner
127 self.name = name
128
Berker Peksag01d17192016-07-30 14:06:15 +0300129 class A(metaclass=Meta):
Nick Coghland78448e2016-07-30 16:26:03 +1000130 d = Descriptor()
131 self.assertEqual(A, 0)
132
133 def test_set_name_error(self):
134 class Descriptor:
135 def __set_name__(self, owner, name):
136 raise RuntimeError
137
138 with self.assertRaises(RuntimeError):
Berker Peksag01d17192016-07-30 14:06:15 +0300139 class A:
Nick Coghland78448e2016-07-30 16:26:03 +1000140 d = Descriptor()
141
142 def test_set_name_wrong(self):
143 class Descriptor:
144 def __set_name__(self):
145 pass
146
147 with self.assertRaises(TypeError):
Berker Peksag01d17192016-07-30 14:06:15 +0300148 class A:
Nick Coghland78448e2016-07-30 16:26:03 +1000149 d = Descriptor()
150
151 def test_set_name_init_subclass(self):
152 class Descriptor:
153 def __set_name__(self, owner, name):
154 self.owner = owner
155 self.name = name
156
157 class Meta(type):
158 def __new__(cls, name, bases, ns):
159 self = super().__new__(cls, name, bases, ns)
160 self.meta_owner = self.owner
161 self.meta_name = self.name
162 return self
163
Berker Peksag01d17192016-07-30 14:06:15 +0300164 class A:
Nick Coghland78448e2016-07-30 16:26:03 +1000165 def __init_subclass__(cls):
166 cls.owner = cls.d.owner
167 cls.name = cls.d.name
168
169 class B(A, metaclass=Meta):
170 d = Descriptor()
171
172 self.assertIs(B.owner, B)
173 self.assertEqual(B.name, 'd')
174 self.assertIs(B.meta_owner, B)
175 self.assertEqual(B.name, 'd')
176
177 def test_errors(self):
178 class MyMeta(type):
179 pass
180
181 with self.assertRaises(TypeError):
Berker Peksag01d17192016-07-30 14:06:15 +0300182 class MyClass(metaclass=MyMeta, otherarg=1):
Nick Coghland78448e2016-07-30 16:26:03 +1000183 pass
184
185 with self.assertRaises(TypeError):
186 types.new_class("MyClass", (object,),
187 dict(metaclass=MyMeta, otherarg=1))
188 types.prepare_class("MyClass", (object,),
189 dict(metaclass=MyMeta, otherarg=1))
190
191 class MyMeta(type):
192 def __init__(self, name, bases, namespace, otherarg):
193 super().__init__(name, bases, namespace)
194
195 with self.assertRaises(TypeError):
Berker Peksag01d17192016-07-30 14:06:15 +0300196 class MyClass(metaclass=MyMeta, otherarg=1):
Nick Coghland78448e2016-07-30 16:26:03 +1000197 pass
198
199 class MyMeta(type):
200 def __new__(cls, name, bases, namespace, otherarg):
201 return super().__new__(cls, name, bases, namespace)
202
203 def __init__(self, name, bases, namespace, otherarg):
204 super().__init__(name, bases, namespace)
205 self.otherarg = otherarg
206
Berker Peksag01d17192016-07-30 14:06:15 +0300207 class MyClass(metaclass=MyMeta, otherarg=1):
Nick Coghland78448e2016-07-30 16:26:03 +1000208 pass
209
210 self.assertEqual(MyClass.otherarg, 1)
211
212 def test_errors_changed_pep487(self):
213 # These tests failed before Python 3.6, PEP 487
214 class MyMeta(type):
215 def __new__(cls, name, bases, namespace):
216 return super().__new__(cls, name=name, bases=bases,
217 dict=namespace)
218
219 with self.assertRaises(TypeError):
Berker Peksag01d17192016-07-30 14:06:15 +0300220 class MyClass(metaclass=MyMeta):
Nick Coghland78448e2016-07-30 16:26:03 +1000221 pass
222
223 class MyMeta(type):
224 def __new__(cls, name, bases, namespace, otherarg):
225 self = super().__new__(cls, name, bases, namespace)
226 self.otherarg = otherarg
227 return self
228
Berker Peksag01d17192016-07-30 14:06:15 +0300229 class MyClass(metaclass=MyMeta, otherarg=1):
Nick Coghland78448e2016-07-30 16:26:03 +1000230 pass
231
232 self.assertEqual(MyClass.otherarg, 1)
233
234 def test_type(self):
235 t = type('NewClass', (object,), {})
236 self.assertIsInstance(t, type)
237 self.assertEqual(t.__name__, 'NewClass')
238
239 with self.assertRaises(TypeError):
240 type(name='NewClass', bases=(object,), dict={})
241
242
243if __name__ == "__main__":
Berker Peksag01d17192016-07-30 14:06:15 +0300244 unittest.main()