Schema validator built on top of the typing module
Project description
Validate-it
- About
- Installation
- Supported fields
- Validation example
- Dataclass example
- Simple mapping example
- Nested mapping example
- Requirements
About
Schema validator built on top of the typing module
Installation
With pip:
pip install validate-it
Supported fields
import re
from datetime import datetime
from typing import Dict, List, Union, Optional
from validate_it import schema, Options
class IsNotEmailError(Exception):
pass
def is_email(key, value):
if not re.match(r"[^@]+@[^@]+\.[^@]+", value):
raise IsNotEmailError(f"{key}: is not email")
return value
@schema
class Example:
# required fields
field_a: datetime
field_b: float
# required fields with defaults
field_c: str = "unknown"
field_d: int = 9
# required fields with nested types
field_e: Dict[int, str]
field_f: List[int]
# optional fields
field_g: Optional[int]
field_h: Union[int, None] # equivalent of Optional[int]
# with some validators:
fields_i: int = Options(default=0, max_value=100, min_value=100)
fields_j: str = Options(size=10)
fields_k: str = Options(min_length=10, max_length=20)
fields_l: List[str] = Options(size=5)
fields_m: str = Options(validators=[is_email])
fields_n: int = Options(allowed=[1, 2, 3])
# with search (input) alias:
fields_o: int = Options(alias="field_n")
# with rename (output) alias:
fields_p: int = Options(rename="field_q")
# with serializer used in #to_dict(), outgoing value is str type
fields_q: int = Options(serializer=str)
# with parser used in #from_dict() or direct setattr, incoming value will be parsed as int
fields_r: int = Options(parser=int)
Validation example
from typing import List
from validate_it import *
@schema
class Simple:
a: int
b: int
simple = Simple(a=1, b=2)
simple.a = 2
simple.b = 3
try:
simple.a = 'not int'
except TypeError:
print("Wrong type")
@schema
class Owner:
first_name: str
last_name: str
@schema
class Characteristics:
cc: float = Options(min_value=0.0)
hp: int = Options(min_value=0)
@schema
class Car:
name: str = Options(min_length=2, max_length=20)
owners: List[Owner] = Options(auto_pack=True, packer=pack_value)
characteristics: Characteristics = Options(default=lambda: {"cc": 0.0, "hp": 0}, auto_pack=True, packer=pack_value)
convert: bool = Options(parser=bool)
_data = {
"name": "Shelby GT500",
"owners": [
{
"first_name": "Randall",
"last_name": "Raines",
}
],
"characteristics": {
"cc": 4.7,
"hp": 306
},
"unknown_field": 10,
"convert": 1
}
_expected = {
"name": "Shelby GT500",
"owners": [
{
"first_name": "Randall",
"last_name": "Raines",
}
],
"characteristics": {
"cc": 4.7,
"hp": 306
},
"convert": "1"
}
car = Car(**_data)
assert to_dict(car) == _expected
Dataclass example
from validate_it import *
from dataclasses import dataclass
@schema
@dataclass
class Simple:
a: int
b: int
simple = Simple(a=1, b=2)
simple.a = 2
simple.b = 3
try:
simple.a = 'not int'
except TypeError:
print("Wrong type")
Simple mapping example
from validate_it import *
@schema
class User:
first_name: str = Options(alias="f")
last_name: str = Options(alias="l")
_in_data = {
"f": "John",
"l": "Connor"
}
user = User(**_in_data)
assert to_dict(user) == {"first_name": "John", "last_name": "Connor"}
Nested mapping example
from validate_it import *
from accordion import compress
@schema
class Player:
nickname: str = Options(alias="info.nickname")
intelligence: int = Options(alias="characteristics/0")
dexterity: int = Options(alias="characteristics/1")
strength: int = Options(alias="characteristics/2")
vitality: int = Options(alias="characteristics/3")
_in_data = {
"info": {
"nickname": "Killer777",
},
"characteristics": [
7,
55,
11,
44
]
}
player = Player(**compress(_in_data))
assert to_dict(player) == {
"nickname": "Killer777",
"intelligence": 7,
"dexterity": 55,
"strength": 11,
"vitality": 44
}
and back:
from validate_it import *
from accordion import expand
@schema
class Player:
nickname: str = Options(rename="info.nickname")
intelligence: int = Options(rename="characteristics/0")
dexterity: int = Options(rename="characteristics/1")
strength: int = Options(rename="characteristics/2")
vitality: int = Options(rename="characteristics/3")
_in_data = {
"nickname": "Killer777",
"intelligence": 7,
"dexterity": 55,
"strength": 11,
"vitality": 44
}
player = Player(**_in_data)
assert expand(to_dict(player)) == {
"info": {
"nickname": "Killer777",
},
"characteristics": [
7,
55,
11,
44
]
}
Requirements
Tested with python3.6
, python3.7
, pypy3.6-7.0.0
Contribution how-to
Run tests:
- clone repo:
git clone <your-fork>
- create and activate your virtualenv
pip install -r requirements.txt && pip install -r dev-requirements
./run_tests.sh
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
validate-it-0.9.3.tar.gz
(9.9 kB
view hashes)