RussBaz / enforce

Python 3.5+ runtime type checking for integration testing and data validation
543 stars 21 forks source link

Feature Request: Implicit Typecasting #38

Open PurelyApplied opened 7 years ago

PurelyApplied commented 7 years ago

I think a great feature would be the option to attempt a typecast if @enforce.runtime_validation fails, either as a separate decorator @enforce.runtime_typecasting or as an optional parameter @enforce.runtime_validation(coerce=True)

A simple example might be

@enforce.runtime_typecasting
def elongator(s: str):
    return s * 10
...
elongator(5)
# returns '5555555555'

For the simple primitives, this could be a simple task. For more complicated objects, an attempt to pass the argument itself to the required type as a single arg, as *args, and as **kwargs could be attempted in sequence.

class SimpleClass:
    def __init__(self, x: int):
        self.value = x

@enforce.runtime_typecasting
def SillySimpleClassFactory(x: SimpleClass):
    return x
...
SillySimpleClassFactory(10)
# returns SimpleClass(10)
class ComplicatedClass:
    def __init__(self, first_arg, second_arg, third_arg):
        ...
...
@enforce.runtime_typecasting
def ComplicatedClassFactory(x: ComplicatedClass):
    return x

ComplicatedClassFactory((1, 2, 3))
# returns ComplicatedClass(1, 2, 3)

ComplicatedClassFactory({'first_arg' : 4, 'third_arg' : 6, 'second_arg' : 5})
# returns ComplicatedClass(4, 5, 6)

I imagine Callable wouldn't be properly supported. Probably others.

I would be happy to contribute this addition myself in a month or two.

RussBaz commented 7 years ago

This sounds possible and interesting.

However, could you suggest a use case for such feature?

I believe every applied typecast must generate a corresponding warning. Otherwise, the real issue might be left forever forgotten.

In addition, it might be worth having a stand-alone function that will force the type checker to believe that given variable has a different type than what it actually will infer. It might be a useful hack when something cannot be yet understood correctly by the checker or to speed up the process of checking when the variable is known to have a given type, and the user just wants to short circuit the process of type checking without actually disabling it completely.