Package: relaxed_types
This library provides a DSL to do type check in Python. The following is provided:typed_return: Decorator used to verify the type of the return valuecheck_type: Checks if a value matches to type and predicate specificationsAny: A sentinel object that matches any python object used withcheck_typeortyped_returnedValues: A predicate function that matches the specified values instead of specificationsOr: A predicate function that performs ensures that one of the specifications matchAnd: A predicate function that performs ensures all specifications matchReturnTypeError: The exception thatcheck_typeraises if a type check failsThe main goal of this library is to have a simple way to ensure return types dynamically viatyped_return.typed_returnListsThe following snippet shows how to perform a type check (list of integers):>>>@typed_return([int])...deffunc(v):...returnv+[3,4]...>>>func([1,2])[1,2,3,4]>>>func([1,2.0])Traceback(mostrecentcalllast):...relaxed_types.ReturnTypeError:Typemismatchfor2.0,expected<type'int'>.Outervalue:[1,2.0,3,4]TuplesDifferent from lists, tuples have a fixed size. The tuple specification length has to match the value length.>>>@typed_return((str,int))...deffunc(v):...returnv...>>>func(('hello',123))('hello',123)>>>func(('hello','world'))Traceback(mostrecentcalllast):...relaxed_types.ReturnTypeError:Typemismatchfor'world',expected<type'int'>.Outervalue:('hello','world')SetsSets behave the same as lists:>>>@typed_return({str})...deffunc(x):...returnx.union({"test"})...>>>func({"a","b"})set(['a','test','b'])>>>func({"a","b",1,2,3})Traceback(mostrecentcalllast):...relaxed_types.ReturnTypeError:Typemismatchfor1,expected<type'str'>.Outervalue:set(['a',1,2,3,'test','b'])DictionariesIt is possible to specify the expected types for dictionary key values. All keys specified must exist in the dictionary —- the valueAnycan be specified as a key in order to validate additional keys.>>>@typed_return({"name":str,"age":int})...deffunc(v):...v['test']='test'...returnv...>>>func({"name":"John Doe","age":21}){'test':'test','age':21,'name':'John Doe'}>>>func({"name":"Guy","age":"47"})Traceback(mostrecentcalllast):...relaxed_types.ReturnTypeError:Typemismatchfor'47',expected<type'int'>.Outervalue:{'test':'test','age':'47','name':'Guy'}The following example shows how to specify a dictionary with keynameasstrand any other key asint.>>>fromrelaxed_typesimport*>>>@typed_return({"name":str,Any:int})...deffunc(x):...returnx...>>>func({"name":"John Doe","b":2,"c":3}){"name":"John Doe","b":2,"c":3}PredicatesPredicates allow you to create custom type checks.
A predicate is a function that expects an object and returns a boolean:Truemeans the object passed in matches the expectations andFalsemeans it does not.The following snippet ensuresfunconly returns odd numbers:>>>defodd(x):...returnx%2!=0...>>>@typed_return(odd)...deffunc(v):...returnv*3...>>>func(1)3>>>func(2)Traceback(mostrecentcalllast):...relaxed_types.ReturnTypeError:Typemismatchfor6,expected<functionoddat...>.Outervalue:6Because of predicate support, you can integraterelaxed_typeswith other libraries, such asvoluptuous:>>>fromvoluptuousimportLength>>>@typed_return([int],Length(min=10,max=100))...deffunc(l):...returnl*2...>>>func(range(10))[0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9]>>>func(range(3))Traceback(mostrecentcalllast):...voluptuous.LengthInvalid:lengthofvaluemustbeatleast10The only issue with this integration is that it might either raiseReturnTypeErroror
an exception that inherits fromvoluptuous.errors.Invalid.ValuesPredicate function that matches the specified values (not specifications). This is useful to test for literals:>>>func(0)0>>>func(1)1>>>func(2)Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>File"relaxed_types/__init__.py",line16,innewfncheck_type(result,expected_type,outer_value=result,extra=extra)File"relaxed_types/checks.py",line22,incheck_type_check_predicate(value,expected_type,outer_value)File"relaxed_types/checks.py",line35,in_check_predicate_fail(value,expected_type,outer_value,msg=expected_type.__doc__)File"relaxed_types/checks.py",line85,in_failraiseReturnTypeError(msg,value)relaxed_types.exceptions.ReturnTypeError:Expected"2"tobein(0,1)OrPredicate function that matches at least one specification:>>>@typed_return(Or(int,float))...deffunc(x):...returnx...>>>func(1)1>>>func(1.0)1.0>>>func("1")Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>File"relaxed_types/__init__.py",line16,innewfncheck_type(result,expected_type,outer_value=result,extra=extra)File"relaxed_types/checks.py",line22,incheck_type_check_predicate(value,expected_type,outer_value)File"relaxed_types/checks.py",line35,in_check_predicate_fail(value,expected_type,outer_value,msg=expected_type.__doc__)File"relaxed_types/checks.py",line85,in_failraiseReturnTypeError(msg,value)relaxed_types.exceptions.ReturnTypeError:'1'didnotmatchOr(<type'int'>,<type'float'>).Moredetailsaboutthelastcheck:Typemismatchfor'1',expected<type'float'>.Outervalue:'1'AndPredicate function that matches all specifications:>>>fromrelaxed_typesimport*>>>@typed_return({"i":And(int,lambdax:x>0)})...deffunc(x):...return{"i":x}...>>>func(1){'i':1}>>>func(1.0)Traceback(mostrecentcalllast):...relaxed_types.exceptions.ReturnTypeError:1.0didnotmatchAnd(<type'int'>,<function<lambda>at0x105f7a848>).Moredetailsaboutthelastcheck:Typemismatchfor1.0,expected<type'int'>.Outervalue:1.0>>>func(-1)Traceback(mostrecentcalllast):...relaxed_types.exceptions.ReturnTypeError:-1didnotmatchAnd(<type'int'>,<function<lambda>at0x105f7a848>).Moredetailsaboutthelastcheck:Typemismatchfor-1,expected<function<lambda>at0x105f7a848>.Outervalue:-1Combining all togetherIt’s possible to combine lists, tuples, dictionaries, predicates, and any Python type.>>>@typed_return(int,lambdax:x>0)...deffunc1(x):...returnx+10...>>>>>>func1(10)20>>>func1(-100)Traceback(mostrecentcalllast):...relaxed_types.ReturnTypeError:Typemismatchfor-90,expected<type'int'>.Outervalue:-90>>>@typed_return([int],lambdax:len(x)>0)...deffunc1(x):...returnx...>>>>>>func1([1,2])[1,2]>>>func1([])Traceback(mostrecentcalllast):...relaxed_types.ReturnTypeError:Typemismatchfor[],expected[<type'int'>].Outervalue:[]>>>@typed_return([{"name":lambdax:x.upper()==x}])...deffunc2(x):...returnx...>>>>>>func2([{"name":"JOHN DOE"}])[{'name':'JOHN DOE'}]>>>func2([{"name":"test"}])Traceback(mostrecentcalllast):...relaxed_types.ReturnTypeError:Typemismatchfor'test',expected<function<lambda>at0x10e325758>.Outervalue:[{'name':'test'}]>>>@typed_return([{"data":Any,"id":And(int,lambdax:x>0)}])...deffunc3(x):...returnx...>>>func3([{"data":"price=10","id":1}])[{'data':'price=10','id':1}]>>>func3([{"data":10,"id":2}])[{'data':10,'id':2}]>>>func3([{"data":{"price":10},"id":2}])[{'data':{'price':10},'id':2}]