diff options
author | Nick Coghlan <ncoghlan@gmail.com> | 2016-09-11 04:45:49 (GMT) |
---|---|---|
committer | Nick Coghlan <ncoghlan@gmail.com> | 2016-09-11 04:45:49 (GMT) |
commit | 944368e1cc90a0bebaaf1a0a6f4346a81d8f46ad (patch) | |
tree | ea2c59fec386dfbe32c0f53ba8a85f75860e554d /Lib/test/test_super.py | |
parent | fc3f7d56773b3816eb0e8f4151239a0983aedb2c (diff) | |
download | cpython-944368e1cc90a0bebaaf1a0a6f4346a81d8f46ad.zip cpython-944368e1cc90a0bebaaf1a0a6f4346a81d8f46ad.tar.gz cpython-944368e1cc90a0bebaaf1a0a6f4346a81d8f46ad.tar.bz2 |
Issue #23722: Initialize __class__ from type.__new__()
The __class__ cell used by zero-argument super() is now initialized
from type.__new__ rather than __build_class__, so class methods
relying on that will now work correctly when called from metaclass
methods during class creation.
Patch by Martin Teichmann.
Diffstat (limited to 'Lib/test/test_super.py')
-rw-r--r-- | Lib/test/test_super.py | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/Lib/test/test_super.py b/Lib/test/test_super.py index b84863f..a7ceded 100644 --- a/Lib/test/test_super.py +++ b/Lib/test/test_super.py @@ -143,6 +143,87 @@ class TestSuper(unittest.TestCase): return __class__ self.assertIs(X.f(), X) + def test___class___new(self): + test_class = None + + class Meta(type): + def __new__(cls, name, bases, namespace): + nonlocal test_class + self = super().__new__(cls, name, bases, namespace) + test_class = self.f() + return self + + class A(metaclass=Meta): + @staticmethod + def f(): + return __class__ + + self.assertIs(test_class, A) + + def test___class___delayed(self): + test_namespace = None + + class Meta(type): + def __new__(cls, name, bases, namespace): + nonlocal test_namespace + test_namespace = namespace + return None + + class A(metaclass=Meta): + @staticmethod + def f(): + return __class__ + + self.assertIs(A, None) + + B = type("B", (), test_namespace) + self.assertIs(B.f(), B) + + def test___class___mro(self): + test_class = None + + class Meta(type): + def mro(self): + # self.f() doesn't work yet... + self.__dict__["f"]() + return super().mro() + + class A(metaclass=Meta): + def f(): + nonlocal test_class + test_class = __class__ + + self.assertIs(test_class, A) + + def test___classcell___deleted(self): + class Meta(type): + def __new__(cls, name, bases, namespace): + del namespace['__classcell__'] + return super().__new__(cls, name, bases, namespace) + + class A(metaclass=Meta): + @staticmethod + def f(): + __class__ + + with self.assertRaises(NameError): + A.f() + + def test___classcell___reset(self): + class Meta(type): + def __new__(cls, name, bases, namespace): + namespace['__classcell__'] = 0 + return super().__new__(cls, name, bases, namespace) + + class A(metaclass=Meta): + @staticmethod + def f(): + __class__ + + with self.assertRaises(NameError): + A.f() + self.assertEqual(A.__classcell__, 0) + def test_obscure_super_errors(self): def f(): super() |