hexastack-db 0.0.0__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.
Potentially problematic release.
This version of hexastack-db might be problematic. Click here for more details.
- hexastack_db-0.0.0/PKG-INFO +225 -0
- hexastack_db-0.0.0/README.md +197 -0
- hexastack_db-0.0.0/pyproject.toml +65 -0
- hexastack_db-0.0.0/pyproject.toml.orig +68 -0
- hexastack_db-0.0.0/src/hexastack_db/__init__.py +7 -0
- hexastack_db-0.0.0/src/hexastack_db/adapters/__init__.py +23 -0
- hexastack_db-0.0.0/src/hexastack_db/adapters/repository.py +420 -0
- hexastack_db-0.0.0/src/hexastack_db/adapters/unit_of_work.py +184 -0
- hexastack_db-0.0.0/src/hexastack_db/adapters/vector.py +267 -0
- hexastack_db-0.0.0/src/hexastack_db/domain/__init__.py +13 -0
- hexastack_db-0.0.0/src/hexastack_db/domain/exceptions.py +64 -0
- hexastack_db-0.0.0/src/hexastack_db/infra/__init__.py +59 -0
- hexastack_db-0.0.0/src/hexastack_db/infra/bootstrap.py +209 -0
- hexastack_db-0.0.0/src/hexastack_db/infra/config.py +182 -0
- hexastack_db-0.0.0/src/hexastack_db/infra/engine.py +142 -0
- hexastack_db-0.0.0/src/hexastack_db/infra/migrations.py +309 -0
- hexastack_db-0.0.0/src/hexastack_db/infra/mixins.py +63 -0
- hexastack_db-0.0.0/src/hexastack_db/infra/registries/__init__.py +0 -0
- hexastack_db-0.0.0/src/hexastack_db/infra/registries/metadata.py +53 -0
- hexastack_db-0.0.0/src/hexastack_db/py.typed +1 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: hexastack-db
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: SQLAlchemy database integration, repositories, Unit of Work, and bootstrap for Hexastack
|
|
5
|
+
Author: Richard West
|
|
6
|
+
Author-email: Richard West <dopplereffect.us@gmail.com>
|
|
7
|
+
Requires-Dist: hexastack-core
|
|
8
|
+
Requires-Dist: sqlalchemy>=2.0.38
|
|
9
|
+
Requires-Dist: aiosqlite>=0.20.0 ; extra == 'all'
|
|
10
|
+
Requires-Dist: alembic>=1.13.0 ; extra == 'all'
|
|
11
|
+
Requires-Dist: asyncpg>=0.30.0 ; extra == 'all'
|
|
12
|
+
Requires-Dist: pgvector>=0.3.0 ; extra == 'all'
|
|
13
|
+
Requires-Dist: psycopg[binary]>=3.2.0 ; extra == 'all'
|
|
14
|
+
Requires-Dist: alembic>=1.13.0 ; extra == 'migrations'
|
|
15
|
+
Requires-Dist: asyncpg>=0.30.0 ; extra == 'pgvector'
|
|
16
|
+
Requires-Dist: pgvector>=0.3.0 ; extra == 'pgvector'
|
|
17
|
+
Requires-Dist: psycopg[binary]>=3.2.0 ; extra == 'pgvector'
|
|
18
|
+
Requires-Dist: asyncpg>=0.30.0 ; extra == 'postgresql'
|
|
19
|
+
Requires-Dist: psycopg[binary]>=3.2.0 ; extra == 'postgresql'
|
|
20
|
+
Requires-Dist: aiosqlite>=0.20.0 ; extra == 'sqlite'
|
|
21
|
+
Requires-Python: >=3.13
|
|
22
|
+
Provides-Extra: all
|
|
23
|
+
Provides-Extra: migrations
|
|
24
|
+
Provides-Extra: pgvector
|
|
25
|
+
Provides-Extra: postgresql
|
|
26
|
+
Provides-Extra: sqlite
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# hexastack-db
|
|
30
|
+
|
|
31
|
+
> SQLAlchemy 2.0+ persistence layer, generic repositories, Unit of Work, declarative mixins, and Alembic migrations for Hexastack.
|
|
32
|
+
|
|
33
|
+
[](https://www.python.org/downloads/)
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 1. Overview & Capabilities
|
|
38
|
+
|
|
39
|
+
`hexastack-db` provides a robust, decoupled database layer supporting both synchronous and asynchronous workflows:
|
|
40
|
+
|
|
41
|
+
- **Generic Repositories**: `SqlAlchemyRepository[T, ID]` and `AsyncSqlAlchemyRepository[T, ID]` implementing `Repository[E, ID]` and `AsyncRepository[E, ID]`.
|
|
42
|
+
- **Unit of Work**: `SqlAlchemyUnitOfWork` and `AsyncSqlAlchemyUnitOfWork` providing contextual transaction boundaries (`commit()`, `rollback()`).
|
|
43
|
+
- **Declarative Base & Mixins**:
|
|
44
|
+
- `HexastackBase`: Shared `DeclarativeBase` for unified metadata management across applications and migration autogen.
|
|
45
|
+
- `UuidPrimaryKeyMixin`: Portable Python-side `uuid4()` stored as a 36-character string primary key.
|
|
46
|
+
- `TimestampMixin`: Automatic UTC `created_at` and `updated_at` timestamps.
|
|
47
|
+
- **Alembic Migration Engine**: Programmatic migration execution (`upgrade`, `downgrade`, `revision`, `current`, `history`, `stamp`) and CLI integration without requiring manual `alembic.ini` authoring.
|
|
48
|
+
- **Auto Table Creation**: Schema discovery and `create_all()` execution on bootstrap via `register_metadata()`.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 2. Package Anatomy & Key Components
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
hexastack_db/
|
|
56
|
+
├── domain/ # DatabaseError, EntityNotFoundError, UniqueConstraintViolationError
|
|
57
|
+
├── adapters/ # SqlAlchemyRepository, AsyncSqlAlchemyRepository, SqlAlchemyUnitOfWork, AsyncSqlAlchemyUnitOfWork
|
|
58
|
+
└── infra/
|
|
59
|
+
├── bootstrap.py # DatabaseBootstrapper (order=15)
|
|
60
|
+
├── config.py # HexastackDatabaseConfig
|
|
61
|
+
├── engine.py # Engine and sessionmaker factory functions
|
|
62
|
+
├── mixins.py # HexastackBase, UuidPrimaryKeyMixin, TimestampMixin
|
|
63
|
+
├── migrations.py# Alembic migration helpers
|
|
64
|
+
└── registries/ # metadata.py (register_metadata, get_registered_metadata)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Key Exports
|
|
68
|
+
|
|
69
|
+
| Category | Exports |
|
|
70
|
+
|---|---|
|
|
71
|
+
| **Bootstrap** | `DatabaseBootstrapper` (order=15), `HexastackDatabaseConfig` |
|
|
72
|
+
| **Migrations** | `init_migrations`, `get_alembic_config`, `run_upgrade`, `run_downgrade`, `run_revision`, `run_current`, `run_history`, `stamp` |
|
|
73
|
+
| **Mixins & Base** | `HexastackBase`, `UuidPrimaryKeyMixin`, `TimestampMixin` |
|
|
74
|
+
| **Registries** | `register_metadata`, `get_registered_metadata`, `clear_metadata_registry` |
|
|
75
|
+
| **Repositories** | `SqlAlchemyRepository`, `AsyncSqlAlchemyRepository` |
|
|
76
|
+
| **Unit of Work** | `SqlAlchemyUnitOfWork`, `AsyncSqlAlchemyUnitOfWork` |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 3. Monorepo & Sibling Relationships
|
|
81
|
+
|
|
82
|
+
```mermaid
|
|
83
|
+
graph TD
|
|
84
|
+
subgraph SiblingConsumers ["Sibling Consumers"]
|
|
85
|
+
CQRS["hexastack-cqrs (UnitOfWorkMiddleware)"]
|
|
86
|
+
FASTAPI["hexastack-fastapi (DbSessionMiddleware)"]
|
|
87
|
+
CLI["hexastack (hexastack db <cmd>)"]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
subgraph DatabasePackage ["hexastack-db"]
|
|
91
|
+
BOOT["DatabaseBootstrapper (order=15)"]
|
|
92
|
+
UOW["SqlAlchemyUnitOfWork / AsyncSqlAlchemyUnitOfWork"]
|
|
93
|
+
ENG["Engine & sessionmaker"]
|
|
94
|
+
MIGR["Alembic Migration Engine"]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
subgraph CoreContracts ["hexastack-core"]
|
|
98
|
+
UOW_PORT["UnitOfWorkPort"]
|
|
99
|
+
REPO_PORT["RepositoryPort"]
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
BOOT --> UOW
|
|
103
|
+
BOOT --> ENG
|
|
104
|
+
UOW -->|implements| UOW_PORT
|
|
105
|
+
|
|
106
|
+
CQRS -. consumes UnitOfWorkPort from DI .-> UOW
|
|
107
|
+
FASTAPI -. consumes sessionmaker from DI .-> ENG
|
|
108
|
+
CLI -. invokes migration helpers .-> MIGR
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Explicit Dependencies (Direct)
|
|
112
|
+
- `hexastack-core`: Core ports (`UnitOfWorkPort`, `Repository`), exception types, and DI container.
|
|
113
|
+
- `sqlalchemy>=2.0.38`: Core ORM and SQL toolkit.
|
|
114
|
+
|
|
115
|
+
### Implied / Behavioral Relationships (DI-Mediated)
|
|
116
|
+
- **Unit of Work Binding**: Binds `UnitOfWorkPort` into the DI container at `order=15` (before CQRS `order=20`), allowing `UnitOfWorkMiddleware` to manage transactions automatically.
|
|
117
|
+
- **Session Injection**: Injects `sessionmaker` / `async_sessionmaker` into DI, which `hexastack-fastapi` resolves in `DbSessionMiddleware` without requiring a direct package dependency.
|
|
118
|
+
- **Migration CLI Integration**: The `hexastack` umbrella package exposes CLI subcommands (`hexastack db init/upgrade/revision/...`) backed by `hexastack_db.infra.migrations`.
|
|
119
|
+
|
|
120
|
+
### Optional Integrations (Extras)
|
|
121
|
+
- `[sqlite]`: Installs `aiosqlite>=0.20.0` for async SQLite support.
|
|
122
|
+
- `[postgresql]`: Installs `asyncpg>=0.30.0` and `psycopg[binary]>=3.2.0`.
|
|
123
|
+
- `[pgvector]`: Installs `pgvector>=0.3.0` and PostgreSQL drivers for VectorStorePort support.
|
|
124
|
+
- `[migrations]`: Installs `alembic>=1.13.0` for migration commands and autogeneration.
|
|
125
|
+
- `[all]`: Installs all drivers, pgvector, and Alembic.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 4. Installation
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Standalone install with SQLite async support
|
|
133
|
+
pip install "hexastack-db[sqlite]"
|
|
134
|
+
|
|
135
|
+
# Standalone with PostgreSQL and Alembic migrations
|
|
136
|
+
pip install "hexastack-db[postgresql,migrations]"
|
|
137
|
+
|
|
138
|
+
# With PostgreSQL vector search (pgvector)
|
|
139
|
+
pip install "hexastack-db[pgvector]"
|
|
140
|
+
|
|
141
|
+
# Via umbrella package
|
|
142
|
+
pip install "hexastack[db]"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 5. Configuration Reference
|
|
148
|
+
|
|
149
|
+
```toml
|
|
150
|
+
[hexastack.db]
|
|
151
|
+
# Global Settings
|
|
152
|
+
url = "sqlite:///app.db" # "postgresql+asyncpg://user:pass@localhost:5432/dbname"
|
|
153
|
+
async_mode = false # Set to true for async engine & sessions
|
|
154
|
+
auto_create_tables = false # Runs create_all() on registered metadata at bootstrap
|
|
155
|
+
echo = false # Enables raw SQLAlchemy SQL logging
|
|
156
|
+
pool_size = 5
|
|
157
|
+
max_overflow = 10
|
|
158
|
+
pool_timeout = 30
|
|
159
|
+
pool_recycle = 1800
|
|
160
|
+
|
|
161
|
+
# SQLite-Specific Dialect Settings
|
|
162
|
+
[hexastack.db.sqlite]
|
|
163
|
+
foreign_keys = true # PRAGMA foreign_keys = ON
|
|
164
|
+
journal_mode = "WAL" # PRAGMA journal_mode = WAL
|
|
165
|
+
busy_timeout_ms = 5000 # PRAGMA busy_timeout = 5000
|
|
166
|
+
synchronous = "NORMAL"
|
|
167
|
+
|
|
168
|
+
# PostgreSQL-Specific Dialect Settings
|
|
169
|
+
[hexastack.db.postgres]
|
|
170
|
+
search_path = "public"
|
|
171
|
+
ssl_mode = "require"
|
|
172
|
+
server_side_cursors = false
|
|
173
|
+
|
|
174
|
+
# PostgreSQL pgvector Configuration
|
|
175
|
+
[hexastack.db.vector]
|
|
176
|
+
enabled = false # Auto-binds VectorStorePort in DI container
|
|
177
|
+
table_name = "hexastack_vectors"
|
|
178
|
+
dimension = 1536
|
|
179
|
+
distance_strategy = "cosine" # "cosine", "l2", "inner_product"
|
|
180
|
+
index_type = "hnsw" # "hnsw", "ivfflat", "none"
|
|
181
|
+
m = 16
|
|
182
|
+
ef_construction = 64
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 6. Quickstart Example
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
|
191
|
+
from hexastack_core.infra.bootstrap import bootstrap
|
|
192
|
+
from hexastack_core.ports.unit_of_work import UnitOfWorkPort
|
|
193
|
+
from hexastack_db.infra.mixins import HexastackBase, UuidPrimaryKeyMixin, TimestampMixin
|
|
194
|
+
from hexastack_db.infra.registries.metadata import register_metadata
|
|
195
|
+
from hexastack_db.adapters.repository import SqlAlchemyRepository
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
# 1. Define Model
|
|
199
|
+
class UserRecord(UuidPrimaryKeyMixin, TimestampMixin, HexastackBase):
|
|
200
|
+
__tablename__ = "users"
|
|
201
|
+
email: Mapped[str] = mapped_column(unique=True)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
register_metadata(HexastackBase.metadata)
|
|
205
|
+
|
|
206
|
+
# 2. Bootstrap with auto-table creation
|
|
207
|
+
runtime = bootstrap(
|
|
208
|
+
config_overrides={
|
|
209
|
+
"db": {
|
|
210
|
+
"url": "sqlite:///:memory:",
|
|
211
|
+
"auto_create_tables": True,
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
# 3. Use Unit of Work and Repository
|
|
217
|
+
uow = runtime.container.get(UnitOfWorkPort)
|
|
218
|
+
with uow:
|
|
219
|
+
repo = SqlAlchemyRepository(session=uow.session, model_cls=UserRecord)
|
|
220
|
+
user = UserRecord(email="alice@hexastack.dev")
|
|
221
|
+
repo.add(user)
|
|
222
|
+
uow.commit()
|
|
223
|
+
|
|
224
|
+
print(f"Created user {user.id} at {user.created_at}")
|
|
225
|
+
```
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# hexastack-db
|
|
2
|
+
|
|
3
|
+
> SQLAlchemy 2.0+ persistence layer, generic repositories, Unit of Work, declarative mixins, and Alembic migrations for Hexastack.
|
|
4
|
+
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Overview & Capabilities
|
|
10
|
+
|
|
11
|
+
`hexastack-db` provides a robust, decoupled database layer supporting both synchronous and asynchronous workflows:
|
|
12
|
+
|
|
13
|
+
- **Generic Repositories**: `SqlAlchemyRepository[T, ID]` and `AsyncSqlAlchemyRepository[T, ID]` implementing `Repository[E, ID]` and `AsyncRepository[E, ID]`.
|
|
14
|
+
- **Unit of Work**: `SqlAlchemyUnitOfWork` and `AsyncSqlAlchemyUnitOfWork` providing contextual transaction boundaries (`commit()`, `rollback()`).
|
|
15
|
+
- **Declarative Base & Mixins**:
|
|
16
|
+
- `HexastackBase`: Shared `DeclarativeBase` for unified metadata management across applications and migration autogen.
|
|
17
|
+
- `UuidPrimaryKeyMixin`: Portable Python-side `uuid4()` stored as a 36-character string primary key.
|
|
18
|
+
- `TimestampMixin`: Automatic UTC `created_at` and `updated_at` timestamps.
|
|
19
|
+
- **Alembic Migration Engine**: Programmatic migration execution (`upgrade`, `downgrade`, `revision`, `current`, `history`, `stamp`) and CLI integration without requiring manual `alembic.ini` authoring.
|
|
20
|
+
- **Auto Table Creation**: Schema discovery and `create_all()` execution on bootstrap via `register_metadata()`.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. Package Anatomy & Key Components
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
hexastack_db/
|
|
28
|
+
├── domain/ # DatabaseError, EntityNotFoundError, UniqueConstraintViolationError
|
|
29
|
+
├── adapters/ # SqlAlchemyRepository, AsyncSqlAlchemyRepository, SqlAlchemyUnitOfWork, AsyncSqlAlchemyUnitOfWork
|
|
30
|
+
└── infra/
|
|
31
|
+
├── bootstrap.py # DatabaseBootstrapper (order=15)
|
|
32
|
+
├── config.py # HexastackDatabaseConfig
|
|
33
|
+
├── engine.py # Engine and sessionmaker factory functions
|
|
34
|
+
├── mixins.py # HexastackBase, UuidPrimaryKeyMixin, TimestampMixin
|
|
35
|
+
├── migrations.py# Alembic migration helpers
|
|
36
|
+
└── registries/ # metadata.py (register_metadata, get_registered_metadata)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Key Exports
|
|
40
|
+
|
|
41
|
+
| Category | Exports |
|
|
42
|
+
|---|---|
|
|
43
|
+
| **Bootstrap** | `DatabaseBootstrapper` (order=15), `HexastackDatabaseConfig` |
|
|
44
|
+
| **Migrations** | `init_migrations`, `get_alembic_config`, `run_upgrade`, `run_downgrade`, `run_revision`, `run_current`, `run_history`, `stamp` |
|
|
45
|
+
| **Mixins & Base** | `HexastackBase`, `UuidPrimaryKeyMixin`, `TimestampMixin` |
|
|
46
|
+
| **Registries** | `register_metadata`, `get_registered_metadata`, `clear_metadata_registry` |
|
|
47
|
+
| **Repositories** | `SqlAlchemyRepository`, `AsyncSqlAlchemyRepository` |
|
|
48
|
+
| **Unit of Work** | `SqlAlchemyUnitOfWork`, `AsyncSqlAlchemyUnitOfWork` |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 3. Monorepo & Sibling Relationships
|
|
53
|
+
|
|
54
|
+
```mermaid
|
|
55
|
+
graph TD
|
|
56
|
+
subgraph SiblingConsumers ["Sibling Consumers"]
|
|
57
|
+
CQRS["hexastack-cqrs (UnitOfWorkMiddleware)"]
|
|
58
|
+
FASTAPI["hexastack-fastapi (DbSessionMiddleware)"]
|
|
59
|
+
CLI["hexastack (hexastack db <cmd>)"]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
subgraph DatabasePackage ["hexastack-db"]
|
|
63
|
+
BOOT["DatabaseBootstrapper (order=15)"]
|
|
64
|
+
UOW["SqlAlchemyUnitOfWork / AsyncSqlAlchemyUnitOfWork"]
|
|
65
|
+
ENG["Engine & sessionmaker"]
|
|
66
|
+
MIGR["Alembic Migration Engine"]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
subgraph CoreContracts ["hexastack-core"]
|
|
70
|
+
UOW_PORT["UnitOfWorkPort"]
|
|
71
|
+
REPO_PORT["RepositoryPort"]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
BOOT --> UOW
|
|
75
|
+
BOOT --> ENG
|
|
76
|
+
UOW -->|implements| UOW_PORT
|
|
77
|
+
|
|
78
|
+
CQRS -. consumes UnitOfWorkPort from DI .-> UOW
|
|
79
|
+
FASTAPI -. consumes sessionmaker from DI .-> ENG
|
|
80
|
+
CLI -. invokes migration helpers .-> MIGR
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Explicit Dependencies (Direct)
|
|
84
|
+
- `hexastack-core`: Core ports (`UnitOfWorkPort`, `Repository`), exception types, and DI container.
|
|
85
|
+
- `sqlalchemy>=2.0.38`: Core ORM and SQL toolkit.
|
|
86
|
+
|
|
87
|
+
### Implied / Behavioral Relationships (DI-Mediated)
|
|
88
|
+
- **Unit of Work Binding**: Binds `UnitOfWorkPort` into the DI container at `order=15` (before CQRS `order=20`), allowing `UnitOfWorkMiddleware` to manage transactions automatically.
|
|
89
|
+
- **Session Injection**: Injects `sessionmaker` / `async_sessionmaker` into DI, which `hexastack-fastapi` resolves in `DbSessionMiddleware` without requiring a direct package dependency.
|
|
90
|
+
- **Migration CLI Integration**: The `hexastack` umbrella package exposes CLI subcommands (`hexastack db init/upgrade/revision/...`) backed by `hexastack_db.infra.migrations`.
|
|
91
|
+
|
|
92
|
+
### Optional Integrations (Extras)
|
|
93
|
+
- `[sqlite]`: Installs `aiosqlite>=0.20.0` for async SQLite support.
|
|
94
|
+
- `[postgresql]`: Installs `asyncpg>=0.30.0` and `psycopg[binary]>=3.2.0`.
|
|
95
|
+
- `[pgvector]`: Installs `pgvector>=0.3.0` and PostgreSQL drivers for VectorStorePort support.
|
|
96
|
+
- `[migrations]`: Installs `alembic>=1.13.0` for migration commands and autogeneration.
|
|
97
|
+
- `[all]`: Installs all drivers, pgvector, and Alembic.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 4. Installation
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Standalone install with SQLite async support
|
|
105
|
+
pip install "hexastack-db[sqlite]"
|
|
106
|
+
|
|
107
|
+
# Standalone with PostgreSQL and Alembic migrations
|
|
108
|
+
pip install "hexastack-db[postgresql,migrations]"
|
|
109
|
+
|
|
110
|
+
# With PostgreSQL vector search (pgvector)
|
|
111
|
+
pip install "hexastack-db[pgvector]"
|
|
112
|
+
|
|
113
|
+
# Via umbrella package
|
|
114
|
+
pip install "hexastack[db]"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 5. Configuration Reference
|
|
120
|
+
|
|
121
|
+
```toml
|
|
122
|
+
[hexastack.db]
|
|
123
|
+
# Global Settings
|
|
124
|
+
url = "sqlite:///app.db" # "postgresql+asyncpg://user:pass@localhost:5432/dbname"
|
|
125
|
+
async_mode = false # Set to true for async engine & sessions
|
|
126
|
+
auto_create_tables = false # Runs create_all() on registered metadata at bootstrap
|
|
127
|
+
echo = false # Enables raw SQLAlchemy SQL logging
|
|
128
|
+
pool_size = 5
|
|
129
|
+
max_overflow = 10
|
|
130
|
+
pool_timeout = 30
|
|
131
|
+
pool_recycle = 1800
|
|
132
|
+
|
|
133
|
+
# SQLite-Specific Dialect Settings
|
|
134
|
+
[hexastack.db.sqlite]
|
|
135
|
+
foreign_keys = true # PRAGMA foreign_keys = ON
|
|
136
|
+
journal_mode = "WAL" # PRAGMA journal_mode = WAL
|
|
137
|
+
busy_timeout_ms = 5000 # PRAGMA busy_timeout = 5000
|
|
138
|
+
synchronous = "NORMAL"
|
|
139
|
+
|
|
140
|
+
# PostgreSQL-Specific Dialect Settings
|
|
141
|
+
[hexastack.db.postgres]
|
|
142
|
+
search_path = "public"
|
|
143
|
+
ssl_mode = "require"
|
|
144
|
+
server_side_cursors = false
|
|
145
|
+
|
|
146
|
+
# PostgreSQL pgvector Configuration
|
|
147
|
+
[hexastack.db.vector]
|
|
148
|
+
enabled = false # Auto-binds VectorStorePort in DI container
|
|
149
|
+
table_name = "hexastack_vectors"
|
|
150
|
+
dimension = 1536
|
|
151
|
+
distance_strategy = "cosine" # "cosine", "l2", "inner_product"
|
|
152
|
+
index_type = "hnsw" # "hnsw", "ivfflat", "none"
|
|
153
|
+
m = 16
|
|
154
|
+
ef_construction = 64
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 6. Quickstart Example
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
|
163
|
+
from hexastack_core.infra.bootstrap import bootstrap
|
|
164
|
+
from hexastack_core.ports.unit_of_work import UnitOfWorkPort
|
|
165
|
+
from hexastack_db.infra.mixins import HexastackBase, UuidPrimaryKeyMixin, TimestampMixin
|
|
166
|
+
from hexastack_db.infra.registries.metadata import register_metadata
|
|
167
|
+
from hexastack_db.adapters.repository import SqlAlchemyRepository
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
# 1. Define Model
|
|
171
|
+
class UserRecord(UuidPrimaryKeyMixin, TimestampMixin, HexastackBase):
|
|
172
|
+
__tablename__ = "users"
|
|
173
|
+
email: Mapped[str] = mapped_column(unique=True)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
register_metadata(HexastackBase.metadata)
|
|
177
|
+
|
|
178
|
+
# 2. Bootstrap with auto-table creation
|
|
179
|
+
runtime = bootstrap(
|
|
180
|
+
config_overrides={
|
|
181
|
+
"db": {
|
|
182
|
+
"url": "sqlite:///:memory:",
|
|
183
|
+
"auto_create_tables": True,
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# 3. Use Unit of Work and Repository
|
|
189
|
+
uow = runtime.container.get(UnitOfWorkPort)
|
|
190
|
+
with uow:
|
|
191
|
+
repo = SqlAlchemyRepository(session=uow.session, model_cls=UserRecord)
|
|
192
|
+
user = UserRecord(email="alice@hexastack.dev")
|
|
193
|
+
repo.add(user)
|
|
194
|
+
uow.commit()
|
|
195
|
+
|
|
196
|
+
print(f"Created user {user.id} at {user.created_at}")
|
|
197
|
+
```
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "hexastack-db"
|
|
3
|
+
version = "0.0.0"
|
|
4
|
+
description = "SQLAlchemy database integration, repositories, Unit of Work, and bootstrap for Hexastack"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"hexastack-core",
|
|
9
|
+
"sqlalchemy>=2.0.38",
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
[[project.authors]]
|
|
13
|
+
name = "Richard West"
|
|
14
|
+
email = "dopplereffect.us@gmail.com"
|
|
15
|
+
|
|
16
|
+
[project.optional-dependencies]
|
|
17
|
+
sqlite = ["aiosqlite>=0.20.0"]
|
|
18
|
+
postgresql = [
|
|
19
|
+
"asyncpg>=0.30.0",
|
|
20
|
+
"psycopg[binary]>=3.2.0",
|
|
21
|
+
]
|
|
22
|
+
pgvector = [
|
|
23
|
+
"asyncpg>=0.30.0",
|
|
24
|
+
"pgvector>=0.3.0",
|
|
25
|
+
"psycopg[binary]>=3.2.0",
|
|
26
|
+
]
|
|
27
|
+
migrations = ["alembic>=1.13.0"]
|
|
28
|
+
all = [
|
|
29
|
+
"aiosqlite>=0.20.0",
|
|
30
|
+
"alembic>=1.13.0",
|
|
31
|
+
"asyncpg>=0.30.0",
|
|
32
|
+
"pgvector>=0.3.0",
|
|
33
|
+
"psycopg[binary]>=3.2.0",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.entry-points."hexastack.bootstrappers"]
|
|
37
|
+
db = "hexastack_db.infra.bootstrap:DatabaseBootstrapper"
|
|
38
|
+
|
|
39
|
+
[build-system]
|
|
40
|
+
requires = ["uv_build>=0.12.3,<0.13.0"]
|
|
41
|
+
build-backend = "uv_build"
|
|
42
|
+
|
|
43
|
+
[tool.uv.sources.hexastack-core]
|
|
44
|
+
workspace = true
|
|
45
|
+
|
|
46
|
+
[tool.importlinter]
|
|
47
|
+
root_packages = ["hexastack_db"]
|
|
48
|
+
|
|
49
|
+
[[tool.importlinter.contracts]]
|
|
50
|
+
name = "Hexagonal architecture layer hierarchy"
|
|
51
|
+
type = "layers"
|
|
52
|
+
containers = ["hexastack_db"]
|
|
53
|
+
layers = [
|
|
54
|
+
"adapters",
|
|
55
|
+
"domain",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[[tool.importlinter.contracts]]
|
|
59
|
+
name = "Forbidden imports for domain"
|
|
60
|
+
type = "forbidden"
|
|
61
|
+
source_modules = ["hexastack_db.domain"]
|
|
62
|
+
forbidden_modules = [
|
|
63
|
+
"hexastack_db.adapters",
|
|
64
|
+
"hexastack_db.infra",
|
|
65
|
+
]
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "hexastack-db"
|
|
3
|
+
version = "0.0.0"
|
|
4
|
+
description = "SQLAlchemy database integration, repositories, Unit of Work, and bootstrap for Hexastack"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Richard West", email = "dopplereffect.us@gmail.com" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.13"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"hexastack-core",
|
|
12
|
+
"sqlalchemy>=2.0.38",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.optional-dependencies]
|
|
16
|
+
sqlite = [
|
|
17
|
+
"aiosqlite>=0.20.0",
|
|
18
|
+
]
|
|
19
|
+
postgresql = [
|
|
20
|
+
"asyncpg>=0.30.0",
|
|
21
|
+
"psycopg[binary]>=3.2.0",
|
|
22
|
+
]
|
|
23
|
+
pgvector = [
|
|
24
|
+
"asyncpg>=0.30.0",
|
|
25
|
+
"pgvector>=0.3.0",
|
|
26
|
+
"psycopg[binary]>=3.2.0",
|
|
27
|
+
]
|
|
28
|
+
migrations = [
|
|
29
|
+
"alembic>=1.13.0",
|
|
30
|
+
]
|
|
31
|
+
all = [
|
|
32
|
+
"aiosqlite>=0.20.0",
|
|
33
|
+
"alembic>=1.13.0",
|
|
34
|
+
"asyncpg>=0.30.0",
|
|
35
|
+
"pgvector>=0.3.0",
|
|
36
|
+
"psycopg[binary]>=3.2.0",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.entry-points."hexastack.bootstrappers"]
|
|
40
|
+
db = "hexastack_db.infra.bootstrap:DatabaseBootstrapper"
|
|
41
|
+
|
|
42
|
+
[build-system]
|
|
43
|
+
requires = ["uv_build>=0.12.3,<0.13.0"]
|
|
44
|
+
build-backend = "uv_build"
|
|
45
|
+
|
|
46
|
+
[tool.uv.sources]
|
|
47
|
+
hexastack-core = { workspace = true }
|
|
48
|
+
|
|
49
|
+
[tool.importlinter]
|
|
50
|
+
root_packages = ["hexastack_db"]
|
|
51
|
+
|
|
52
|
+
[[tool.importlinter.contracts]]
|
|
53
|
+
name = "Hexagonal architecture layer hierarchy"
|
|
54
|
+
type = "layers"
|
|
55
|
+
containers = ["hexastack_db"]
|
|
56
|
+
layers = [
|
|
57
|
+
"adapters",
|
|
58
|
+
"domain",
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
[[tool.importlinter.contracts]]
|
|
62
|
+
name = "Forbidden imports for domain"
|
|
63
|
+
type = "forbidden"
|
|
64
|
+
source_modules = ["hexastack_db.domain"]
|
|
65
|
+
forbidden_modules = [
|
|
66
|
+
"hexastack_db.adapters",
|
|
67
|
+
"hexastack_db.infra",
|
|
68
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from hexastack_db.adapters.repository import (
|
|
2
|
+
AsyncSqlAlchemyRepository,
|
|
3
|
+
SqlAlchemyRepository,
|
|
4
|
+
)
|
|
5
|
+
from hexastack_db.adapters.unit_of_work import (
|
|
6
|
+
AsyncSqlAlchemyUnitOfWork,
|
|
7
|
+
SqlAlchemyUnitOfWork,
|
|
8
|
+
)
|
|
9
|
+
from hexastack_db.adapters.vector import (
|
|
10
|
+
AsyncPgVectorStoreAdapter,
|
|
11
|
+
PgVectorStoreAdapter,
|
|
12
|
+
create_vector_table,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"AsyncPgVectorStoreAdapter",
|
|
17
|
+
"AsyncSqlAlchemyRepository",
|
|
18
|
+
"AsyncSqlAlchemyUnitOfWork",
|
|
19
|
+
"create_vector_table",
|
|
20
|
+
"PgVectorStoreAdapter",
|
|
21
|
+
"SqlAlchemyRepository",
|
|
22
|
+
"SqlAlchemyUnitOfWork",
|
|
23
|
+
]
|