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 -
SetFieldshares 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 -
DateTimeFieldfields will returndatetimeobjects
| Parameter | Type | Description |
|---|---|---|
date_format |
str |
The date format |
UUIDField - Defining UUIDs
Note -
UUIDFieldfields will NOT return aUUIDobejct, 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
validatemethod 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!
Metadata
Release files for liaison 0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| liaison-0.3.tar.gz | 5.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| liaison-0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 11.8 kB
Release files / liaison-0.3.tar.gz
| Download URL | liaison-0.3.tar.gz |
|---|---|
| Size | 5.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ad8092967d7b38ef1157ee390bb73c3e27ca2b64e609383a66c3418f25e9e143
|
|
BLAKE2b-256 checksum How to use checksums |
b7ff3849cd1aab615d9d472f704c3a68378431c6604f3e730b16151dd2283f16
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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
|
Release files / liaison-0.3-py3-none-any.whl
| Download URL | liaison-0.3-py3-none-any.whl |
|---|---|
| Size | 6.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
35ab3d77ed116bdf72e18cfc56ab64fcda7ceff642c0ab226384a9b63222862a
|
|
BLAKE2b-256 checksum How to use checksums |
59ded0b6c4e9152b147cbbb3e9aa5bd74602a737aabfa17b826919c273c17cd8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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
|