A simple library that help you dump and load SQLModel object
Project description
dump-sqlmodel
A simple library that helps you dump and load your SQLModel objects
I. Introduction
This is a simple library that helps you dump and load your SQLModel objects. It also preserve complex relationship object.
So why not model_dump?
Because when you have a cyclic Relationship reference, model_dump will just call recursively and reach recursion limit.
In this library, it uses seen mechanism and reference mechanism. In simple term, each time it sees a Relationship, it will check if the relationship is in a seen list. If so, create a reference that links to the origin Relationship, or else, dump the Relationship and push a reference link to the seen list
II. So are there any disadvantages?
I think there are a lots ;-;
- I just implement a few obj type that can't be JSON serializable, which includes Enum, datetime and pydantic BaseModel.
- It requires manually garbage collector implement to get rid of the reference list or you will evntually get memory leak eror (I'm sorry ;-;)
- And more...
III. Installation
If you still choose me, then this is installation guide.
Make sure your Python version is 3.11 or higher by using this command:
python --version
If it shows Python 3.11 or greater then you are good to go.
You can install it with pip using this command:
pip install dump-sqlmodel
Or if you want to use Redis, use this command:
pip install 'dump-sqlmodel[redis]'
IV. How to use this?
First, import the class:
from sqlmodel_dump import SQLModelDump
Or import the async or redis version:
from sqlmodel_dump.ext.io import SQLModelDump
from sqlmodel_dump.ext.redis import SQLModelDump
from sqlmodel_dump.ext.aio_redis import SQLModelDump
Second, init it:
sqlmodel_dump = SQLModelDump()
Or with the redis version
sqlmodel_dump = SQLModelDump(redis=<your redis client>)
sqlmodel_dump = SQLModelDump(redis=<your async redis client>)
Third, use it:
enrollment = <some SQLModel>
dump_data = sqlmodel_dump.dumps(enrollment)
print(dump_data)
{
"__type": "model",
"__class": "Enrollment",
"id": "f2915205-831c-4941-b116-7c76b27ebd2f",
"classroom": {
"__type": "relationship",
"__class": "Class",
"__ref": "Class:b607a4a3-4a10-453b-aed4-cd575ebb6c36" # An address to the reference in `_ref` object
},
...
}
But there is an option called self_ref, what is that?
With self_ref set to False, the Relationship reference will be stored in SQLModelDump._ref dict.
This is the default mode and need a garbage collector in order not to raise the memory leak error..
Example: Return object:
{
"__type": "model",
"__class": "Enrollment",
"id": "f2915205-831c-4941-b116-7c76b27ebd2f",
"classroom": {
"__type": "relationship",
"__class": "Class",
"__ref": "Class:b607a4a3-4a10-453b-aed4-cd575ebb6c36" # An address to the reference in `_ref` object
},
...
}
The _ref object
{
"Class:b607a4a3-4a10-453b-aed4-cd575ebb6c36": { # The relationship value
"__type": "model",
"__class": "Class",
"id": "b607a4a3-4a10-453b-aed4-cd575ebb6c36",
"name": "Test Class",
"subject": "Test",
"teacher_id": "3135756c-be25-41a5-a6a8-be2c6f667c99",
"teacher": {
"__type": "relationship",
"__class": "Teacher",
"__ref": "Teacher:3135756c-be25-41a5-a6a8-be2c6f667c99" # Reference to another object
}
},
...
}
With self_ref set to True, the reference will be stored in the result object itself.
This can help eliminate the garbage collector but the result object size will be significantly increased
Example:
{
"__type": "model",
"__class": "Enrollment",
"id": "ae4efb62-cd94-47bf-a6e7-3f9c93703c00",
"class_id": "bdd2df1c-5b33-467b-9c0b-a1e69f4324b2",
"classroom": {
"__type": "relationship",
"__class": "Class",
"__ref": "Class:bdd2df1c-5b33-467b-9c0b-a1e69f4324b2",
"__val": { # The relationship will be store in itself
"__type": "model",
"__class": "Class",
"id": "bdd2df1c-5b33-467b-9c0b-a1e69f4324b2",
"created_at": {
"__type": "datetime",
"__val": 1772292084.449564
},
"updated_at": {
"__type": "datetime",
"__val": 1772292084.449624
},
"name": "Test Class",
"subject": "Test",
...
}
},
...
}
V. API
1. SQLModelDump
SQLModelDump(
max_depth: int = 3,
self_ref: bool = False,
key_factory: Callable[[Any], str] | None = None,
attr_to_key: dict[str | type[Any], list[str]] | None = None,
ref_alternative: Callable[[str], Any] | None = None
)
Create a SQLModelDump instance
Args:
max_depthintcontrol how deep the serializer and deserializer will goself_refboolUseself_refmodeattr_to_keydictA map of class or class name and keys that will be used to create the reference key. For example, if you want class Enrollment use its class_id and student_id for reference key, it should be{ Enrollment: ["class_id", "student_id"] }. This is the alternative way to modify the reference key.key_factoryCallableA custom function to produce the key for reference, should accept only one args is the reference objectref_alternativeCallableA function to call when a reference is missing, could be an async function
dumps(obj: SQLModel) -> dict[str, Any]
Dump the SQLModel object
Args:
objSQLModelThe object to dumps
Return dict[str, Any] The dumped object
loads(obj: Any) -> Any
Load the SQLModel object
Args:
objSQLModelThe object to loads
Return Any The loaded object
2. Async SQLModelDump
SQLModelDump(
max_depth: int = 3,
self_ref: bool = False,
key_factory: Callable[[Any], str] | None = None,
attr_to_key: dict[str | type[Any], list[str]] | None = None,
ref_alternative: Callable[[str], Coroutine[Any, Any, Any]] | None = None
)
Create an async SQLModelDump instance, which accept ref_alternative as an async function.
Args:
max_depthintcontrol how deep the serializer and deserializer will goself_refboolUseself_refmodeattr_to_keydictA map of class or class name and keys that will be used to create the reference key. For example, if you want class Enrollment use its class_id and student_id for reference key, it should be{ Enrollment: ["class_id", "student_id"] }. This is the alternative way to modify the reference key.key_factoryCallableA custom function to produce the key for reference, should accept only one args is the reference objectref_alternativeCallableA function to call when a reference is missing, could be an async function
3. Redis SQLModelDump
ext.redis.SQLModelDump(
redis: Redis,
max_depth: int = 3,
self_ref: bool = False,
key_factory: Callable[[Any], str] | None = None,
attr_to_key: dict[str | type[Any], list[str]] | None = None,
ref_alternative: Callable[[str], Any] | None = None,
running_loop: AbstractEventLoop | None = None,
store_obj_to_redis: bool = False,
set_kwargs: dict[str, Any] = {},
get_kwargs: dict[str, Any] = {},
)
Create a SQLModel with Redis as the reference manager
Args:
redisredis.RedisRedis clientmax_depthintcontrol how deep the serializer and deserializer will goself_refboolUseself_refmodeattr_to_keydictA map of class or class name and keys that will be used to create the reference key. For example, if you want class Enrollment use its class_id and student_id for reference key, it should be{ Enrollment: ["class_id", "student_id"] }. This is the alternative way to modify the reference key.key_factoryCallableA custom function to produce the key for reference, should accept only one args is the reference objectref_alternativeCallableA function to call when a reference is missing, could be an async functionset_kwargsdict[str, Any]The kwargs to pass to set functionget_kwargsdict[str, Any]The kwargs to pass to get function
loads_from_redis(key: str) -> Any
Loads the object from Redis
Args
keystrThe Redis key
Return Any The loaded object
dumps(obj: SQLModel, store_obj_to_redis: bool) -> dict[str, Any]
Dump the SQLModel object
Args:
objSQLModelThe object to dumpsstore_obj_to_redisboolWill the result object be stored in the Redis before returning
Return dict[str, Any] The dumped object
The rest Like SQLModelDump
4. Async Redis SQLModelDump
ext.aio_redis.SQLModelDump(
redis: Redis,
max_depth: int = 3,
self_ref: bool = False,
key_factory: Callable[[Any], str] | None = None,
attr_to_key: dict[str | type[Any], list[str]] | None = None,
ref_alternative: Callable[[str], Any] | None = None,
store_obj_to_redis: bool = False,
set_kwargs: dict[str, Any] = {},
get_kwargs: dict[str, Any] = {},
)
Create a SQLModel with Redis as the reference manager
Args:
redisredis.asyncio.RedisAsync Redis clientmax_depthintcontrol how deep the serializer and deserializer will goself_refboolUseself_refmodeattr_to_keydictA map of class or class name and keys that will be used to create the reference key. For example, if you want class Enrollment use its class_id and student_id for reference key, it should be{ Enrollment: ["class_id", "student_id"] }. This is the alternative way to modify the reference key.key_factoryCallableA custom function to produce the key for reference, should accept only one args is the reference objectref_alternativeCallableA function to call when a reference is missing, could be an async functionstore_obj_to_redisboolWill the result object be stored in the Redis before returningset_kwargsdict[str, Any]The kwargs to pass to set functionget_kwargsdict[str, Any]The kwargs to pass to get function
The rest Like Redis SQLModelDump but use async :D
5. Serializer
Serializer(
self_ref: bool = False,
max_depth: int = 3,
key_factory: Callable[[Any], str] | None = None,
attr_to_key: dict[str | type[Any], list[str]] | None = None,
)
Create a Serializer
Args:
self_refboolUse self_ref mode. The output will be a self_ref objectmax_depthintControll how deep the serializer will dig into the object.attr_to_keydictA map of class or class name and keys that will be used to create the reference key. For example, if you want class Enrollment use its class_id and student_id for reference key, it should be{ Enrollment: ["class_id", "student_id"] }. This is the alternative way to modify the reference key.key_factoryCallable[[Any], str]Modify how a reference key will be created. Accept the refering object as the input and the output must be a string as the reference key. The default key pattern isobj_class_name:obj_id
ref: dict[str, Any]
Store references. Will be an empty object if self_ref is set to True
base_class: dict[str, type[Any]]
Store reference class to recontruct them when come to deserialization. Should be passed to Deserializer.
serialize(obj: Any, current_depth: int = 1) -> Any
Serialize object into a json object.
Args:
objAnyObject to serializecurrent_depthintTo control the object depth
Return Any The dumped object
Note: This function will be call recusively while running.
6. Deserializer
Deserializer(
get_class: Callable[[str], type[Any] | None],
get_ref: Callable[[str], Any] | None = None,
self_ref: bool = False,
max_depth: int = 3,
ref_alternative: Callable[[str], Any] | None = None
)
Create a Deserializer
Args:
get_classCallable[[str], type[Any] | None]The function to get the reference class.get_refCallable[[str], Any] | NoneThe function to get the reference.self_refboolUseself_refmode. Will return aself_refobject.max_depthintControll how deep the deserializer will dig into the object.ref_alternativeCallable[[str], Any] | NoneThe function to call when the ref is missing. Could be a function to call to the DB. Should return the obj, not a dict, for example, a SQLModel object.
deserialize(obj: Any, current_depth: int = 1) -> Any
Deserialize json object into a object.
Args:
objAnyObject to deserializecurrent_depthintTo control the object depth
Return Any The loaded object
7. AsyncDeserializer
ext.aio.AsyncDeserializer(
get_class: Callable[[str], type[Any] | None],
get_ref: Callable[[str], Any] | None = None,
self_ref: bool = False,
max_depth: int = 3,
ref_alternative: Callable[[str], Coroutine[Any, Any, Any]] | None = None
)
Create a AsyncDeserializer, which accept ref_alternative as an async function.
Args:
get_classCallable[[str], type[Any] | None]The function to get the reference class.get_refCallable[[str], Any] | NoneThe function to get the reference.self_refboolUseself_refmode. Will return aself_refobject.max_depthintControll how deep the deserializer will dig into the object.ref_alternativeCallable[[str], Any] | NoneThe function to call when the ref is missing. Could be a function to call to the DB. Should return the obj, not a dict, for example, a SQLModel object.
async deserialize(obj: Any, current_depth: int = 1) -> Any
Deserialize json object into a object.
Args:
objAnyObject to deserializecurrent_depthintTo control the object depth
Return Any The loaded object
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 dump_sqlmodel-1.3.1.tar.gz.
File metadata
- Download URL: dump_sqlmodel-1.3.1.tar.gz
- Upload date:
- Size: 31.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
685233bae40a8f8236197522b14f7a6731b5cf6b818346d0e6e8fe9b0d46d3be
|
|
| MD5 |
081df817d7095afd7aab96665bb2d52c
|
|
| BLAKE2b-256 |
1f77f53ef8065d8ae816b8cd85c68718b3c908061723343f616cffe968cfecc3
|
File details
Details for the file dump_sqlmodel-1.3.1-py3-none-any.whl.
File metadata
- Download URL: dump_sqlmodel-1.3.1-py3-none-any.whl
- Upload date:
- Size: 18.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f288e82238ba8fac09eaaf46f227f38b0f9400a6633e16e5e8de1bc61de064d2
|
|
| MD5 |
ef6db0e38809e3cc2612832bcdedb92d
|
|
| BLAKE2b-256 |
79311b6b1e9688dd5107694610a007aee9c47f3f4b65312d12083af3f7664d27
|