Example #1
0
    def test_no_type_check(self):
        """
        Verifies that no_type_check is respected
        """

        def get_sample_func():
            def sample(data: int):
                pass

            return sample

        sample_d1 = typing.no_type_check(runtime_validation(get_sample_func()))
        sample_d2 = runtime_validation(typing.no_type_check(get_sample_func()))

        sample_d3 = runtime_validation(get_sample_func())

        sample_d4 = typing.no_type_check_decorator(
            runtime_validation(get_sample_func())
        )
        sample_d5 = runtime_validation(
            typing.no_type_check_decorator(get_sample_func())
        )

        get_sample_func()("str")
        sample_d1("str")
        sample_d2("str")
        with self.assertRaises(RuntimeTypeError):
            sample_d3("str")
Example #2
0
    def test_named_tuple(self):
        from collections import namedtuple

        MyNamedTuple = typing.NamedTuple("MyNamedTuple", [("my_int", int)])

        t = MyNamedTuple(5)
        t1 = namedtuple("MyNamedTuple", "my_int")(5)
        t2 = namedtuple("MyNamedTuple", "my_int")("string")
        t3 = runtime_validation(MyNamedTuple)(5)
        t4 = (5,)
        t5 = "5"

        @runtime_validation
        def sample(data: MyNamedTuple) -> MyNamedTuple:
            return data

        # invariant cases
        sample(t)
        with self.assertRaises(RuntimeTypeError):
            sample(t1)
        with self.assertRaises(RuntimeTypeError):
            sample(t2)
        sample(t3)
        with self.assertRaises(RuntimeTypeError):
            sample(t4)
        with self.assertRaises(RuntimeTypeError):
            sample(t5)

        # Covariant case
        config({"mode": "covariant"})
Example #3
0
    def get_type_var_func(self, configurable=False, type_var=None):
        if type_var is None:
            A = typing.TypeVar('A')
        else:
            A = type_var

        def type_var_func(data: A) -> A:
            return data

        def configurable_type_var_func(data: typing.Any, type_option: A) -> A:
            return data

        if configurable:
            return runtime_validation(configurable_type_var_func)
        else:
            return runtime_validation(type_var_func)
Example #4
0
    def get_type_var_func(self, configurable=False, type_var=None):
        if type_var is None:
            A = typing.TypeVar("A")
        else:
            A = type_var

        def type_var_func(data: A) -> A:
            return data

        def configurable_type_var_func(data: typing.Any, type_option: A) -> A:
            return data

        if configurable:
            return runtime_validation(configurable_type_var_func)
        else:
            return runtime_validation(type_var_func)
Example #5
0
    def test_named_tuple(self):
        from collections import namedtuple

        MyNamedTuple = typing.NamedTuple('MyNamedTuple', [('my_int', int)])

        t = MyNamedTuple(5)
        t1 = namedtuple('MyNamedTuple', 'my_int')(5)
        t2 = namedtuple('MyNamedTuple', 'my_int')('string')
        t3 = runtime_validation(MyNamedTuple)(5)
        t4 = (5, )
        t5 = '5'

        @runtime_validation
        def sample(data: MyNamedTuple) -> MyNamedTuple:
            return data

        # invariant cases
        sample(t)
        with self.assertRaises(RuntimeTypeError):
            sample(t1)
        with self.assertRaises(RuntimeTypeError):
            sample(t2)
        sample(t3)
        with self.assertRaises(RuntimeTypeError):
            sample(t4)
        with self.assertRaises(RuntimeTypeError):
            sample(t5)

        # Covariant case
        config({'mode': 'covariant'})
Example #6
0
    def test_named_tuple(self):
        from collections import namedtuple

        MyNamedTuple = typing.NamedTuple('MyNamedTuple', [('my_int', int)])

        t = MyNamedTuple(5)
        t1 = namedtuple('MyNamedTuple', 'my_int')(5)
        t2 = namedtuple('MyNamedTuple', 'my_int')('string')
        t3 = runtime_validation(MyNamedTuple)(5)
        t4 = (5, )
        t5 = '5'

        @runtime_validation
        def sample(data: MyNamedTuple) -> MyNamedTuple:
            return data

        # invariant cases
        sample(t)
        with self.assertRaises(RuntimeTypeError):
            sample(t1)
        with self.assertRaises(RuntimeTypeError):
            sample(t2)
        sample(t3)
        with self.assertRaises(RuntimeTypeError):
            sample(t4)
        with self.assertRaises(RuntimeTypeError):
            sample(t5)

        # Covariant case
        config({'mode': 'covariant'})
