|
1 | 1 | """Unit tests for zero-argument super() & related machinery."""
|
2 | 2 |
|
3 | 3 | import unittest
|
| 4 | +from unittest.mock import patch |
| 5 | +from test import shadowed_super |
4 | 6 |
|
5 | 7 |
|
6 | 8 | class A:
|
@@ -283,17 +285,28 @@ def f(self):
|
283 | 285 | def test_obscure_super_errors(self):
|
284 | 286 | def f():
|
285 | 287 | super()
|
286 |
| - self.assertRaises(RuntimeError, f) |
| 288 | + with self.assertRaisesRegex(RuntimeError, r"no arguments"): |
| 289 | + f() |
| 290 | + |
| 291 | + class C: |
| 292 | + def f(): |
| 293 | + super() |
| 294 | + with self.assertRaisesRegex(RuntimeError, r"no arguments"): |
| 295 | + C.f() |
| 296 | + |
287 | 297 | def f(x):
|
288 | 298 | del x
|
289 | 299 | super()
|
290 |
| - self.assertRaises(RuntimeError, f, None) |
| 300 | + with self.assertRaisesRegex(RuntimeError, r"arg\[0\] deleted"): |
| 301 | + f(None) |
| 302 | + |
291 | 303 | class X:
|
292 | 304 | def f(x):
|
293 | 305 | nonlocal __class__
|
294 | 306 | del __class__
|
295 | 307 | super()
|
296 |
| - self.assertRaises(RuntimeError, X().f) |
| 308 | + with self.assertRaisesRegex(RuntimeError, r"empty __class__ cell"): |
| 309 | + X().f() |
297 | 310 |
|
298 | 311 | def test_cell_as_self(self):
|
299 | 312 | class X:
|
@@ -325,6 +338,78 @@ def test_super_argtype(self):
|
325 | 338 | with self.assertRaisesRegex(TypeError, "argument 1 must be a type"):
|
326 | 339 | super(1, int)
|
327 | 340 |
|
| 341 | + def test_shadowed_global(self): |
| 342 | + self.assertEqual(shadowed_super.C().method(), "truly super") |
| 343 | + |
| 344 | + def test_shadowed_local(self): |
| 345 | + class super: |
| 346 | + msg = "quite super" |
| 347 | + |
| 348 | + class C: |
| 349 | + def method(self): |
| 350 | + return super().msg |
| 351 | + |
| 352 | + self.assertEqual(C().method(), "quite super") |
| 353 | + |
| 354 | + def test_shadowed_dynamic(self): |
| 355 | + class MySuper: |
| 356 | + msg = "super super" |
| 357 | + |
| 358 | + class C: |
| 359 | + def method(self): |
| 360 | + return super().msg |
| 361 | + |
| 362 | + with patch("test.test_super.super", MySuper) as m: |
| 363 | + self.assertEqual(C().method(), "super super") |
| 364 | + |
| 365 | + def test_shadowed_dynamic_two_arg(self): |
| 366 | + call_args = [] |
| 367 | + class MySuper: |
| 368 | + def __init__(self, *args): |
| 369 | + call_args.append(args) |
| 370 | + msg = "super super" |
| 371 | + |
| 372 | + class C: |
| 373 | + def method(self): |
| 374 | + return super(1, 2).msg |
| 375 | + |
| 376 | + with patch("test.test_super.super", MySuper) as m: |
| 377 | + self.assertEqual(C().method(), "super super") |
| 378 | + self.assertEqual(call_args, [(1, 2)]) |
| 379 | + |
| 380 | + def test_attribute_error(self): |
| 381 | + class C: |
| 382 | + def method(self): |
| 383 | + return super().msg |
| 384 | + |
| 385 | + with self.assertRaisesRegex(AttributeError, "'super' object has no attribute 'msg'"): |
| 386 | + C().method() |
| 387 | + |
| 388 | + def test_bad_first_arg(self): |
| 389 | + class C: |
| 390 | + def method(self): |
| 391 | + return super(1, self).method() |
| 392 | + |
| 393 | + with self.assertRaisesRegex(TypeError, "argument 1 must be a type"): |
| 394 | + C().method() |
| 395 | + |
| 396 | + def test_super___class__(self): |
| 397 | + class C: |
| 398 | + def method(self): |
| 399 | + return super().__class__ |
| 400 | + |
| 401 | + self.assertEqual(C().method(), super) |
| 402 | + |
| 403 | + def test_super_subclass___class__(self): |
| 404 | + class mysuper(super): |
| 405 | + pass |
| 406 | + |
| 407 | + class C: |
| 408 | + def method(self): |
| 409 | + return mysuper(C, self).__class__ |
| 410 | + |
| 411 | + self.assertEqual(C().method(), mysuper) |
| 412 | + |
328 | 413 |
|
329 | 414 | if __name__ == "__main__":
|
330 | 415 | unittest.main()
|
0 commit comments