-
Notifications
You must be signed in to change notification settings - Fork 294
/
Copy pathtest_super.py
359 lines (287 loc) · 9.67 KB
/
test_super.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
"""Unit tests for new super() implementation."""
from __future__ import absolute_import, division, unicode_literals
import sys
from future.tests.base import unittest, skip26, expectedFailurePY2
from future import utils
from future.builtins import super
class A(object):
def f(self):
return 'A'
@classmethod
def cm(cls):
return (cls, 'A')
class B(A):
def f(self):
return super().f() + 'B'
@classmethod
def cm(cls):
return (cls, super().cm(), 'B')
class C(A):
def f(self):
return super().f() + 'C'
@classmethod
def cm(cls):
return (cls, super().cm(), 'C')
class D(C, B):
def f(self):
return super().f() + 'D'
def cm(cls):
return (cls, super().cm(), 'D')
class E(D):
pass
class F(E):
f = E.f
class G(A):
pass
class TestSuper(unittest.TestCase):
def test_basics_working(self):
self.assertEqual(D().f(), 'ABCD')
def test_class_getattr_working(self):
self.assertEqual(D.f(D()), 'ABCD')
def test_subclass_no_override_working(self):
self.assertEqual(E().f(), 'ABCD')
self.assertEqual(E.f(E()), 'ABCD')
@expectedFailurePY2 # not working yet: infinite loop
def test_unbound_method_transfer_working(self):
self.assertEqual(F().f(), 'ABCD')
self.assertEqual(F.f(F()), 'ABCD')
def test_class_methods_still_working(self):
self.assertEqual(A.cm(), (A, 'A'))
self.assertEqual(A().cm(), (A, 'A'))
self.assertEqual(G.cm(), (G, 'A'))
self.assertEqual(G().cm(), (G, 'A'))
def test_super_in_class_methods_working(self):
d = D()
self.assertEqual(d.cm(), (d, (D, (D, (D, 'A'), 'B'), 'C'), 'D'))
e = E()
self.assertEqual(e.cm(), (e, (E, (E, (E, 'A'), 'B'), 'C'), 'D'))
def test_super_with_closure(self):
# Issue4360: super() did not work in a function that
# contains a closure
class E(A):
def f(self):
def nested():
self
return super().f() + 'E'
self.assertEqual(E().f(), 'AE')
# We declare this test invalid: __class__ should be a class.
# def test___class___set(self):
# # See issue #12370
# class X(A):
# def f(self):
# return super().f()
# __class__ = 413
# x = X()
# self.assertEqual(x.f(), 'A')
# self.assertEqual(x.__class__, 413)
@unittest.skipIf(utils.PY2, "no __class__ on Py2")
def test___class___instancemethod(self):
# See issue #14857
class X(object):
def f(self):
return __class__
self.assertIs(X().f(), X)
@unittest.skipIf(utils.PY2, "no __class__ on Py2")
def test___class___classmethod(self):
# See issue #14857
class X(object):
@classmethod
def f(cls):
return __class__
self.assertIs(X.f(), X)
@unittest.skipIf(utils.PY2, "no __class__ on Py2")
def test___class___staticmethod(self):
# See issue #14857
class X(object):
@staticmethod
def f():
return __class__
self.assertIs(X.f(), X)
def test_obscure_super_errors(self):
def f():
super()
self.assertRaises(RuntimeError, f)
def f(x):
del x
super()
self.assertRaises(RuntimeError, f, None)
# class X(object):
# def f(x):
# nonlocal __class__
# del __class__
# super()
# self.assertRaises(RuntimeError, X().f)
def test_cell_as_self(self):
class X(object):
def meth(self):
super()
def f():
k = X()
def g():
return k
return g
c = f().__closure__[0]
self.assertRaises(TypeError, X.meth, c)
def test_properties(self):
class Harmless(object):
bomb = ''
def walk(self):
return self.bomb
class Dangerous(Harmless):
@property
def bomb(self):
raise Exception("Kaboom")
def walk(self):
return super().walk()
class Elite(Dangerous):
bomb = 'Defused'
self.assertEqual(Elite().walk(), 'Defused')
def test_metaclass(self):
class Meta(type):
def __init__(cls, name, bases, clsdict):
super().__init__(name, bases, clsdict)
try:
class Base(object):
__metaclass__ = Meta
except Exception as e:
self.fail('raised %s with a custom metaclass'
% type(e).__name__)
class TestSuperFromTestDescrDotPy(unittest.TestCase):
"""
These are from Python 3.3.5/Lib/test/test_descr.py
"""
@skip26
def test_classmethods(self):
# Testing class methods...
class C(object):
def foo(*a): return a
goo = classmethod(foo)
c = C()
self.assertEqual(C.goo(1), (C, 1))
self.assertEqual(c.goo(1), (C, 1))
self.assertEqual(c.foo(1), (c, 1))
class D(C):
pass
d = D()
self.assertEqual(D.goo(1), (D, 1))
self.assertEqual(d.goo(1), (D, 1))
self.assertEqual(d.foo(1), (d, 1))
self.assertEqual(D.foo(d, 1), (d, 1))
# Test for a specific crash (SF bug 528132)
def f(cls, arg): return (cls, arg)
ff = classmethod(f)
self.assertEqual(ff.__get__(0, int)(42), (int, 42))
self.assertEqual(ff.__get__(0)(42), (int, 42))
# Test super() with classmethods (SF bug 535444)
self.assertEqual(C.goo.__self__, C)
self.assertEqual(D.goo.__self__, D)
self.assertEqual(super(D,D).goo.__self__, D)
self.assertEqual(super(D,d).goo.__self__, D)
self.assertEqual(super(D,D).goo(), (D,))
self.assertEqual(super(D,d).goo(), (D,))
# Verify that a non-callable will raise
meth = classmethod(1).__get__(1)
self.assertRaises(TypeError, meth)
# Verify that classmethod() doesn't allow keyword args
try:
classmethod(f, kw=1)
except TypeError:
pass
else:
self.fail("classmethod shouldn't accept keyword args")
# cm = classmethod(f)
# self.assertEqual(cm.__dict__, {})
# cm.x = 42
# self.assertEqual(cm.x, 42)
# self.assertEqual(cm.__dict__, {"x" : 42})
# del cm.x
# self.assertTrue(not hasattr(cm, "x"))
def test_supers(self):
# Testing super...
class A(object):
def meth(self, a):
return "A(%r)" % a
self.assertEqual(A().meth(1), "A(1)")
class B(A):
def __init__(self):
self.__super = super(B, self)
def meth(self, a):
return "B(%r)" % a + self.__super.meth(a)
self.assertEqual(B().meth(2), "B(2)A(2)")
class C(A):
def meth(self, a):
return "C(%r)" % a + self.__super.meth(a)
C._C__super = super(C)
self.assertEqual(C().meth(3), "C(3)A(3)")
class D(C, B):
def meth(self, a):
return "D(%r)" % a + super(D, self).meth(a)
self.assertEqual(D().meth(4), "D(4)C(4)B(4)A(4)")
# # Test for subclassing super
# class mysuper(super):
# def __init__(self, *args):
# return super(mysuper, self).__init__(*args)
# class E(D):
# def meth(self, a):
# return "E(%r)" % a + mysuper(E, self).meth(a)
# self.assertEqual(E().meth(5), "E(5)D(5)C(5)B(5)A(5)")
# class F(E):
# def meth(self, a):
# s = self.__super # == mysuper(F, self)
# return "F(%r)[%s]" % (a, s.__class__.__name__) + s.meth(a)
# F._F__super = mysuper(F)
# self.assertEqual(F().meth(6), "F(6)[mysuper]E(6)D(6)C(6)B(6)A(6)")
# Make sure certain errors are raised
try:
super(D, 42)
except TypeError:
pass
else:
self.fail("shouldn't allow super(D, 42)")
try:
super(D, C())
except TypeError:
pass
else:
self.fail("shouldn't allow super(D, C())")
try:
super(D).__get__(12)
except TypeError:
pass
else:
self.fail("shouldn't allow super(D).__get__(12)")
try:
super(D).__get__(C())
except TypeError:
pass
else:
self.fail("shouldn't allow super(D).__get__(C())")
# Make sure data descriptors can be overridden and accessed via super
# (new feature in Python 2.3)
class DDbase(object):
def getx(self): return 42
x = property(getx)
class DDsub(DDbase):
def getx(self): return "hello"
x = property(getx)
dd = DDsub()
self.assertEqual(dd.x, "hello")
self.assertEqual(super(DDsub, dd).x, 42)
# Ensure that super() lookup of descriptor from classmethod
# works (SF ID# 743627)
class Base(object):
aProp = property(lambda self: "foo")
class Sub(Base):
@classmethod
def test(klass):
return super(Sub,klass).aProp
self.assertEqual(Sub.test(), Base.aProp)
# Verify that super() doesn't allow keyword args
try:
super(Base, kw=1)
except TypeError:
pass
else:
self.assertEqual("super shouldn't accept keyword args")
if __name__ == "__main__":
unittest.main()