Liaison is a Python library for defining schemas, parsing and validating payloads
Project description
Liaison
A zero dependency Python library for defining schemas, parsing and validating payloads.
Liaison doesn't aim to be too clever. It doesn't use descriptors, fancy metaprogramming or type hints for defining
your schema. Simply inherit from the Schema
base class, define your fields and call parse
. In return, you'll
receive a simple Namespace
object containing your parsed data.
Goals:
- Simplicity
- Extensibility
- Speed
- 100% test coverage
Installation:
pip install liaison
Example:
from liaison import Schema, ValidationError
from liaison.fields import StringField, IntField, BoolField, ListField, DateTimeField
class UserSchema(Schema):
name = StringField(required=True)
email = StringField(required=True)
age = IntField(min_val=18)
date_of_birth = DateTimeField(date_format="%d-%m-%Y")
subscribed = BoolField(default=False)
tags = ListField(min_len=1)
data = {
"name": "Bar",
"email": "foo@bar.com",
"age": 21,
"tags": ["Python"]
}
result = UserSchema.parse(data)
print(result.name, result.email, result.age, result.tags) # Bar foo@bar.com 21 ['Python']
Handling validation errors:
data = {
"name": "Bar",
"email": "foo@bar.com",
"age": 16
}
try:
result = UserSchema.parse(data)
except ValidationError as e:
print(e) # Value for 'age' must be at least 18
Defining custom field validators via the <field>.validator
decorator:
class UserSchema(Schema):
name = StringField(required=True)
email = StringField(required=True)
age = IntField(min_val=18)
@name.validator
def validate_name(self, key, value):
# Define a custom validator, overrides the default validation method
if value == "Foo":
raise ValidationError(f"'{value}' is not a valid value for '{key}'")
return value
Custom validators can also be passed as a parameter to the field:
def name_validator(schema_cls, key, value):
if value in ("Foo", "Bar", "Baz"):
raise ValidationError(f"'{value}' is not a valid value for '{key}'")
return value
class UserSchema(Schema):
name = StringField(required=True, validator=name_validator)
email = StringField(required=True)
age = IntField(min_val=18)
Fields
Use fields to define your schema. By default, all fields accept the following common parameters:
Parameter | Type | Description | Default |
---|---|---|---|
required |
bool |
If the value is required | False |
default |
Any |
A default value | None |
choices |
List[Any] |
A list of choices | None |
validator |
Callable |
A function to override the default validation method | None |
strict_type |
bool |
If True , only accept the fields data type |
False |
StringField
- Defining strings
Parameter | Type | Description | Default |
---|---|---|---|
min_len |
int |
The minimum length | None |
max_len |
int |
The maximum length | None |
IntField
- Defining integers
Parameter | Type | Description | Default |
---|---|---|---|
min_val |
int |
The minimum value | None |
max_val |
int |
The maximum value | None |
FloatField
- Defining floats
Parameter | Type | Description | Default |
---|---|---|---|
min_val |
int |
The minimum value | None |
max_val |
int |
The maximum value | None |
BoolField
- Defining booleans
ListField
- Defining lists
Parameter | Type | Description | Default |
---|---|---|---|
min_len |
int |
The minimum length | None |
max_len |
int |
The maximum length | None |
SetField
- Defining sets
Note -
SetField
shares the same behaviour asListField
, returning aset
.
Parameter | Type | Description | Default |
---|---|---|---|
min_len |
int |
The minimum length | None |
max_len |
int |
The maximum length | None |
DictField
- Defining dictionaries
Parameter | Type | Description | Default |
---|---|---|---|
min_len |
int |
The minimum length | None |
max_len |
int |
The maximum length | None |
DateTimeField
- Defining datetimes
Note -
DateTimeField
fields will returndatetime
objects
Parameter | Type | Description |
---|---|---|
date_format |
str |
The date format |
UUIDField
- Defining UUIDs
Note -
UUIDField
fields will NOT return aUUID
obejct, it will return a string.
Namespace
Calling the parse
method on a Schema
object will return a Namespace
object, holding the parsed values as
attributes.
from liaison import Schema
from liaison.fields import StringField, IntField, BoolField, FloatField, UUIDField
class RESTBaseSchema(Schema):
offset = IntField(min_val=0, default=0)
limit = IntField(max_val=100)
search = StringField()
class ProductsRESTSchema(RESTBaseSchema):
product_id = UUIDField()
category = StringField()
price = FloatField()
in_stock = BoolField()
payload = {
"offset": 10,
"category": "shoes",
"in_stock": True
}
result = ProductsRESTSchema.parse(payload)
print(result.offset, result.limit, result.search, result.category, result.in_stock)
# 10 None None shoes True
Namespace
objects have a to_dict
method, returning a dictionary of the Namespace
attributes and values:
print(result.to_dict())
# {'category': 'shoes', 'in_stock': True, 'limit': None, 'offset': 10, 'price': None, 'product_id': None, 'search': None}
An optional exclude
parameter can be included to exclude certain attributes:
print(result.to_dict(exclude=("offset", "limit", "search")))
# {'category': 'shoes', 'in_stock': True, 'price': None, 'product_id': None}
Defining custom fields
Create your own fields and validation logic by inheriting from any of the field classes and implementing a
validate
method.
Note - The
validate
method must accept 2 params (key, value)
from liaison import Schema, ValidationError
from liaison.fields import StringField
class PasswordField(StringField):
def validate(self, key, value):
value = super().validate(key, value)
if len(value) < 9:
raise ValidationError("Value for 'password' must be at least 9 characters in length")
# etc...
return value
class UserSchema(Schema):
username = StringField(required=True)
password = PasswordField()
payload = {
"username": "FooBar",
"password": "password"
}
try:
result = UserSchema.parse(payload)
except ValidationError as e:
print(e) # Value for 'password' must be at least 9 characters in length
payload = {
"username": "FooBar",
"password": "password12345!"
}
result = UserSchema.parse(payload)
print(result.password) # password12345!
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
Built Distribution
File details
Details for the file liaison-0.3.tar.gz
.
File metadata
- Download URL: liaison-0.3.tar.gz
- Upload date:
- Size: 5.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ad8092967d7b38ef1157ee390bb73c3e27ca2b64e609383a66c3418f25e9e143 |
|
MD5 | 3c47a01fe4c1eaf2229fc2ecad018f85 |
|
BLAKE2b-256 | b7ff3849cd1aab615d9d472f704c3a68378431c6604f3e730b16151dd2283f16 |
File details
Details for the file liaison-0.3-py3-none-any.whl
.
File metadata
- Download URL: liaison-0.3-py3-none-any.whl
- Upload date:
- Size: 6.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 35ab3d77ed116bdf72e18cfc56ab64fcda7ceff642c0ab226384a9b63222862a |
|
MD5 | 9cfe5561729789d09ccefdd1cf44105a |
|
BLAKE2b-256 | 59ded0b6c4e9152b147cbbb3e9aa5bd74602a737aabfa17b826919c273c17cd8 |