PieValidator 0.0.1
A simple python package for validating user input with a schema orientated approach

# PieValidator, Python Data Validation

A simple python package for validating user input. It can mainly be used for APIs and json data. <br>
Don't forget to check out [the documentation](#documentation) section.

## Installation

You can install the package through PyPi
```python
pip install PieValidator
```

## Sample Usage

```python
from PieValidator import String, Number, Boolean, Array, Object
import json, requests

# Fetching json data from URL
response = requests.get("https://jsonplaceholder.typicode.com/todos")
todo = json.loads(response.text)[0]

## Creating a schema
todo_schema = Object({
    "title": String().min(20),
    "profile_url": String().url(),
    "related_todo_ids": Array().length(5).of(int),
    "is_completed": Boolean().required(),
    "author": Object({
        "user_id": Number().min(10),
        "email": String().email().required()
    })
})

# Validating object
>>> todo_schema.validate(todo)
{'title': 'Title must have a minimum length of 20'}
```

## Documentation

You can use one of the following Types:

- `` Number() `` Integer and Float values
  - `` Number().min(number: int) `` Defines a minimum value 
  - `` Number().max(number: int) `` Defines a maximum value 
  - `` Number().custom(function: lambda) `` Custom rule
  - `` Number().required() `` Makes value required
  
- `` String() `` Strings
  - `` String().min(number: int) `` Defines a minimum value 
  - `` String().max(number: int) `` Defines a maximum value
  - `` String().length(number: int) `` Validates if the length is exactly equal to n
  - `` String().email() `` Checks if value is a valid email
  - `` String().url() `` Checks if value is a valid http url
  - `` String().custom(function: lambda) `` Custom rule
  - `` String().required() `` Makes value required
  
- `` Array() `` Python list
  - `` Array().min(number: int) `` Defines a minimum value 
  - `` Array().max(number: int) `` Defines a maximum value
  - `` Array().length(number: int) `` Validates if the length is exactly equal to n
  - `` Array().of(x: type) `` Validates if all list items are of type x
  - `` Array().custom(function: lambda) `` Custom rule
  - `` Array().required() `` Makes value required
  
- `` Boolean() `` Fetch the 15 latest posts
  - `` Boolean().custom(function: lambda) `` Custom rule
  - `` Boolean().required() `` Makes value required
 
### Labels

Labels can be passed as a parameter to the initialization of a validation type,
If nothing is passed, it will default to "Value" 
(Types that are keys inside a Object({}) instance will get named after their dictionary key if the schema doesn't include any labels by default):

```python
schema = Number("Age").min(10)
>>> schema.validate(6)
# Output: "Age must be greator or equal to 10"

# To pass a label into an object, use the second parameter
>>> Object(dictionary, "BookDictionary")
```

### Exit Early

You can pass an `` exit_early `` kwarg in the .validate() method to configurate its behavior
It is set to True by default, which will return the first error message that the program will encounter. Otherwise, it will return a list.

```python
>>> example_schema.validate(data, exit_early=False)
{ "value": ["Error #1", "Error #2"...] }

>>> example_schema.validate(data, exit_early=True)
{ "value": "Error #1" }
```

### Custom Validation Rules

```python
is_even_schema = Number().custom(lambda n: n % 2 == 0, message="Number has to be even!")
>>> is_even_schema.validate(9)
"Number has to be even!"
```

### Custom Error Messages

To add a custom error message, pass a string as the `` message `` kwarg:
Here are some formatting rules that you can follow:
- `` [[key]] `` will get replaced by the rule's label
- `` [[0]] `` will be replaced by the 1st argument of the function and so on..

```python
bigger_than_ten_schema = Number().min(10, message="Value has to be greater than 10!") 
# Or: message="[[key]] has to be greater than [[0]]!"

error = bigger_than_ten_schema.validate(4)
```