SafeModel
A safe container, a wrapper around a structure whose schema is unknown or may dynamically change.
The idea is to put an object (e.g. a structure that is retrieved from an external source)
in a container that will support the __getattr__ and __getitem__ methods,
but will not throw errors if non-existent data is accessed.
How to install
Using uv
uv add safemodel
Using pip
pip install safemodel
How to Use
General
SafeModel is a potentially iterable object. If we try to iterate it, we get: 1. If iterable is wrapped: (SafeModel(x) for x in iterable) 2. If non-iterable is wrapped: empty iterator
When unpacking a wraparound value via __call__, it is passed to each processor sequentially.
If any processor raises ProcessingError, the value will be replaced with Placeholder.
If there is no wraparound data, Placeholder will be returned.
Processors
Functions that take 1 positional argument and return a value (usually the one passed in unchanged, but it can be changed) or throw a ProcessingError exception. The result of a processor is used by the next one in the chain.
NO_DATA
A special value denoting the absence of data.
None is not suitable because it may be the expected value in some cases.
The object denoting the absence of data must be fundamentally unobtainable from the source structure.
Examples
from safemodel import SafeModel, default_placeholder_context
unsafe_struct = {
"hello": "world",
"list_of_optional_dict_with_value": [
{"value": 1},
None,
{"value": 2},
3,
4,
],
"age_str": "24",
"strange_struct": {
"foo": "bar",
"members": [
{
"fio": {
"name": "Ivan",
}
},
],
},
"camelCaseField": "ok",
}
safe_struct = SafeModel(unsafe_struct)
assert safe_struct.hello() == "world"
expected_values = [1, "-", 2, "-", "-"]
actual_values_1 = [value_container.value("-") for value_container in safe_struct.list_of_optional_dict_with_value]
with default_placeholder_context(safe_struct, "-"):
actual_values_2 = [value_container.value() for value_container in safe_struct.list_of_optional_dict_with_value]
assert actual_values_1 == actual_values_2 == expected_values
assert safe_struct.age_str | int == 24
assert safe_struct.camel_case_field() == "ok"
assert safe_struct.strange_struct.members[0].fio.name() == "Ivan"
assert safe_struct.some.field.that.does.not_.exist("Nothing!!!") == "Nothing!!!"
assert not safe_struct.some.field.that.does.not_.exist.should.be.false
assert safe_struct.age_str | [float, str] == safe_struct.age_str(extend_processors=[float, str]) == "24.0"
How To Develop
Prepare your environment (once)
Install uv
Using scoop
scoop install uv
Without scoop
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Run Linter
Using Make
make lintfix
If Make is not installed
uv run ruff format
uv run ruff check --fix
Run Tests
With Make
make
or
make test
Without Make
uv pip install -e .
uv run pytest -v
Build
uv build
Metadata
Release files for safemodel 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| safemodel-1.0.0.tar.gz | 4.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| safemodel-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 11.8 kB
Release files / safemodel-1.0.0.tar.gz
| Download URL | safemodel-1.0.0.tar.gz |
|---|---|
| Size | 4.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6484c365e1f3a4c2833de66b735959e291b5f7541d5de667c0383cf24d2072b5
|
|
BLAKE2b-256 checksum How to use checksums |
8439aeb3689c8606c014d10f9e47bd98de53665bc799fdba91ed38e063b87f3b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.0
|
Release files / safemodel-1.0.0-py3-none-any.whl
| Download URL | safemodel-1.0.0-py3-none-any.whl |
|---|---|
| Size | 6.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4d467b2b2c4db65f34554b7314fa62e6accfa9ac78e1a728ed07b96a2b1f1821
|
|
BLAKE2b-256 checksum How to use checksums |
afbfec0fa1699bfd7d9735f7298880628b66e356c4ab437e53671b091184efd4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.0
|