def test_union_protocols(self): class U1: @untypy.patch def meth(self) -> str: return "s" class U2: @untypy.patch def meth(self) -> int: return 42 @untypy.patch def meth2(self) -> int: return 42 # when wrapping order matters UnionFactory() \ .create_from(Union[U1, U2], DummyDefaultCreationContext()) \ .check_and_wrap(U1(), DummyExecutionContext()) \ .meth() UnionFactory() \ .create_from(Union[U1, U2], DummyDefaultCreationContext()) \ .check_and_wrap(U2(), DummyExecutionContext()) \ .meth() UnionFactory() \ .create_from(Union[U2, U1], DummyDefaultCreationContext()) \ .check_and_wrap(U1(), DummyExecutionContext()) \ .meth() UnionFactory() \ .create_from(Union[U2, U1], DummyDefaultCreationContext()) \ .check_and_wrap(U2(), DummyExecutionContext()) \ .meth()
def setUp(self) -> None: self.sig_b = "B" self.ProtoReturnB = ProtoReturnB self.ProtoReceiveB = ProtoReceiveB self.ProtoReturnBName = "ProtoReturnB" self.ProtoReceiveBName = "ProtoReceiveB" self.checker_return = ProtocolFactory().create_from(ProtoReturnB, DummyDefaultCreationContext()) self.checker_arg = ProtocolFactory().create_from(ProtoReceiveB, DummyDefaultCreationContext())
def test_not_allowing_multiple_callables(self): with self.assertRaises(UntypyAttributeError): checker = UnionFactory().create_from(Union[int, str, Callable[[int], str], Callable[[str], str]], DummyDefaultCreationContext()) with self.assertRaises(UntypyAttributeError): checker = UnionFactory().create_from(Union[int, Callable[[int], str], Union[Callable[[str], str], list[int]]], DummyDefaultCreationContext())
def test_wrap(self): checker = UnionFactory().create_from(Union[int, str], DummyDefaultCreationContext()) res = checker.check_and_wrap(1, DummyExecutionContext()) self.assertEqual(1, res) res = checker.check_and_wrap("2", DummyExecutionContext()) self.assertEqual("2", res)
def setUp(self) -> None: self.checker = CallableFactory().create_from( Callable[[int, int], str], DummyDefaultCreationContext()) self.fn1 = self.checker.check_and_wrap(lambda x, y: str(x // y), DummyExecutionContext()) self.fn2 = self.checker.check_and_wrap(lambda x, y: x // y, DummyExecutionContext())
def test_wrap(self): checker = OptionalFactory().create_from(Optional[int], DummyDefaultCreationContext()) res = checker.check_and_wrap(1, DummyExecutionContext()) self.assertEqual(1, res) res = checker.check_and_wrap(None, DummyExecutionContext()) self.assertEqual(None, res)
def test_wrap_inheritance(self): checker = SimpleFactory().create_from(SomeParent, DummyDefaultCreationContext()) res = checker.check_and_wrap(ChildOfSomeParent(), DummyExecutionContext()) with self.assertRaises(UntypyTypeError): res.meth()
def test_untyped_match(self): checker = ProtocolFactory().create_from(UntypedProtocol, DummyDefaultCreationContext()) class U1: @untypy.patch def meth(self, a, b): # matches return 42 self.assertEqual(checker.check_and_wrap(U1(), DummyExecutionContext()).meth("a", "b"), 42)
def test_unions_simple_types_negative(self): class U3: def meth(self) -> None: pass class U4: def meth(self) -> None: pass def somethingelse(self) -> None: pass # this should also be fine. A and B don't have any signatures, # so protocol like wrapping does not apply UnionFactory().create_from(Union[A, B], DummyDefaultCreationContext()) # this must be fine: Names of Signatures differ. UnionFactory().create_from(Union[U3, U4], DummyDefaultCreationContext())
def check(self, f): l = [1, 4, 2, 1] refRes = f(l.copy()) checker = ListFactory().create_from(list[int], DummyDefaultCreationContext()) wrapped = checker.check_and_wrap(l, DummyExecutionContext()) res = f(wrapped) self.assertEqual(l, wrapped) self.assertEqual(refRes, res)
def check21(self, f): l1 = [1, 4, 2, 1] refRes11 = f(l1.copy(), l1.copy()) checker = ListFactory().create_from(list[int], DummyDefaultCreationContext()) wrapped1 = checker.check_and_wrap(l1, DummyExecutionContext()) res11 = f(wrapped1, wrapped1) self.assertEqual(l1, wrapped1) self.assertEqual(refRes11, res11)
def test_untyped_no_match(self): checker = ProtocolFactory().create_from(UntypedProtocol, DummyDefaultCreationContext()) class U0: @untypy.patch def notmeth(self, a, b): return 42 with self.assertRaises(UntypyTypeError) as cm: checker.check_and_wrap(U0(), DummyExecutionContext()) self.assertEqual(cm.exception.expected, "UntypedProtocol")
def test_untyped_nomatch_signature(self): checker = ProtocolFactory().create_from(UntypedProtocol, DummyDefaultCreationContext()) class U2: @untypy.patch def meth(self, a): # does not match pass with self.assertRaises(UntypyTypeError) as cm: checker.check_and_wrap(U2(), DummyExecutionContext()).meth("a", 42) self.assertEqual(cm.exception.expected, "UntypedProtocol")
def test_wrap(self): checker = SimpleFactory().create_from(A, DummyDefaultCreationContext()) a = A() child_a = ChildOfA() res = checker.check_and_wrap(a, DummyExecutionContext()) self.assertIs(a, res) res = checker.check_and_wrap(child_a, DummyExecutionContext()) self.assertIsNot(child_a, res) # Wrapped with AWrapper
def setUp(self) -> None: self.checker = ListFactory() \ .create_from(list[int], DummyDefaultCreationContext()) self.normal_list = [0, 1, 2, 3] self.wrapped_list = self.checker \ .check_and_wrap(self.normal_list, DummyExecutionContext()) self.faulty_normal_list = [0, 1, "2", 3] self.faulty_wrapped_list = self.checker \ .check_and_wrap(self.faulty_normal_list, DummyExecutionContext())
def setUp(self) -> None: T = TypeVar("T") class ProtoReturnGeneric(Protocol[T]): @untypy.patch def meth(self) -> T: raise NotImplementedError class ProtoReceiveGeneric(Protocol[T]): @untypy.patch def meth(self, b: T) -> None: raise NotImplementedError self.sig_b = "~T=B" self.ProtoReturnB = ProtoReturnGeneric self.ProtoReceiveB = ProtoReceiveGeneric self.ProtoReturnBName = "ProtoReturnGeneric[~T=B]" self.ProtoReceiveBName = "ProtoReceiveGeneric(Protocol)" self.checker_return = ProtocolFactory().create_from(ProtoReturnGeneric[B], DummyDefaultCreationContext()) self.checker_arg = ProtocolFactory().create_from(ProtoReceiveGeneric[B], DummyDefaultCreationContext())
def test_wrap_negative(self): checker = UnionFactory().create_from(Union[int, str], DummyDefaultCreationContext()) with self.assertRaises(UntypyTypeError) as cm: res = checker.check_and_wrap(23.5, DummyExecutionContext()) (t, i) = cm.exception.next_type_and_indicator() i = i.rstrip() self.assertEqual(t, "Union[int, str]") self.assertEqual(i, "^^^^^^^^^^^^^^^") # This DummyExecutionContext is responsable self.assertEqual(cm.exception.last_responsable().file, "dummy")
def test_unions_simple_types_negative(self): class U1: def meth(self) -> None: pass class U2: def meth(self) -> None: pass with self.assertRaises(UntypyAttributeError): # Should fail because both have the same methods # Wrapping cannot distinguish UnionFactory().create_from(Union[U1, U2], DummyDefaultCreationContext())
def test_protocol_type_repr(self): T = TypeVar("T") # There was a bug, causing T to be listet multiple Times. @untypy.patch class Proto(Generic[T]): @untypy.patch def do_it(self, a: T, b: T) -> None: return fac = GenericFactory().create_from(Proto[int], DummyDefaultCreationContext()) with self.assertRaises(UntypyTypeError) as cm: fac.check_and_wrap(42, DummyExecutionContext()) self.assertEqual(cm.exception.expected, "Proto[~T=int]")
def test_untyped_narrow_signature(self): checker = ProtocolFactory().create_from(UntypedProtocol, DummyDefaultCreationContext()) class U3: @untypy.patch def meth(self, a : int, b : int) -> int: # matches, but to specific return a + b wrapped = checker.check_and_wrap(U3(), DummyExecutionContext()) self.assertEqual(wrapped.meth(10, 20), 30) with self.assertRaises(UntypyTypeError) as cm: wrapped.meth("a", 20) self.assertEqual(cm.exception.previous_chain.expected, "UntypedProtocol")
def test_negative_delayed(self): checker = TupleFactory().create_from(tuple[int, DummyDelayedType], DummyDefaultCreationContext()) res = checker.check_and_wrap((1, 2), DummyExecutionContext()) with self.assertRaises(UntypyTypeError) as cm: res[1].use() (t, i) = cm.exception.next_type_and_indicator() i = i.rstrip() self.assertEqual(t, "Tuple[int, DummyDelayedType]") self.assertEqual(i, " ^^^^^^^^^^^^^^^^") # This DummyExecutionContext is responsable self.assertEqual(cm.exception.last_responsable().file, "dummy")
def test_error_delayed(self): self.checker = CallableFactory().create_from( Callable[[int, int], DummyDelayedType], DummyDefaultCreationContext()) fn = self.checker.check_and_wrap(lambda x, y: x // y, DummyExecutionContext()) res = fn(1, 2) with self.assertRaises(UntypyTypeError) as cm: res.use() (t, i) = cm.exception.next_type_and_indicator() i = i.rstrip() self.assertEqual(t, "Callable[[int, int], DummyDelayedType]") self.assertEqual(i, " ^^^^^^^^^^^^^^^^") self.assertEqual(cm.exception.last_responsable().file, "dummy")
def test_error_delayed(self): checker = ListFactory() \ .create_from(list[DummyDelayedType], DummyDefaultCreationContext()) lst = checker \ .check_and_wrap([1], DummyExecutionContext()) res = lst[0] with self.assertRaises(UntypyTypeError) as cm: res.use() (t, i) = cm.exception.next_type_and_indicator() i = i.rstrip() self.assertEqual(t, "list[DummyDelayedType]") self.assertEqual(i, " ^^^^^^^^^^^^^^^^") self.assertEqual(cm.exception.last_responsable().file, "dummy")
def setUp(self) -> None: self.checker = LiteralFactory().create_from( Literal[1, 2, "3"], DummyDefaultCreationContext())
def create_checker(annotation): return GeneratorFactory().create_from(annotation, DummyDefaultCreationContext())
def test_wrap_of_none_type(self): checker = NoneFactory().create_from(type(None), DummyDefaultCreationContext()) res = checker.check_and_wrap(None, DummyExecutionContext()) self.assertEqual(None, res)
def test_wrap_upper_case(self): checker = TupleFactory().create_from(Tuple[int, str], DummyDefaultCreationContext()) res = checker.check_and_wrap((1, "2"), DummyExecutionContext()) self.assertEqual((1, "2"), res)