Skip to main content

A safe container, a wrapper around a structure whose schema is unknown or may dynamically change.

Project description

SafeModel

PyPI version Downloads

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

safemodel-1.0.0.tar.gz (4.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

safemodel-1.0.0-py3-none-any.whl (6.9 kB view details)

Uploaded Python 3

File details

Details for the file safemodel-1.0.0.tar.gz.

File metadata

  • Download URL: safemodel-1.0.0.tar.gz
  • Upload date:
  • Size: 4.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.0

File hashes

Hashes for safemodel-1.0.0.tar.gz
Algorithm Hash digest
SHA256 6484c365e1f3a4c2833de66b735959e291b5f7541d5de667c0383cf24d2072b5
MD5 72b849b825d520f59a3af688dd244b76
BLAKE2b-256 8439aeb3689c8606c014d10f9e47bd98de53665bc799fdba91ed38e063b87f3b

See more details on using hashes here.

File details

Details for the file safemodel-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: safemodel-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 6.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.0

File hashes

Hashes for safemodel-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4d467b2b2c4db65f34554b7314fa62e6accfa9ac78e1a728ed07b96a2b1f1821
MD5 944c4bd6e62d8b3c3ced56cfa686a3e7
BLAKE2b-256 afbfec0fa1699bfd7d9735f7298880628b66e356c4ab437e53671b091184efd4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page