Example #7
0
 def decorate(self, f):
     wrapper = enforce.runtime_validation(f)
     wrapper = functools.update_wrapper(wrapper, f)
     name = f.__name__
     self[f.__qualname__] = wrapper
     if name in self:
         # There is a conflict in short name
         log.debug("selector %s already registered %s vs %s",
                   name, f.__qualname__,
                   self[name].__qualname__)
     else:
         self[name] = wrapper
     return wrapper
Example #8
0
    def test_no_type_check(self):
        """
        Verifies that no_type_check is respected
        """
        def get_sample_func():
            def sample(data: int):
                pass

            return sample

        sample_d1 = typing.no_type_check(runtime_validation(get_sample_func()))
        sample_d2 = runtime_validation(typing.no_type_check(get_sample_func()))

        sample_d3 = runtime_validation(get_sample_func())

        sample_d4 = typing.no_type_check_decorator(runtime_validation(get_sample_func()))
        sample_d5 = runtime_validation(typing.no_type_check_decorator(get_sample_func()))

        get_sample_func()('str')
        sample_d1('str')
        sample_d2('str')
        with self.assertRaises(RuntimeTypeError):
            sample_d3('str')
Example #9
0
 def exec_module(self, module: ModuleType) -> None:
     from enforce import runtime_validation
     super().exec_module(module)
     if module.__package__ and module.__package__.split(
             '.')[0] in check_mods:
         for clsname, cls in inspect.getmembers(module, inspect.isclass):
             for funname, fun in list((k, v)
                                      for k, v in cls.__dict__.items()
                                      if inspect.isfunction(v)):
                 try:
                     module.__dict__[funname] = runtime_validation(fun)
                 except Exception as e:
                     logging.debug(
                         f'failed to apply runtime validation on {fun}: {e}'
                     )
Example #10
0
    def test_docstring_name_presrved(self):
        """
        Verifies that an original name and a docstring are preserved
        """
        def test(text: str) -> None:
            """I am a docstring"""
            print(text)

        original_name = test.__name__
        original_doc = test.__doc__

        test = runtime_validation(test)

        self.assertEqual(original_doc, test.__doc__)
        self.assertEqual(original_name, test.__name__)
def test_validate_none_enforce():
    """ Tests that a None will be caught by enforce: no need for not_none validator """

    from enforce import runtime_validation, config
    from enforce.exceptions import RuntimeTypeError

    # we're not supposed to do that but if your python environment is a bit clunky, that might help
    config(dict(mode='covariant'))

    from ._test_pep484 import create_for_test_validate_none_enforce
    myfunc = create_for_test_validate_none_enforce()

    # decorate manually (reverse order)
    myfunc = validate_io(a=[is_even, gt(1)], b=is_even, c=is_even)(myfunc)
    myfunc = runtime_validation(myfunc)

    # -- check that the validation works
    myfunc(84, None)     # OK because b is Nonable and c is optional with default value None
    with pytest.raises(RuntimeTypeError):
        myfunc(None, 0)  # RuntimeTypeError: a is None
Example #12
0
    def test_custom_generic_initialisation(self):
        """
        Verifies that user defined generics can be initialised
        """
        T = typing.TypeVar('T')

        class Sample(typing.Generic[T]):
            pass

        SD = runtime_validation(Sample)

        ST = Sample[int]
        SDT = SD[int]

        s = Sample()
        sd = SD()
        st = ST()
        sdt = SDT()

        self.assertFalse(hasattr(s, '__enforcer__'))
        self.assertFalse(hasattr(st, '__enforcer__'))
        self.assertTrue(hasattr(sd, '__enforcer__'))
        self.assertTrue(hasattr(sdt, '__enforcer__'))

        self.assertEqual(sd.__enforcer__.signature, Sample)
        self.assertEqual(sdt.__enforcer__.signature, Sample)

        self.assertEqual(sd.__enforcer__.generic, SD.__enforcer__.generic)
        self.assertEqual(sdt.__enforcer__.generic, SDT.__enforcer__.generic)

        self.assertEqual(sd.__enforcer__.bound, SD.__enforcer__.bound)
        self.assertEqual(sdt.__enforcer__.bound, SDT.__enforcer__.bound)

        for hint_name, hint_value in sdt.__enforcer__.hints.items():
            self.assertEqual(hint_value, SDT.__enforcer__.hints[hint_name])

        self.assertEqual(len(sdt.__enforcer__.hints),
                         len(SDT.__enforcer__.hints))
Example #13
0
    def test_custom_generic_initialisation(self):
        """
        Verifies that user defined generics can be initialised
        """
        T = typing.TypeVar('T')

        class Sample(typing.Generic[T]):
            pass

        SD = runtime_validation(Sample)

        ST = Sample[int]
        SDT = SD[int]

        s = Sample()
        sd = SD()
        st = ST()
        sdt = SDT()

        self.assertFalse(hasattr(s, '__enforcer__'))
        self.assertFalse(hasattr(st, '__enforcer__'))
        self.assertTrue(hasattr(sd, '__enforcer__'))
        self.assertTrue(hasattr(sdt, '__enforcer__'))

        self.assertEqual(sd.__enforcer__.signature, Sample)
        self.assertEqual(sdt.__enforcer__.signature, Sample)

        self.assertEqual(sd.__enforcer__.generic, SD.__enforcer__.generic)
        self.assertEqual(sdt.__enforcer__.generic, SDT.__enforcer__.generic)

        self.assertEqual(sd.__enforcer__.bound, SD.__enforcer__.bound)
        self.assertEqual(sdt.__enforcer__.bound, SDT.__enforcer__.bound)

        for hint_name, hint_value in sdt.__enforcer__.hints.items():
            self.assertEqual(hint_value, SDT.__enforcer__.hints[hint_name])

        self.assertEqual(len(sdt.__enforcer__.hints), len(SDT.__enforcer__.hints))
Example #14
0
    def test_typed_named_tuple(self):
        MyNamedTuple = typing.NamedTuple("MyNamedTuple", [("my_int", int)])
        MyNamedTuple = runtime_validation(MyNamedTuple)

        mt = MyNamedTuple(5)
        mt2 = MyNamedTuple(my_int=5)

        self.assertEqual(mt[0], 5)
        self.assertEqual(mt.my_int, 5)

        self.assertEqual(mt2[0], 5)
        self.assertEqual(mt2.my_int, 5)

        with self.assertRaises(RuntimeTypeError):
            MyNamedTuple("string")

        with self.assertRaises(RuntimeTypeError):
            MyNamedTuple(my_int="string")

        with self.assertRaises(AttributeError):
            mt2.my_int = "hello world"

        with self.assertRaises(TypeError):
            MyNamedTuple(2, my_int="string")
Example #15
0
    def test_typed_named_tuple(self):
        MyNamedTuple = typing.NamedTuple('MyNamedTuple', [('my_int', int)])
        MyNamedTuple = runtime_validation(MyNamedTuple)

        mt = MyNamedTuple(5)
        mt2 = MyNamedTuple(my_int=5)

        self.assertEqual(mt[0], 5)
        self.assertEqual(mt.my_int, 5)

        self.assertEqual(mt2[0], 5)
        self.assertEqual(mt2.my_int, 5)

        with self.assertRaises(RuntimeTypeError):
            MyNamedTuple('string')

        with self.assertRaises(RuntimeTypeError):
            MyNamedTuple(my_int='string')

        with self.assertRaises(AttributeError):
            mt2.my_int = 'hello world'

        with self.assertRaises(TypeError):
            MyNamedTuple(2, my_int='string')
Example #16
0
    def test_typed_named_tuple(self):
        MyNamedTuple = typing.NamedTuple('MyNamedTuple', [('my_int', int)])
        MyNamedTuple = runtime_validation(MyNamedTuple)

        mt = MyNamedTuple(5)
        mt2 = MyNamedTuple(my_int=5)

        self.assertEqual(mt[0], 5)
        self.assertEqual(mt.my_int, 5)

        self.assertEqual(mt2[0], 5)
        self.assertEqual(mt2.my_int, 5)

        with self.assertRaises(RuntimeTypeError):
            MyNamedTuple('string')

        with self.assertRaises(RuntimeTypeError):
            MyNamedTuple(my_int='string')

        with self.assertRaises(AttributeError):
            mt2.my_int = 'hello world'

        with self.assertRaises(TypeError):
            MyNamedTuple(2, my_int='string')