Package: pycomb
PyCombTcombport for Python 3. It
provides a means to apply runtime type checking.InstallationpipinstallpycombBasic examplesfrompycombimportcombinators# A simple stringMyStringType=combinators.Strings1=combinators.String('hello')# This IS a 'str' objects2=combinators.String(10)# This will fail# A list that contains only stringsListOfStrings=combinators.list(combinators.String)l1=ListOfStrings(['1','2','3'])# This IS a native tuplel1=ListOfStrings(['1','2',3])# This will fail# Structured dataUser=combinators.struct({'name':combinators.String,'age':combinators.Int,'city':combinators.maybe(combinators.String)})my_user=User({'name':'John Burns','age':30})# This IS a dictmy_user2=User({'name':'John Burns','age':'30'})# This will failmy_user3=User({'name':'John Burns','age':30,'city':'New York'})# This IS a dict# SubtypesSmallString=combinators.subtype(combinators.String,lambdad:len(d)<=10)# Strings shorter than 11 charactersSmallString('12345678901')# This will failSmallString('12345')# This IS a 'str' object# Constantsjohn_data={'name':'John'}John=combinators.constant(john_data,name='JohnConstant')John({'name':'John'})John({'name':'Jack'})# Error on JohnConstant: expected JohnConstant but was dict# Regexp with groupsimportredefname_condition(d):returndin('John','Jack')defage_condition(d):returnint(d)>0Name=combinators.subtype(combinators.String,name_condition,name='Name')Age=combinators.subtype(combinators.String,age_condition,name='Age')NameAndAge=combinators.regexp_group('(\w+) +(-?[0-9]+)',Name,Age,name='NameAndAge')NameAndAge('John 32')# OkNameAndAge('John 3x')# Error on NameAndAge: expected NameAndAge but was strNameAndAge('John -32')# Error on NameAndAge[1]: expected Age but was strNameAndAge('WRONG 32')# Error on NameAndAge[0]: expected Name but was strValidation contextThe validation procedure runs within a context that controls:The behavior in case of errorThe production mode: if active, no such error is raised during
validationContext Examplesfrompycombimportcombinators,context# Example of production modeListOfNumbers=combinators.list(combinators.Number,'ListOfNumbers')production_ctx=context.create(production_mode=True)numbers=ListOfNumbers([1,2,'hello'],ctx=production_ctx)# This will NOT fail# Example of custom behavior in case of errorclassMyObserver(context.ValidationErrorObserver):defon_error(self,ctx,expected_type,found_type):print('Expected{}, got{}'.format(expected_type,found_type))ListOfNumbers=combinators.list(combinators.Number,'ListOfNumbers')notification_ctx=context.create(validation_error_observer=MyObserver())numbers=ListOfNumbers([1,2,'hello'],ctx=production_ctx)# This will NOT fail# Expected output:# > Expected Int or Float, got <class 'str'>DecoratorsIt is possible to wrap functions in order to protect the input
parameters, or ensure the type of its return valueDecorators examplefrompycombimportcombinators# Example of input parameters check@combinators.function(combinators.String,combinators.Int,c=combinators.Float,d=combinators.list(combinators.Int))deff(a,b,c=None,d=None):passf('John',1,c=1.0,d=[3,4])# OKf(1,1,c=1.0,d=[3,4])# This will fail# Example of output check@returning(cmb.subtype(cmb.String,lambdad:len(d)<10))deff(n):return' '*nf(3)# OKf(10)# This will failMore types are supported, such as:UnionsIntersectionsFunctionsEnums…All the base types have a default example field. Please read the test
code to find more examples.