varco-sa 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,191 @@
1
+ Metadata-Version: 2.4
2
+ Name: varco-sa
3
+ Version: 0.0.1
4
+ Summary: SQLAlchemy async backend for varco — runtime ORM generation, repository, schema guard, and Alembic helpers
5
+ License: Apache-2.0
6
+ Keywords: fastapi,sqlalchemy,async,domain-model,repository,alembic,orm,schema-guard
7
+ Author: edoardo.scarpaci
8
+ Author-email: edoardo.scarpaci@gmail.com
9
+ Requires-Python: >=3.12
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Framework :: FastAPI
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Database
19
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
20
+ Classifier: Typing :: Typed
21
+ Requires-Dist: sqlalchemy[asyncio] (>=2.0)
22
+ Requires-Dist: varco-core (>=0.0.1)
23
+ Project-URL: Documentation, https://github.com/edoardoscarpaci/varco#sqlalchemy-backend
24
+ Project-URL: Homepage, https://github.com/edoardoscarpaci/varco
25
+ Project-URL: Repository, https://github.com/edoardoscarpaci/varco
26
+ Description-Content-Type: text/markdown
27
+
28
+ # varco-sa
29
+
30
+ [![PyPI version](https://img.shields.io/pypi/v/varco-sa)](https://pypi.org/project/varco-sa/)
31
+ [![Python](https://img.shields.io/pypi/pyversions/varco-sa)](https://pypi.org/project/varco-sa/)
32
+ [![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/edoardoscarpaci/varco/blob/main/LICENSE)
33
+ [![GitHub](https://img.shields.io/badge/GitHub-edoardoscarpaci%2Fvarco-blue?logo=github)](https://github.com/edoardoscarpaci/varco)
34
+
35
+ SQLAlchemy async backend for **varco**.
36
+
37
+ Generates SQLAlchemy ORM classes at runtime from your `DomainModel` subclasses — no hand-written ORM models needed. Requires [`varco-core`](https://pypi.org/project/varco-core/).
38
+
39
+ ---
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ pip install varco-sa
45
+
46
+ # With PostgreSQL async driver:
47
+ pip install "varco-sa[postgresql]"
48
+
49
+ # With SQLite (tests / local dev):
50
+ pip install "varco-sa[sqlite]"
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Features
56
+
57
+ - **Zero-boilerplate ORM** — `SAModelFactory` generates `DeclarativeBase` subclasses at runtime; no duplication between domain and ORM layers
58
+ - **Full async repository** — `AsyncSQLAlchemyRepository` implements `AsyncRepository` (CRUD, `exists()`, `stream_by_query()` with server-side cursor)
59
+ - **Unit of Work** — `SQLAlchemyUnitOfWork` manages `AsyncSession` lifecycle and atomic commits
60
+ - **One-liner bootstrap** — `SAFastrestApp` + `SAConfig` wire engine, session factory, ORM generation, and table creation
61
+ - **Alembic integration** — `get_target_metadata()` and `print_create_ddl()` helpers for migration scripts
62
+ - **Schema Guard** — `SchemaGuard` detects drift between ORM metadata and the live database schema
63
+ - **Query integration** — accepts `varco-core` `QueryParams` / `QueryBuilder` AST natively; translates to SQLAlchemy `where()` clauses
64
+
65
+ ---
66
+
67
+ ## What's in the package
68
+
69
+ | Module | Purpose |
70
+ |---|---|
71
+ | `factory.py` | `SAModelFactory` — generates `DeclarativeBase` subclasses at runtime; `SAModelRegistry` — escape hatch |
72
+ | `repository.py` | `AsyncSQLAlchemyRepository` — `AsyncSession`-backed CRUD + `exists()` + `stream_by_query()` |
73
+ | `uow.py` | `SQLAlchemyUnitOfWork` — session lifecycle + atomic commits |
74
+ | `provider.py` | `SQLAlchemyRepositoryProvider` — wires factory + repos + UoW |
75
+ | `bootstrap.py` | `SAConfig`, `SAFastrestApp` — one-liner app setup |
76
+ | `alembic_helpers.py` | `get_target_metadata`, `print_create_ddl` — Alembic integration |
77
+ | `schema_guard.py` | `SchemaGuard` — drift detection between ORM metadata and live DB |
78
+
79
+ ---
80
+
81
+ ## Quick start
82
+
83
+ ### Bootstrap (one-liner)
84
+
85
+ ```python
86
+ from sqlalchemy.ext.asyncio import create_async_engine
87
+ from sqlalchemy.orm import DeclarativeBase
88
+ from varco_sa import SAConfig, SAFastrestApp
89
+
90
+ class Base(DeclarativeBase): pass
91
+
92
+ engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/mydb")
93
+
94
+ app = SAFastrestApp(SAConfig(
95
+ engine=engine,
96
+ base=Base,
97
+ entity_classes=(User, Post),
98
+ ))
99
+
100
+ await app.create_all() # CREATE TABLE IF NOT EXISTS ...
101
+ uow_provider = app.uow_provider # ready to inject as IUoWProvider
102
+ ```
103
+
104
+ ### Manual setup
105
+
106
+ ```python
107
+ from sqlalchemy.ext.asyncio import async_sessionmaker
108
+ from varco_sa import SQLAlchemyRepositoryProvider
109
+
110
+ sessions = async_sessionmaker(engine, expire_on_commit=False)
111
+ provider = SQLAlchemyRepositoryProvider(engine=engine, session_factory=sessions)
112
+ provider.register(User, Post)
113
+ await provider.create_all()
114
+
115
+ async with provider.make_uow() as uow:
116
+ user = await uow.users.save(User(name="Edo", email="edo@example.com"))
117
+ print(user.pk)
118
+ ```
119
+
120
+ ### Query integration
121
+
122
+ ```python
123
+ from varco_core import QueryBuilder, QueryParams
124
+
125
+ async with provider.make_uow() as uow:
126
+ # exists() — uses SA identity-map cache, no full ORM load when cached
127
+ if await uow.posts.exists(post_id):
128
+ ...
129
+
130
+ # stream_by_query() — server-side cursor, constant memory regardless of result size
131
+ params = QueryParams(node=QueryBuilder().eq("active", True).build())
132
+ async for post in uow.posts.stream_by_query(params):
133
+ await process(post)
134
+ ```
135
+
136
+ ### Alembic integration
137
+
138
+ ```python
139
+ # alembic/env.py
140
+ from varco_sa import get_target_metadata
141
+ from myapp.models import User, Post
142
+
143
+ target_metadata = get_target_metadata(User, Post)
144
+ ```
145
+
146
+ Preview the DDL before running a migration:
147
+
148
+ ```python
149
+ from varco_sa import print_create_ddl
150
+
151
+ print(print_create_ddl(User, Post, dialect="postgresql"))
152
+ ```
153
+
154
+ ### Schema Guard — detect drift
155
+
156
+ ```python
157
+ from varco_sa import SchemaGuard
158
+
159
+ guard = SchemaGuard(engine, User, Post)
160
+ differences = await guard.check()
161
+ if differences:
162
+ print("Schema drift detected:", differences)
163
+ ```
164
+
165
+ ### Access the generated SA model (escape hatch)
166
+
167
+ ```python
168
+ from varco_sa import SAModelRegistry
169
+ from sqlalchemy.orm import relationship
170
+
171
+ UserORM = SAModelRegistry.get(User)
172
+ UserORM.posts = relationship("PostORM", back_populates="author")
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Related packages
178
+
179
+ | Package | Description |
180
+ |---|---|
181
+ | [`varco-core`](https://pypi.org/project/varco-core/) | Domain model, service layer, query AST, JWT — required dependency |
182
+ | [`varco-beanie`](https://pypi.org/project/varco-beanie/) | Beanie / Motor MongoDB backend (alternative to this package) |
183
+
184
+ ---
185
+
186
+ ## Links
187
+
188
+ - **Repository**: https://github.com/edoardoscarpaci/varco
189
+ - **Full docs**: https://github.com/edoardoscarpaci/varco#sqlalchemy-backend
190
+ - **Issue tracker**: https://github.com/edoardoscarpaci/varco/issues
191
+
@@ -0,0 +1,163 @@
1
+ # varco-sa
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/varco-sa)](https://pypi.org/project/varco-sa/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/varco-sa)](https://pypi.org/project/varco-sa/)
5
+ [![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/edoardoscarpaci/varco/blob/main/LICENSE)
6
+ [![GitHub](https://img.shields.io/badge/GitHub-edoardoscarpaci%2Fvarco-blue?logo=github)](https://github.com/edoardoscarpaci/varco)
7
+
8
+ SQLAlchemy async backend for **varco**.
9
+
10
+ Generates SQLAlchemy ORM classes at runtime from your `DomainModel` subclasses — no hand-written ORM models needed. Requires [`varco-core`](https://pypi.org/project/varco-core/).
11
+
12
+ ---
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ pip install varco-sa
18
+
19
+ # With PostgreSQL async driver:
20
+ pip install "varco-sa[postgresql]"
21
+
22
+ # With SQLite (tests / local dev):
23
+ pip install "varco-sa[sqlite]"
24
+ ```
25
+
26
+ ---
27
+
28
+ ## Features
29
+
30
+ - **Zero-boilerplate ORM** — `SAModelFactory` generates `DeclarativeBase` subclasses at runtime; no duplication between domain and ORM layers
31
+ - **Full async repository** — `AsyncSQLAlchemyRepository` implements `AsyncRepository` (CRUD, `exists()`, `stream_by_query()` with server-side cursor)
32
+ - **Unit of Work** — `SQLAlchemyUnitOfWork` manages `AsyncSession` lifecycle and atomic commits
33
+ - **One-liner bootstrap** — `SAFastrestApp` + `SAConfig` wire engine, session factory, ORM generation, and table creation
34
+ - **Alembic integration** — `get_target_metadata()` and `print_create_ddl()` helpers for migration scripts
35
+ - **Schema Guard** — `SchemaGuard` detects drift between ORM metadata and the live database schema
36
+ - **Query integration** — accepts `varco-core` `QueryParams` / `QueryBuilder` AST natively; translates to SQLAlchemy `where()` clauses
37
+
38
+ ---
39
+
40
+ ## What's in the package
41
+
42
+ | Module | Purpose |
43
+ |---|---|
44
+ | `factory.py` | `SAModelFactory` — generates `DeclarativeBase` subclasses at runtime; `SAModelRegistry` — escape hatch |
45
+ | `repository.py` | `AsyncSQLAlchemyRepository` — `AsyncSession`-backed CRUD + `exists()` + `stream_by_query()` |
46
+ | `uow.py` | `SQLAlchemyUnitOfWork` — session lifecycle + atomic commits |
47
+ | `provider.py` | `SQLAlchemyRepositoryProvider` — wires factory + repos + UoW |
48
+ | `bootstrap.py` | `SAConfig`, `SAFastrestApp` — one-liner app setup |
49
+ | `alembic_helpers.py` | `get_target_metadata`, `print_create_ddl` — Alembic integration |
50
+ | `schema_guard.py` | `SchemaGuard` — drift detection between ORM metadata and live DB |
51
+
52
+ ---
53
+
54
+ ## Quick start
55
+
56
+ ### Bootstrap (one-liner)
57
+
58
+ ```python
59
+ from sqlalchemy.ext.asyncio import create_async_engine
60
+ from sqlalchemy.orm import DeclarativeBase
61
+ from varco_sa import SAConfig, SAFastrestApp
62
+
63
+ class Base(DeclarativeBase): pass
64
+
65
+ engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/mydb")
66
+
67
+ app = SAFastrestApp(SAConfig(
68
+ engine=engine,
69
+ base=Base,
70
+ entity_classes=(User, Post),
71
+ ))
72
+
73
+ await app.create_all() # CREATE TABLE IF NOT EXISTS ...
74
+ uow_provider = app.uow_provider # ready to inject as IUoWProvider
75
+ ```
76
+
77
+ ### Manual setup
78
+
79
+ ```python
80
+ from sqlalchemy.ext.asyncio import async_sessionmaker
81
+ from varco_sa import SQLAlchemyRepositoryProvider
82
+
83
+ sessions = async_sessionmaker(engine, expire_on_commit=False)
84
+ provider = SQLAlchemyRepositoryProvider(engine=engine, session_factory=sessions)
85
+ provider.register(User, Post)
86
+ await provider.create_all()
87
+
88
+ async with provider.make_uow() as uow:
89
+ user = await uow.users.save(User(name="Edo", email="edo@example.com"))
90
+ print(user.pk)
91
+ ```
92
+
93
+ ### Query integration
94
+
95
+ ```python
96
+ from varco_core import QueryBuilder, QueryParams
97
+
98
+ async with provider.make_uow() as uow:
99
+ # exists() — uses SA identity-map cache, no full ORM load when cached
100
+ if await uow.posts.exists(post_id):
101
+ ...
102
+
103
+ # stream_by_query() — server-side cursor, constant memory regardless of result size
104
+ params = QueryParams(node=QueryBuilder().eq("active", True).build())
105
+ async for post in uow.posts.stream_by_query(params):
106
+ await process(post)
107
+ ```
108
+
109
+ ### Alembic integration
110
+
111
+ ```python
112
+ # alembic/env.py
113
+ from varco_sa import get_target_metadata
114
+ from myapp.models import User, Post
115
+
116
+ target_metadata = get_target_metadata(User, Post)
117
+ ```
118
+
119
+ Preview the DDL before running a migration:
120
+
121
+ ```python
122
+ from varco_sa import print_create_ddl
123
+
124
+ print(print_create_ddl(User, Post, dialect="postgresql"))
125
+ ```
126
+
127
+ ### Schema Guard — detect drift
128
+
129
+ ```python
130
+ from varco_sa import SchemaGuard
131
+
132
+ guard = SchemaGuard(engine, User, Post)
133
+ differences = await guard.check()
134
+ if differences:
135
+ print("Schema drift detected:", differences)
136
+ ```
137
+
138
+ ### Access the generated SA model (escape hatch)
139
+
140
+ ```python
141
+ from varco_sa import SAModelRegistry
142
+ from sqlalchemy.orm import relationship
143
+
144
+ UserORM = SAModelRegistry.get(User)
145
+ UserORM.posts = relationship("PostORM", back_populates="author")
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Related packages
151
+
152
+ | Package | Description |
153
+ |---|---|
154
+ | [`varco-core`](https://pypi.org/project/varco-core/) | Domain model, service layer, query AST, JWT — required dependency |
155
+ | [`varco-beanie`](https://pypi.org/project/varco-beanie/) | Beanie / Motor MongoDB backend (alternative to this package) |
156
+
157
+ ---
158
+
159
+ ## Links
160
+
161
+ - **Repository**: https://github.com/edoardoscarpaci/varco
162
+ - **Full docs**: https://github.com/edoardoscarpaci/varco#sqlalchemy-backend
163
+ - **Issue tracker**: https://github.com/edoardoscarpaci/varco/issues
@@ -0,0 +1,49 @@
1
+ [tool.poetry]
2
+ name = "varco-sa"
3
+ version = "0.0.1"
4
+ description = "SQLAlchemy async backend for varco — runtime ORM generation, repository, schema guard, and Alembic helpers"
5
+ authors = ["edoardo.scarpaci <edoardo.scarpaci@gmail.com>"]
6
+ readme = "README.md"
7
+ license = "Apache-2.0"
8
+ homepage = "https://github.com/edoardoscarpaci/varco"
9
+ repository = "https://github.com/edoardoscarpaci/varco"
10
+ documentation = "https://github.com/edoardoscarpaci/varco#sqlalchemy-backend"
11
+ keywords = ["fastapi", "sqlalchemy", "async", "domain-model", "repository", "alembic", "orm", "schema-guard"]
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Intended Audience :: Developers",
15
+ "License :: OSI Approved :: Apache Software License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Topic :: Software Development :: Libraries :: Application Frameworks",
19
+ "Topic :: Database",
20
+ "Framework :: FastAPI",
21
+ "Typing :: Typed",
22
+ ]
23
+ packages = [{include = "varco_sa"}]
24
+
25
+ [tool.poetry.dependencies]
26
+ python = ">=3.12"
27
+ # Path dependency — installs varco_core in editable mode from the monorepo.
28
+ # Changes to varco_core are immediately visible without reinstalling.
29
+ varco-core = ">=0.0.1"
30
+ sqlalchemy = {version = ">=2.0", extras = ["asyncio"]}
31
+
32
+ [tool.poetry.group.postgresql.dependencies]
33
+ # Install with: poetry install --with postgresql
34
+ asyncpg = ">=0.29"
35
+
36
+ [tool.poetry.group.dev.dependencies]
37
+ # aiosqlite is included here (not just sqlite group) so tests run without
38
+ # needing a separate --with sqlite flag during local development.
39
+ pytest = ">=8.0"
40
+ pytest-asyncio = ">=0.24"
41
+ aiosqlite = ">=0.20"
42
+
43
+ [build-system]
44
+ requires = ["poetry-core>=2.0.0,<3.0.0", "poetry-monorepo-dependency-plugin"]
45
+ build-backend = "poetry.core.masonry.api"
46
+
47
+ [tool.pytest.ini_options]
48
+ asyncio_mode = "auto"
49
+ testpaths = ["tests"]
@@ -0,0 +1,78 @@
1
+ """
2
+ varco_sa
3
+ ============
4
+ SQLAlchemy async backend for varco.
5
+
6
+ All stable public symbols are importable directly from ``varco_sa``::
7
+
8
+ from varco_sa import SQLAlchemyRepositoryProvider, SAModelRegistry
9
+ from varco_sa import BaseDatabaseModel, IndexedDatabaseModel
10
+ from varco_sa import SQLAlchemyQueryApplicator
11
+
12
+ # Query usage
13
+ from varco_core import QueryBuilder, QueryParams
14
+ from varco_sa import SQLAlchemyRepositoryProvider
15
+
16
+ provider = SQLAlchemyRepositoryProvider(base=Base, session_factory=async_session)
17
+ provider.register(User, Post)
18
+
19
+ async with provider.make_uow() as uow:
20
+ active_users = await uow.users.find_by_query(
21
+ QueryParams(
22
+ node=QueryBuilder().eq("active", True).build(),
23
+ limit=20,
24
+ )
25
+ )
26
+
27
+ Sub-package layout
28
+ ------------------
29
+ varco_sa/
30
+ ├── factory.py — SAModelFactory (DomainModel → SA ORM class at runtime)
31
+ │ SAModelRegistry (process-level ORM class registry)
32
+ ├── provider.py — SQLAlchemyRepositoryProvider
33
+ ├── repository.py — AsyncSQLAlchemyRepository (CRUD + find_by_query + count)
34
+ ├── uow.py — SQLAlchemyUnitOfWork
35
+ └── models.py — BaseDatabaseModel
36
+ """
37
+
38
+ from __future__ import annotations
39
+
40
+ from varco_sa.alembic_helpers import get_target_metadata, print_create_ddl
41
+ from varco_sa.bootstrap import SAConfig, SAFastrestApp
42
+ from varco_sa.factory import SAModelFactory, SAModelRegistry
43
+ from varco_sa.models import BaseDatabaseModel
44
+ from varco_sa.provider import SQLAlchemyRepositoryProvider
45
+ from varco_sa.repository import AsyncSQLAlchemyRepository
46
+ from varco_sa.schema_guard import SchemaGuard, SchemaDrift, SchemaDriftReport
47
+ from varco_sa.uow import SQLAlchemyUnitOfWork
48
+
49
+ # SA-specific applicator is in varco_core (no session; pure SA expressions)
50
+ from varco_core.query.applicator.sqlalchemy import SQLAlchemyQueryApplicator
51
+ from varco_sa.type_coercion import registry_from_sa_model
52
+
53
+ __all__ = [
54
+ # ── Factory + registry ─────────────────────────────────────────────────────
55
+ "SAModelFactory",
56
+ "SAModelRegistry",
57
+ # ── Repository + UoW ──────────────────────────────────────────────────────
58
+ "AsyncSQLAlchemyRepository",
59
+ "SQLAlchemyUnitOfWork",
60
+ # ── Provider ──────────────────────────────────────────────────────────────
61
+ "SQLAlchemyRepositoryProvider",
62
+ # ── Base models ───────────────────────────────────────────────────────────
63
+ "BaseDatabaseModel",
64
+ # ── Query applicator ──────────────────────────────────────────────────────
65
+ "SQLAlchemyQueryApplicator",
66
+ # ── Schema guard ──────────────────────────────────────────────────────────
67
+ "SchemaGuard",
68
+ "SchemaDrift",
69
+ "SchemaDriftReport",
70
+ # ── Type coercion ─────────────────────────────────────────────────────────
71
+ "registry_from_sa_model",
72
+ # ── Alembic helpers ───────────────────────────────────────────────────────
73
+ "get_target_metadata",
74
+ "print_create_ddl",
75
+ # ── Bootstrap ─────────────────────────────────────────────────────────────
76
+ "SAConfig",
77
+ "SAFastrestApp",
78
+ ]