Metadata-Version: 2.5
Name: s-persistkit
Version: 0.1.0
Summary: «Сохранение данных» экосистемы S-kits в одном доме: persistkit.sql (SQLAlchemy 2.0, бывший ormkit), persistkit.object (MinIO+Pillow, бывший storagekit), persistkit.state (pluggable state-порты, бывший librarykit.repositories) — без тяжёлых зависимостей.
Author: Dmitry
License: MIT
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: s-corekit>=0.0.14
Provides-Extra: object
Requires-Dist: anyio>=3.0; extra == 'object'
Requires-Dist: minio>=7.0; extra == 'object'
Requires-Dist: pillow>=10.0; extra == 'object'
Provides-Extra: sql
Requires-Dist: sqlalchemy>=2.0; extra == 'sql'
Provides-Extra: sql-migrations
Requires-Dist: alembic>=1.13; extra == 'sql-migrations'
Requires-Dist: sqlalchemy>=2.0; extra == 'sql-migrations'
Description-Content-Type: text/markdown

# persistkit

«Сохранение данных» экосистемы S-kits — один дом, три подпакета, три разных
абстракции. Родился волной 4 платформы китов из слияния `ormkit` (реляционная
БД) и `storagekit` (объектное хранилище), плюс переехавший из `librarykit`
pluggable state-слой.

## Три подпакета

| Подпакет           | Что было раньше              | Extra    | Зависимости                  |
|---------------------|-------------------------------|----------|-------------------------------|
| `persistkit.sql`    | `ormkit`                      | `sql`    | `sqlalchemy>=2.0` (миграции — вложенный extra `sql-migrations`, `alembic`) |
| `persistkit.object` | `storagekit`                  | `object` | `minio`, `anyio`, `Pillow`   |
| `persistkit.state`  | `librarykit.repositories`     | —        | только `corekit` (stdlib-only) |

`persistkit.state` идёт БЕЗ extra — устанавливается вместе с корнем пакета
(`pip install s-persistkit`) и не тянет ни sqlalchemy, ни minio. В этом его
ценность: сессии/лимиты/идемпотентность для приложения, которому не нужна ни
реляционная БД, ни объектное хранилище.

```bash
pip install s-persistkit                    # только persistkit.state
pip install s-persistkit[sql]                # + persistkit.sql
pip install s-persistkit[sql-migrations]     # + alembic
pip install s-persistkit[object]             # + persistkit.object
pip install "s-persistkit[sql,object]"       # всё
```

## Контракт слоёв

`persistkit.state` не зависит ни от `persistkit.sql`, ни от
`persistkit.object` — все три подпакета взаимно независимы. Контракт
закреплён `.importlinter` (`lint-imports` в CI) и фитнес-тестом
`tests/state/test_no_heavy_deps.py` (импорт `persistkit.state` в подпроцессе
БЕЗ sqlalchemy и minio).

## `persistkit.sql` — фабрика баз, не разделяемая база

Кит НЕ экспортирует общий `Base`. `declarative_base(name)` создаёт новый
declarative-класс со своей `MetaData` на каждый вызов:

```python
from persistkit.sql import declarative_base, IntPkMixin, TimestampMixin

Base = declarative_base("my_app")

class Account(Base, IntPkMixin, TimestampMixin):
    __tablename__ = "accounts"
```

Два вызова `declarative_base(...)` (даже с одинаковым `name`) никогда не
делят метаданные — так несколько потребителей кита живут в одном процессе, не
задевая таблиц друг друга при `create_all`/`drop_all`.

## `persistkit.object` — без доменного имени Skillery

В отличие от `storagekit`-донора, здесь нет `snapshot_key()` — построение
ключа объекта (`skills/{id}/versions/{semver}.tar.gz` и т.п.) осталось делом
потребителя. `PresignedUrlGenerator` работает с ключом как с непрозрачной
строкой.

## `persistkit.state` — pluggable-порты состояния

Пять портов (сессии, лимиты, идемпотентность, KV-форма Redis, SQL-форма
asyncpg) и тринадцать реализаций (память, локальный диск на stdlib-`sqlite3`,
SaaS-адаптеры поверх портов драйвера). Один и тот же сценарий проходит на
любом наборе без правки кода потребителя:

```python
from persistkit.state import memory_repositories, local_repositories

repos = memory_repositories()                       # тесты
repos = local_repositories(root, sessions=my_store)  # ноутбук: sessions — свои
```

`local_repositories` требует `sessions=` явным аргументом — без удобного
default'а на боевое хранилище сессий: persistkit — фундаментный кит, ссылку
на что-либо более высокоуровневое (например, `librarykit.sessions`) заводить
не должен даже лениво.

## Версия

Читается из метаданных установленного дистрибутива (`importlib.metadata`),
не из литерала `__version__` в коде — второй источник правды запрещён (см.
`docs/kits/SAFETY-NET.md` в devcontour).

## Тесты

```bash
uv sync --all-extras --group dev
uv run pytest -q
```
