def test_can_proxy_generic(self): """ Verifies that Generic Proxy wraps the original user defined generic and applies an enforcer to it """ T = TypeVar("T") K = TypeVar("K") V = TypeVar("V") class AG(Generic[T]): pass class BG(Generic[T, K, V]): pass AP = GenericProxy(AG) BP = GenericProxy(BG) self.assertIs(AP.__class__, AG.__class__) self.assertIs(BP.__class__, BG.__class__) self.assertIs(AP.__wrapped__, AG) self.assertIs(BP.__wrapped__, BG) self.assertTrue(AP.__enforcer__.generic) self.assertTrue(BP.__enforcer__.generic) self.assertFalse(AP.__enforcer__.bound) self.assertFalse(BP.__enforcer__.bound) self.assertFalse(hasattr(AG, "__enforcer__")) self.assertFalse(hasattr(BG, "__enforcer__"))
def test_instances_have_enforcer(self): """ Verifies that instances of generics wrapped with Generic Proxy have __enforcer__ object """ T = TypeVar("T") class AG(Generic[T]): pass AP = GenericProxy(AG) APT = AP[int] ap = AP() apt = APT() self.assertTrue(hasattr(ap, "__enforcer__")) self.assertTrue(hasattr(apt, "__enforcer__")) # Signature in generics should always point to the original unconstrained generic self.assertEqual(ap.__enforcer__.signature, AG) self.assertEqual(apt.__enforcer__.signature, AG) self.assertEqual(ap.__enforcer__.generic, AP.__enforcer__.generic) self.assertEqual(apt.__enforcer__.generic, APT.__enforcer__.generic) self.assertEqual(ap.__enforcer__.bound, AP.__enforcer__.bound) self.assertEqual(apt.__enforcer__.bound, APT.__enforcer__.bound) for hint_name, hint_value in apt.__enforcer__.hints.items(): self.assertEqual(hint_value, APT.__enforcer__.hints[hint_name]) self.assertEqual(len(apt.__enforcer__.hints), len(APT.__enforcer__.hints))
def test_typed_generic_is_proxied(self): """ Verifies that when Generic Proxy is constrained, the returned generic is also wrapped in a Generic Proxy And its origin property is pointing to a parent Generic Proxy (not an original user defined generic) """ types = (int, int, str) T = TypeVar("T") K = TypeVar("K") V = TypeVar("V") T_t, K_t, V_t = types class AG(Generic[T, K, V]): pass AP = GenericProxy(AG) AGT = AG[T_t, K_t, V_t] APT = AP[T_t, K_t, V_t] self.assertFalse(hasattr(AGT, "__enforcer__")) self.assertTrue(APT.__enforcer__.generic) self.assertTrue(APT.__enforcer__.bound) self.assertIs(APT.__origin__, AG) self.assertEqual(len(APT.__args__), len(types)) for i, arg in enumerate(APT.__args__): self.assertIs(arg, types[i])
def test_applying_to_another_proxy(self): """ Verifies that applying Generic Proxy to another Generic Proxy will result in a new generic proxy of wrapped object being returned """ T = TypeVar("T") class AG(Generic[T]): pass AGTA = GenericProxy(AG) AGTB = GenericProxy(AGTA) self.assertIsNot(AGTA, AGTB) self.assertIs(AGTA.__wrapped__, AG) self.assertIs(AGTB.__wrapped__, AG) self.assertIs(AGTA.__enforcer__.signature, AG) self.assertIs(AGTB.__enforcer__.signature, AG)
def test_cannot_apply_to_non_generics(self): """ Verifies that a Generic Proxy can only be applied to valid generics Otherwise, it should return a type error. """ T = TypeVar("T") class AG(Generic[T]): pass class B(AG): pass AP = GenericProxy(AG) APT = AP[int] ag = AG() agt = AG[int]() ap = AP() apt = APT() with self.assertRaises(TypeError): GenericProxy(ag) with self.assertRaises(TypeError): GenericProxy(agt) with self.assertRaises(TypeError): GenericProxy(ap) with self.assertRaises(TypeError): GenericProxy(apt) with self.assertRaises(TypeError): GenericProxy(B)
def test_can_init_proxied_generics(self): """ Verifies that all proxied generics can be instantiated """ T = TypeVar("T") class AG(Generic[T]): pass AP = GenericProxy(AG) APT = AP[int] ap = AP() apt = APT()
def test_generic_constraints_are_validated(self): """ Verifies that proxied generic constraints cannot contradict the TypeVar definition """ T = TypeVar("T", int, str) class AG(Generic[T]): pass AP = GenericProxy(AG) APT = AP[int] APT = AP[str] with self.assertRaises(TypeError): APT = AP[tuple]
def test_generic_type(self): """ Verifies that it can correctly compare generic types """ from enforce.enforcers import GenericProxy T = TypeVar('T') class A(Generic[T]): pass class B(A): pass C = GenericProxy(A) self.assertFalse(is_type_of_type(A, Generic)) self.assertFalse(is_type_of_type(Generic, A)) self.assertTrue(is_type_of_type(A, Generic, covariant=True)) self.assertFalse(is_type_of_type(Generic, A, covariant=True)) self.assertFalse(is_type_of_type(A, Generic, contravariant=True)) self.assertTrue(is_type_of_type(Generic, A, contravariant=True)) self.assertTrue( is_type_of_type(A, Generic, covariant=True, contravariant=True)) self.assertTrue( is_type_of_type(Generic, A, covariant=True, contravariant=True)) self.assertFalse(is_type_of_type(B, Generic)) self.assertFalse(is_type_of_type(Generic, B)) self.assertTrue(is_type_of_type(B, Generic, covariant=True)) self.assertFalse(is_type_of_type(Generic, B, covariant=True)) self.assertFalse(is_type_of_type(B, Generic, contravariant=True)) self.assertTrue(is_type_of_type(Generic, B, contravariant=True)) self.assertTrue( is_type_of_type(B, Generic, covariant=True, contravariant=True)) self.assertTrue( is_type_of_type(Generic, B, covariant=True, contravariant=True)) self.assertFalse(is_type_of_type(C, Generic)) self.assertFalse(is_type_of_type(Generic, C)) self.assertTrue(is_type_of_type(C, Generic, covariant=True)) self.assertFalse(is_type_of_type(Generic, C, covariant=True)) self.assertFalse(is_type_of_type(C, Generic, contravariant=True)) self.assertTrue(is_type_of_type(Generic, C, contravariant=True)) self.assertTrue( is_type_of_type(C, Generic, covariant=True, contravariant=True)) self.assertTrue( is_type_of_type(Generic, C, covariant=True, contravariant=True))