Pydantic model utilities for serialization and settings
Project description
Model-lib - pydantic base models with convenient dump methods
Installation
pip install 'model-lib[toml]'
Model-lib tutorial: What classes to use as base classes, how to serialize them, and add metadata
- A library built on top of pydantic
- Both pydantic v1 and v2 are supported
- The models:
EventandEntityare subclassing pydantic.BaseModel- Event is immutable
- Entity is mutable
- The specific configuration are:
- Automatic registering for dumping to the various formats
- Support different serializers for yaml/json/pretty_json/toml
- use_enum_values
- Use
dump(model|payload, format) -> str- if using an
Event|Entityit should "just-work" - Alternatively, support custom dumping with
register_dumper(instance_type: Type[T],dump_call: DumpCall)(see example below)
- if using an
- Use
parse_payload(payload, format)to parse to adictorlist- bytes
- str
- pathlib.Path (format not necessary if file has extension:
.yaml|.yml|json|toml) - dict|list will be returned directly
- supports
register_parserfor adding e.g., a parser for KafkaMessage
- Use
parse_model(payload, t=Type, format)to parse and create a modeltnot necessary if class name stored inmetadata.model_name(see example below)- format not necessary if parsing from a file with extension
from datetime import datetime
from freezegun import freeze_time
from pydantic import Field
from model_lib import (
Entity,
Event,
dump,
dump_with_metadata,
parse_model,
FileFormat,
register_dumper,
)
from model_lib.serialize.parse import register_parser, parse_payload
dump_formats = list(FileFormat)
expected_dump_formats: list[str] = [
"json",
"pretty_json",
"yaml",
"yml",
"json_pydantic",
"pydantic_json",
"toml",
"toml_compact",
]
missing_dump_formats = set(FileFormat) - set(expected_dump_formats)
assert not missing_dump_formats, f"found missing dump formats: {missing_dump_formats}"
class Birthday(Event):
"""
>>> birthday = Birthday()
"""
date: datetime = Field(default_factory=datetime.utcnow)
class Person(Entity):
"""
>>> person = Person(name="espen", age=99)
>>> person.age += 1 # mutable
>>> person.age
100
"""
name: str
age: int
_pretty_person = """\
{
"age": 99,
"name": "espen"
}"""
def test_show_dumping():
with freeze_time("2020-01-01"):
birthday = Birthday(date=datetime.utcnow())
# can dump non-primitives e.g., datetime
assert dump(birthday, "json") == '{"date":"2020-01-01T00:00:00"}'
person = Person(name="espen", age=99)
assert dump(person, "yaml") == "name: espen\nage: 99\n"
assert dump(person, "pretty_json") == _pretty_person
_metadata_dump = """\
model:
name: espen
age: 99
metadata:
model_name: Person
"""
def test_show_parsing(tmp_path):
path_json = tmp_path / "example.json"
path_json.write_text(_pretty_person)
person = Person(name="espen", age=99)
assert parse_model(path_json, t=Person) == person
assert dump_with_metadata(person, format="yaml") == _metadata_dump
path_yaml = tmp_path / "example.yaml"
path_yaml.write_text(_metadata_dump)
assert parse_model(path_yaml) == person # metadata is used to find the class
class CustomDumping:
def __init__(self, first_name: str, last_name: str):
self.first_name = first_name
self.last_name = last_name
def __eq__(self, other):
if isinstance(other, CustomDumping):
return self.__dict__ == other.__dict__
return super().__eq__(other)
def custom_dump(custom: CustomDumping) -> dict:
return dict(full_name=f"{custom.first_name} {custom.last_name}")
register_dumper(CustomDumping, custom_dump)
class CustomKafkaPayload:
def __init__(self, body: str, topic: str):
self.topic = topic
self.body = body
def custom_parse_kafka(payload: CustomKafkaPayload, format: str) -> dict | list: # use Union[dict, list] if py3.9
return parse_payload(payload.body, format)
register_parser(CustomKafkaPayload, custom_parse_kafka)
def test_custom_dump():
instance = CustomDumping("Espen", "Python")
assert dump(instance, "json") == '{"full_name":"Espen Python"}'
payload = CustomKafkaPayload(
body='{"first_name": "Espen", "last_name": "Python"}', topic="some-topic"
)
assert parse_model(payload, t=CustomDumping) == instance
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
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file model_lib-0.103.2.tar.gz.
File metadata
- Download URL: model_lib-0.103.2.tar.gz
- Upload date:
- Size: 20.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0cc379369a1b825c917dcba8b22218d3929adb99caeddc6b98b5855147f0612c
|
|
| MD5 |
2873260751614b4e288448ac6ab846ff
|
|
| BLAKE2b-256 |
7196c6a0b28d8d2508af68dc48c615004c3a5c6847d51263473d46e0c6b354a3
|
Provenance
The following attestation bundles were made for model_lib-0.103.2.tar.gz:
Publisher:
release.yaml on EspenAlbert/model-lib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
model_lib-0.103.2.tar.gz -
Subject digest:
0cc379369a1b825c917dcba8b22218d3929adb99caeddc6b98b5855147f0612c - Sigstore transparency entry: 1548132967
- Sigstore integration time:
-
Permalink:
EspenAlbert/model-lib@b6ae34563a72675dfee04628100b052e82a7254e -
Branch / Tag:
refs/tags/v0.103.2 - Owner: https://github.com/EspenAlbert
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@b6ae34563a72675dfee04628100b052e82a7254e -
Trigger Event:
push
-
Statement type:
File details
Details for the file model_lib-0.103.2-py3-none-any.whl.
File metadata
- Download URL: model_lib-0.103.2-py3-none-any.whl
- Upload date:
- Size: 28.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8fd0e173d11bb984f80ed4eff28efce0acbaee4377546bba987e1191a46211e2
|
|
| MD5 |
d1b17e6b479b4f5e84fc1adcd5c64f62
|
|
| BLAKE2b-256 |
5183b5319b709d3fd0dae109f25aa96c56095c6119540bdc6bdb05f75310e933
|
Provenance
The following attestation bundles were made for model_lib-0.103.2-py3-none-any.whl:
Publisher:
release.yaml on EspenAlbert/model-lib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
model_lib-0.103.2-py3-none-any.whl -
Subject digest:
8fd0e173d11bb984f80ed4eff28efce0acbaee4377546bba987e1191a46211e2 - Sigstore transparency entry: 1548133004
- Sigstore integration time:
-
Permalink:
EspenAlbert/model-lib@b6ae34563a72675dfee04628100b052e82a7254e -
Branch / Tag:
refs/tags/v0.103.2 - Owner: https://github.com/EspenAlbert
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@b6ae34563a72675dfee04628100b052e82a7254e -
Trigger Event:
push
-
Statement type: