Files
megasniff/README.md
2025-08-29 01:29:04 +03:00

127 lines
4.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# megasniff
### Автоматическая валидация данных по схеме, сборка и разборка объекта в одном флаконе
#### Как применять:
```python
# 1. Объявляем схемы
from __future__ import annotations
import dataclasses
import typing
@dataclasses.dataclass
class SomeSchema1:
a: int
b: float | str
c: SomeSchema2 | str | None
@dataclasses.dataclass
class SomeSchema2:
field1: dict
field2: float
field3: typing.Optional[SomeSchema1]
# 2. Генерируем метод для валидации и сборки
import megasniff
infl = megasniff.SchemaInflatorGenerator()
defl = megasniff.SchemaDeflatorGenerator()
fn_in = infl.schema_to_inflator(SomeSchema1)
fn_out = defl.schema_to_deflator(SomeSchema1)
# 3. Проверяем что всё работает
data = fn_in({'a': 1, 'b': 2, 'c': {'field1': {}, 'field2': '1.1', 'field3': None}})
# SomeSchema1(a=1, b=2.0, c={'field1': {}, 'field2': 1.1, 'field3': None})
fn_out(data)
# {'a': 1, 'b': 2.0, 'c': {'field1': {}, 'field2': 1.1, 'field3': None}}
```
Особенности работы:
- поддерживает циклические зависимости
- проверяет `Union`-типы через ретрай на выбросе исключения
- по умолчанию использует готовый щаблон для кодогенерации и исполняет его по запросу, требуется особое внимание к
сохранности данного шаблона
- проверяет типы списков, может приводить списки к множествам
- не проверяет типы generic-словарей, кортежей (реализация ожидается)
- пользовательские проверки типов должны быть реализованы через наследование и проверки в конструкторе
- опциональный `strict-mode`: выключение приведения базовых типов
- для inflation может генерировать кортежи верхнеуровневых объектов при наличии описания схемы (полезно при
развертывании аргументов)
- `TypedDict` поддерживается только для inflation из-за сложностей выбора варианта при сборке `Union`-полей
- для deflation поддерживается включение режима `explicit_casts`, приводящего типы к тем, которые указаны в
аннотациях (не распространяется на `Union`-типы, т.к. невозможно определить какой из них должен быть выбран)
----
### Как установить:
#### [uv](https://docs.astral.sh/uv/concepts/projects/dependencies/#dependency-sources):
```bash
uv add megasniff --index sniff_index=https://git.nikto-b.ru/api/packages/nikto_b/pypi/simple
```
#### [poetry](https://python-poetry.org/docs/repositories/#private-repository-example):
1. Добавить репозиторий в `pyproject.toml`
```bash
poetry source add --priority=supplemental sniff_index https://git.nikto-b.ru/api/packages/nikto_b/pypi/simple
```
2. Поставить пакет
```bash
poetry add --source sniff_index megasniff
```
----
### Strict-mode:
#### Strict-mode off:
```
@dataclass
class A:
a: list[int]
```
```
>>> {"a": [1, 1.1, "321"]}
<<< A(a=[1, 1, 321])
>>> A(a=[1, 1.1, "321"])
<<< {"a": [1, 1.1, "321"]} # explicit_casts=False
<<< {"a": [1, 1, 321]} # explicit_casts=True
```
#### Strict-mode on:
```
@dataclass
class A:
a: list[int]
```
```
>>> {"a": [1, 1.1, "321"]}
<<< FieldValidationException, т.к. 1.1 не является int
>>> A(a=[1, 1.1, "321"])
<<< FieldValidationException, т.к. 1.1 не является int
```
### Tuple unwrap
```
fn = infl.schema_to_inflator(
(('a', int), TupleSchemaItem(Optional[list[int]], key_name='b', has_default=True, default=None)))
```
Создаёт `fn: (dict[str,Any]) -> tuple[int, Optional[list[int]]]: ...` (сигнатура остаётся `(dict[str,Any])->tuple`)