项目作者: shezadkhan137

项目描述 :
Easy multi-field validation
高级语言: Python
项目地址: git://github.com/shezadkhan137/required.git
创建时间: 2017-02-15T22:45:52Z
项目社区:https://github.com/shezadkhan137/required

开源协议:MIT License

下载


required: A easy to use DSL for validation

PyPI
Build Status
Coverage Status

Required is a simple library which allows you to validate dependencies
across multiple fields. The goal is to make writing things like forms, seralizers and functions much easier by providing a declarative way to encode validation logic. It aims to:

  • Have a declarative way to encode validation logic
  • Allow you to maintain validation logic easily
  • Allow you to reuse your validation logic easily
  • Be flexible with what you want to validate

If this all sounds good. Read On!

Installation

Install using pip

  1. pip install required

Quickstart

You can use required in a number of ways. The easiest way is to use the validate decorator to validate inputs to function calls.

  1. from required import validate
  2. @validate
  3. def calculate_sum(positive_number, negative_number):
  4. """
  5. positive_number -> positive_number > 0
  6. negative_number -> negative_number < 0
  7. """
  8. return positive_number + negative_number
  9. # the following will raise a validation exception
  10. calculate_sum(1, 1)
  11. # this will pass validation
  12. calculate_sum(1, -1) # 0

If you want to have other information in the docstring, the validation rules can be wrapped inside of Requires { } as shown below:

  1. @validate
  2. def calculate_sum(positive_number, negative_number):
  3. """
  4. Other documentation relating to calculate_sum
  5. Requires {
  6. positive_number -> positive_number > 0
  7. negative_number -> negative_number < 0
  8. }
  9. You can also put information after the requires rules
  10. """
  11. return positive_number + negative_number

Validation rules are written in the doc string of the function. They look like:

[param] -> [expression_1] [comparator] [expression_2]

When param is present, it requires expression_1 [comparator] expression_2 to evaluate to true.

The most simple expressions are just variables passed into the function to validate, however they can be more complex. See cookbook for more examples.

The comparator can be one of the standard python comparator operations; ==, !=, in, >= <=, >, <.

Cookbook

The following shows some examples for writing validation rules

  1. # Arithmetic on the objects follow normal maths rules.
  2. # you need to put brackets to define expressions
  3. x -> (x + 1) < 1
  4. x -> (x - y) == 1
  5. # A value `x` needs to be in an array
  6. x -> x in arr
  7. # The length of x must be 10
  8. # see section on registering functions
  9. x -> len(x) == 10
  10. # The length of x and y must be the same
  11. x -> len(x) == len(y)
  12. # when x is present y must not be present
  13. # TODO: not implemented in DSL yet
  14. x -> x == <empty>
  15. # x must be equal to the return value of a function
  16. x -> x == func(x)
  17. # Partial dependencies can be also specified
  18. # when x == 1 then y must be 2
  19. x == 1 -> y == 2
  20. # when x == 1 then y must be set
  21. x == 1 -> y

Registering callables

You can register callables into the validation scope. This is useful when you want to call normal python builtins or custom callables.

  1. from required import validate
  2. scoped_validate = validate.register_callables({
  3. "len": len,
  4. "abs": abs
  5. })
  6. @scoped_validate
  7. def return_first_element(arr):
  8. """
  9. arr -> len(arr) >= 1
  10. """
  11. return arr[0]
  12. # validation scoped callables can also be nested
  13. # len, abs and my_func are available in the second_scoped_validate decorator
  14. second_scoped_validate = scoped_validate.register_callables({
  15. "my_func": my_func
  16. })
  17. # or inserted at function level
  18. @validate(callables_dict={"new_func": new_func})
  19. def other_function(var):
  20. """
  21. var -> new_func(var) >= 1
  22. """
  23. return var

Contributing

If you want to contribute you are most welcome! This project is distributed under the MIT licence. It is tested using tox against Python 2.7 and 3.4+