| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- import types
- import unittest
- class Test(unittest.TestCase):
- def test_init_subclass(self):
- class A:
- initialized = False
- def __init_subclass__(cls):
- super().__init_subclass__()
- cls.initialized = True
- class B(A):
- pass
- self.assertFalse(A.initialized)
- self.assertTrue(B.initialized)
- def test_init_subclass_dict(self):
- class A(dict):
- initialized = False
- def __init_subclass__(cls):
- super().__init_subclass__()
- cls.initialized = True
- class B(A):
- pass
- self.assertFalse(A.initialized)
- self.assertTrue(B.initialized)
- def test_init_subclass_kwargs(self):
- class A:
- def __init_subclass__(cls, **kwargs):
- cls.kwargs = kwargs
- class B(A, x=3):
- pass
- self.assertEqual(B.kwargs, dict(x=3))
- def test_init_subclass_error(self):
- class A:
- def __init_subclass__(cls):
- raise RuntimeError
- with self.assertRaises(RuntimeError):
- class B(A):
- pass
- def test_init_subclass_wrong(self):
- class A:
- def __init_subclass__(cls, whatever):
- pass
- with self.assertRaises(TypeError):
- class B(A):
- pass
- def test_init_subclass_skipped(self):
- class BaseWithInit:
- def __init_subclass__(cls, **kwargs):
- super().__init_subclass__(**kwargs)
- cls.initialized = cls
- class BaseWithoutInit(BaseWithInit):
- pass
- class A(BaseWithoutInit):
- pass
- self.assertIs(A.initialized, A)
- self.assertIs(BaseWithoutInit.initialized, BaseWithoutInit)
- def test_init_subclass_diamond(self):
- class Base:
- def __init_subclass__(cls, **kwargs):
- super().__init_subclass__(**kwargs)
- cls.calls = []
- class Left(Base):
- pass
- class Middle:
- def __init_subclass__(cls, middle, **kwargs):
- super().__init_subclass__(**kwargs)
- cls.calls += [middle]
- class Right(Base):
- def __init_subclass__(cls, right="right", **kwargs):
- super().__init_subclass__(**kwargs)
- cls.calls += [right]
- class A(Left, Middle, Right, middle="middle"):
- pass
- self.assertEqual(A.calls, ["right", "middle"])
- self.assertEqual(Left.calls, [])
- self.assertEqual(Right.calls, [])
- def test_set_name(self):
- class Descriptor:
- def __set_name__(self, owner, name):
- self.owner = owner
- self.name = name
- class A:
- d = Descriptor()
- self.assertEqual(A.d.name, "d")
- self.assertIs(A.d.owner, A)
- def test_set_name_metaclass(self):
- class Meta(type):
- def __new__(cls, name, bases, ns):
- ret = super().__new__(cls, name, bases, ns)
- self.assertEqual(ret.d.name, "d")
- self.assertIs(ret.d.owner, ret)
- return 0
- class Descriptor:
- def __set_name__(self, owner, name):
- self.owner = owner
- self.name = name
- class A(metaclass=Meta):
- d = Descriptor()
- self.assertEqual(A, 0)
- def test_set_name_error(self):
- class Descriptor:
- def __set_name__(self, owner, name):
- 1/0
- with self.assertRaises(RuntimeError) as cm:
- class NotGoingToWork:
- attr = Descriptor()
- exc = cm.exception
- self.assertRegex(str(exc), r'\bNotGoingToWork\b')
- self.assertRegex(str(exc), r'\battr\b')
- self.assertRegex(str(exc), r'\bDescriptor\b')
- self.assertIsInstance(exc.__cause__, ZeroDivisionError)
- def test_set_name_wrong(self):
- class Descriptor:
- def __set_name__(self):
- pass
- with self.assertRaises(RuntimeError) as cm:
- class NotGoingToWork:
- attr = Descriptor()
- exc = cm.exception
- self.assertRegex(str(exc), r'\bNotGoingToWork\b')
- self.assertRegex(str(exc), r'\battr\b')
- self.assertRegex(str(exc), r'\bDescriptor\b')
- self.assertIsInstance(exc.__cause__, TypeError)
- def test_set_name_lookup(self):
- resolved = []
- class NonDescriptor:
- def __getattr__(self, name):
- resolved.append(name)
- class A:
- d = NonDescriptor()
- self.assertNotIn('__set_name__', resolved,
- '__set_name__ is looked up in instance dict')
- def test_set_name_init_subclass(self):
- class Descriptor:
- def __set_name__(self, owner, name):
- self.owner = owner
- self.name = name
- class Meta(type):
- def __new__(cls, name, bases, ns):
- self = super().__new__(cls, name, bases, ns)
- self.meta_owner = self.owner
- self.meta_name = self.name
- return self
- class A:
- def __init_subclass__(cls):
- cls.owner = cls.d.owner
- cls.name = cls.d.name
- class B(A, metaclass=Meta):
- d = Descriptor()
- self.assertIs(B.owner, B)
- self.assertEqual(B.name, 'd')
- self.assertIs(B.meta_owner, B)
- self.assertEqual(B.name, 'd')
- def test_set_name_modifying_dict(self):
- notified = []
- class Descriptor:
- def __set_name__(self, owner, name):
- setattr(owner, name + 'x', None)
- notified.append(name)
- class A:
- a = Descriptor()
- b = Descriptor()
- c = Descriptor()
- d = Descriptor()
- e = Descriptor()
- self.assertCountEqual(notified, ['a', 'b', 'c', 'd', 'e'])
- def test_errors(self):
- class MyMeta(type):
- pass
- with self.assertRaises(TypeError):
- class MyClass(metaclass=MyMeta, otherarg=1):
- pass
- with self.assertRaises(TypeError):
- types.new_class("MyClass", (object,),
- dict(metaclass=MyMeta, otherarg=1))
- types.prepare_class("MyClass", (object,),
- dict(metaclass=MyMeta, otherarg=1))
- class MyMeta(type):
- def __init__(self, name, bases, namespace, otherarg):
- super().__init__(name, bases, namespace)
- with self.assertRaises(TypeError):
- class MyClass(metaclass=MyMeta, otherarg=1):
- pass
- class MyMeta(type):
- def __new__(cls, name, bases, namespace, otherarg):
- return super().__new__(cls, name, bases, namespace)
- def __init__(self, name, bases, namespace, otherarg):
- super().__init__(name, bases, namespace)
- self.otherarg = otherarg
- class MyClass(metaclass=MyMeta, otherarg=1):
- pass
- self.assertEqual(MyClass.otherarg, 1)
- def test_errors_changed_pep487(self):
- # These tests failed before Python 3.6, PEP 487
- class MyMeta(type):
- def __new__(cls, name, bases, namespace):
- return super().__new__(cls, name=name, bases=bases,
- dict=namespace)
- with self.assertRaises(TypeError):
- class MyClass(metaclass=MyMeta):
- pass
- class MyMeta(type):
- def __new__(cls, name, bases, namespace, otherarg):
- self = super().__new__(cls, name, bases, namespace)
- self.otherarg = otherarg
- return self
- class MyClass(metaclass=MyMeta, otherarg=1):
- pass
- self.assertEqual(MyClass.otherarg, 1)
- def test_type(self):
- t = type('NewClass', (object,), {})
- self.assertIsInstance(t, type)
- self.assertEqual(t.__name__, 'NewClass')
- with self.assertRaises(TypeError):
- type(name='NewClass', bases=(object,), dict={})
- if __name__ == "__main__":
- unittest.main()
|