Package: gvalidate
Generic Validation For PythonChecking the input arguments of a function is a common task.
It allows the software designer to stop the flow of execution if
an error occured and to display information detailing the error.Python providesdecoratorsthat can be used to add extra
functionality to a function. The packagegvalidateprovides the functionvalidatethat
can be used to easily create argument validating decorators
while avoiding most of the
required boilerplate.InstallationTo install the packagegvalidateuse the command:$pipinstallgvalidateUsageThis section demonstrates how to use the functionvalidateto define validation decorators.1. Generic Validation DecoratorsThe example below shows how to define a decorator that will validate
the arguments of the decorated function and
raise an exception of typeValueErrorif any argument does not pass validation.The most important ingredient is the function provided asvalidator.
This function must accept one argument (the one
being validated) and return a boolean.
If it returnsFalsevalidation fails.
The functionvalidateis generic in the sense that we
can pass any function with the required signature as a validator.In the example shown below all arguments of the functionbox_dimensionsare validated using a lambda function.fromgvalidate.generic_validatorsimportvalidate@validate(validator=lambdax:x>0,message='Dimensions must be positive.'# Optional, default: ''error_type=ValueError,# Optional, default: ValueErrorenable_warnings=True,# Optional, default: True)defbox_dimensions(length,height,width):passTo validate onlycertainfunction arguments these must
be passed as a tuple via the parameterargument_names.
In the example below only the argumentslengthandheightare
validated.fromgvalidate.generic_validatorsimportvalidate@validate(validator=lambdax:x>0,argument_names=('length','height'),message='Dimensions must be positive.'# Optional, default: ''error_type=ValueError,# Optional, default: ValueErrorenable_warnings=True,# Optional, default: True)defbox_dimensions_2(length,height,width):passNote: To validate asingleargument one a string containing the argument name may
specified via the parameterargument_names.Calling the functionbox_dimensionswith negative arguments
causes an exception to be raised:box_dimensions(-1,10,20)# ... stack trace will be printed hereValueError:('Invalid argument in function box_dimensions: length = -10.''Dimensions must be positive.')The argumentmessagepassed to the decorator is appended to the
message attached to the exception. In the example abovemessagewas:
'Dimensions must be positive'.2. Concrete Validation DecoratorsIn the example above, we defined a validating decorator on the spot
using the generic methodvalidate.
To reuse a validating decorator one may define a separate function.In the example below the decoratorvalidate_callablechecks if the
specified arguments are callable.defvalidate_callable(argument_names:tuple=(),enable_warnings=True):'''Raises an exception if any argument in `argument_names` is not callable.'''returnvalidate(validator=lambdainput:callable(input),argument_names=(),message='Must be callable.',enable_warnings=enable_warnings,)# Using the decorator defined above.@validate_callable('callback')deffunction_with_a_callback(id:int,callback:callable):passReady made validation decorators can be found in the modules:function_validatorsnumerical_validatorsstring_validators3. Disabling WarningsAny invalid argument name listed in the tupleargument_nameswill be silently ignored ifenable_warningsis explicitly set toFalse.
Consider the function below:fromgvalidate.generic_validatorsimportvalidate@validate(argument_names=('aeg',),validator=lambdax:x>0,message='Age must be positive.',enable_warnings=False)defperson_data(age,name):passCalling the function with the arguments:person_data(age = -10, name = 'Anna')willpassvalidation since the argument nameaegspecified
in the decorator does not exist.Nested ValidatorsSeveral decorators performing validation
may be applied to the same function.
In that case, validation starts with the top-most decorator.
Stacking decorators allows fine grained validation.In the example below, we check thatlengthis positive andcallbackis callable:@gv.validate_positive('length')@gv.validate_callable('callback')defg(length,callback):'''Used to test nested validation decorators.'''passNote: Stacked decorators are in fact nested decorators. To allow
access to the signature of the decorated
function from within nested decoratorsfunctools.wrapswas used. For more details check out the implementation ofvalidate.TestingTo run the tests clone the project source code available atgvalidateusing the command:$ git clone https://github.com/simphotonics/gvalidate.gitThe command above will create a directory calledgvalidate.
It is recommended to create a separate environment before proceeding.Then navigate to the directorygvalidateand use the commands:$makeinit$maketestThe first command will installpytestand the local packagegvalidate. The second command
will run the unit tests located in the directorytests.ContributingContributions are welcome. To add validators that are useful to you
or other users please create a pull request or request to be added
as a collaborator.The following steps should be considered when creating a pull request:Add validators to existing modules for examplestring_validatorsor
alternatively create a new module.Document the added functions. Add a doc entry to the top of the module.
Add a doc entry to__init__.pyif a new module was added.
Consider adding documentation toREADME.md.Add tests to unit test the added functions.Features and bugsPlease file feature requests and bugs at theissue tracker.