nextorm 0.1.0__py3-none-any.whl
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.
- nextorm/__init__.py +317 -0
- nextorm/async_database.py +1285 -0
- nextorm/collection.py +505 -0
- nextorm/database.py +1109 -0
- nextorm/debug.py +167 -0
- nextorm/entity.py +1146 -0
- nextorm/exceptions.py +100 -0
- nextorm/expr.py +139 -0
- nextorm/fields.py +562 -0
- nextorm/generators.py +630 -0
- nextorm/migrations/__init__.py +27 -0
- nextorm/migrations/cli.py +110 -0
- nextorm/migrations/core.py +427 -0
- nextorm/pool.py +258 -0
- nextorm/providers/__init__.py +67 -0
- nextorm/providers/base.py +354 -0
- nextorm/providers/mariadb.py +319 -0
- nextorm/providers/postgres.py +343 -0
- nextorm/providers/sqlite.py +313 -0
- nextorm/py.typed +0 -0
- nextorm/query.py +1086 -0
- nextorm/schema/__init__.py +40 -0
- nextorm/schema/builder.py +369 -0
- nextorm/schema/core.py +74 -0
- nextorm/schema/ddl.py +435 -0
- nextorm/schema/diff.py +176 -0
- nextorm/schema/introspect.py +269 -0
- nextorm/session.py +694 -0
- nextorm/sql/__init__.py +85 -0
- nextorm/sql/builder.py +428 -0
- nextorm/sql/nodes.py +428 -0
- nextorm-0.1.0.dist-info/METADATA +166 -0
- nextorm-0.1.0.dist-info/RECORD +36 -0
- nextorm-0.1.0.dist-info/WHEEL +4 -0
- nextorm-0.1.0.dist-info/entry_points.txt +5 -0
- nextorm-0.1.0.dist-info/licenses/LICENSE +179 -0
nextorm/__init__.py
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
"""Public API surface for nextorm."""
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
|
|
5
|
+
from nextorm.async_database import AsyncDatabase, AsyncQuerySet
|
|
6
|
+
from nextorm.database import Database
|
|
7
|
+
from nextorm.debug import (
|
|
8
|
+
QueryStat,
|
|
9
|
+
clear_global_stats,
|
|
10
|
+
global_stats,
|
|
11
|
+
set_sql_debug,
|
|
12
|
+
sql_debugging,
|
|
13
|
+
)
|
|
14
|
+
from nextorm.entity import Entity, LocalDescriptor
|
|
15
|
+
from nextorm.exceptions import (
|
|
16
|
+
CommitException,
|
|
17
|
+
ConstraintError,
|
|
18
|
+
MappingError,
|
|
19
|
+
MultipleObjectsFoundError,
|
|
20
|
+
ObjectNotFound,
|
|
21
|
+
OptimisticCheckError,
|
|
22
|
+
PartialCommitException,
|
|
23
|
+
TransactionError,
|
|
24
|
+
) # noqa: F401
|
|
25
|
+
from nextorm.expr import ColumnExpr
|
|
26
|
+
from nextorm.fields import (
|
|
27
|
+
PK,
|
|
28
|
+
ULID,
|
|
29
|
+
CompositeConstraint,
|
|
30
|
+
DateTimeTz,
|
|
31
|
+
FieldSpec,
|
|
32
|
+
Json,
|
|
33
|
+
Local,
|
|
34
|
+
LocalSpec,
|
|
35
|
+
LongStr,
|
|
36
|
+
Opt,
|
|
37
|
+
PrimaryKey,
|
|
38
|
+
RelationSpec,
|
|
39
|
+
Req,
|
|
40
|
+
Set,
|
|
41
|
+
Single,
|
|
42
|
+
Vec,
|
|
43
|
+
composite_index,
|
|
44
|
+
composite_key,
|
|
45
|
+
ulid,
|
|
46
|
+
uuid4,
|
|
47
|
+
uuid7,
|
|
48
|
+
)
|
|
49
|
+
from nextorm.generators import DecompileError, avg, count, max, min, select, sum
|
|
50
|
+
from nextorm.migrations import MigrationRunner, makemigrations, migrate
|
|
51
|
+
from nextorm.pool import AsyncConnectionPool, ConnectionPool, PoolTimeoutError
|
|
52
|
+
from nextorm.providers import (
|
|
53
|
+
AsyncConnection,
|
|
54
|
+
AsyncCursor,
|
|
55
|
+
AsyncProvider,
|
|
56
|
+
SyncConnection,
|
|
57
|
+
SyncCursor,
|
|
58
|
+
SyncProvider,
|
|
59
|
+
get_async_provider,
|
|
60
|
+
get_sync_provider,
|
|
61
|
+
register_provider,
|
|
62
|
+
registered_providers,
|
|
63
|
+
)
|
|
64
|
+
from nextorm.query import EntityProxy, QuerySet
|
|
65
|
+
from nextorm.session import SessionCache, async_db_session, db_session
|
|
66
|
+
from nextorm.sql import (
|
|
67
|
+
Alias,
|
|
68
|
+
BinOp,
|
|
69
|
+
Case,
|
|
70
|
+
CaseWhen,
|
|
71
|
+
Cast,
|
|
72
|
+
ColumnRef,
|
|
73
|
+
Delete,
|
|
74
|
+
FormatBuilder,
|
|
75
|
+
FunctionCall,
|
|
76
|
+
Insert,
|
|
77
|
+
Literal,
|
|
78
|
+
OrderItem,
|
|
79
|
+
Param,
|
|
80
|
+
RawSql,
|
|
81
|
+
Select,
|
|
82
|
+
SQLiteBuilder,
|
|
83
|
+
Star,
|
|
84
|
+
UnaryOp,
|
|
85
|
+
Update,
|
|
86
|
+
render,
|
|
87
|
+
sql,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
__all__ = [
|
|
91
|
+
"Entity",
|
|
92
|
+
"FieldSpec",
|
|
93
|
+
"RelationSpec",
|
|
94
|
+
"LocalSpec",
|
|
95
|
+
"Local",
|
|
96
|
+
"Set",
|
|
97
|
+
"PK",
|
|
98
|
+
"Req",
|
|
99
|
+
"Opt",
|
|
100
|
+
"Single",
|
|
101
|
+
"CompositeConstraint",
|
|
102
|
+
"composite_key",
|
|
103
|
+
"composite_index",
|
|
104
|
+
"PrimaryKey",
|
|
105
|
+
"LocalDescriptor",
|
|
106
|
+
# UUID / ULID
|
|
107
|
+
"ULID",
|
|
108
|
+
"uuid7",
|
|
109
|
+
"uuid4",
|
|
110
|
+
"ulid",
|
|
111
|
+
# Extended types
|
|
112
|
+
"LongStr",
|
|
113
|
+
"Json",
|
|
114
|
+
"DateTimeTz",
|
|
115
|
+
"Vec",
|
|
116
|
+
"Database",
|
|
117
|
+
"AsyncDatabase",
|
|
118
|
+
"AsyncQuerySet",
|
|
119
|
+
"SessionCache",
|
|
120
|
+
"db_session",
|
|
121
|
+
"async_db_session",
|
|
122
|
+
# Generators
|
|
123
|
+
"select",
|
|
124
|
+
"DecompileError",
|
|
125
|
+
"count",
|
|
126
|
+
"avg",
|
|
127
|
+
"sum",
|
|
128
|
+
"min",
|
|
129
|
+
"max",
|
|
130
|
+
# Transaction helpers
|
|
131
|
+
"commit",
|
|
132
|
+
"rollback",
|
|
133
|
+
"flush",
|
|
134
|
+
# Migrations
|
|
135
|
+
"MigrationRunner",
|
|
136
|
+
"makemigrations",
|
|
137
|
+
"migrate",
|
|
138
|
+
# SQL nodes & builder
|
|
139
|
+
"Param",
|
|
140
|
+
"Literal",
|
|
141
|
+
"ColumnRef",
|
|
142
|
+
"Star",
|
|
143
|
+
"BinOp",
|
|
144
|
+
"UnaryOp",
|
|
145
|
+
"Cast",
|
|
146
|
+
"FunctionCall",
|
|
147
|
+
"Case",
|
|
148
|
+
"CaseWhen",
|
|
149
|
+
"Alias",
|
|
150
|
+
"OrderItem",
|
|
151
|
+
"Select",
|
|
152
|
+
"Insert",
|
|
153
|
+
"Update",
|
|
154
|
+
"Delete",
|
|
155
|
+
"RawSql",
|
|
156
|
+
"sql",
|
|
157
|
+
"SQLiteBuilder",
|
|
158
|
+
"FormatBuilder",
|
|
159
|
+
"render",
|
|
160
|
+
# Providers
|
|
161
|
+
"SyncProvider",
|
|
162
|
+
"SyncConnection",
|
|
163
|
+
"SyncCursor",
|
|
164
|
+
"AsyncProvider",
|
|
165
|
+
"AsyncConnection",
|
|
166
|
+
"AsyncCursor",
|
|
167
|
+
"register_provider",
|
|
168
|
+
"get_sync_provider",
|
|
169
|
+
"get_async_provider",
|
|
170
|
+
"registered_providers",
|
|
171
|
+
# Query DSL
|
|
172
|
+
"ColumnExpr",
|
|
173
|
+
"EntityProxy",
|
|
174
|
+
"QuerySet",
|
|
175
|
+
# Debug / diagnostics
|
|
176
|
+
"set_sql_debug",
|
|
177
|
+
"sql_debugging",
|
|
178
|
+
"QueryStat",
|
|
179
|
+
"global_stats",
|
|
180
|
+
"clear_global_stats",
|
|
181
|
+
# Exceptions
|
|
182
|
+
"MappingError",
|
|
183
|
+
"ObjectNotFound",
|
|
184
|
+
"MultipleObjectsFoundError",
|
|
185
|
+
"ConstraintError",
|
|
186
|
+
"TransactionError",
|
|
187
|
+
"OptimisticCheckError",
|
|
188
|
+
"CommitException",
|
|
189
|
+
"PartialCommitException",
|
|
190
|
+
# Connection pool
|
|
191
|
+
"ConnectionPool",
|
|
192
|
+
"AsyncConnectionPool",
|
|
193
|
+
"PoolTimeoutError",
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
# ---------------------------------------------------------------------------
|
|
197
|
+
# Module-level transaction helpers (mirrors PonyORM's commit/rollback/flush)
|
|
198
|
+
# ---------------------------------------------------------------------------
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def commit() -> None:
|
|
202
|
+
"""Commit all sync databases that have entities in the current session.
|
|
203
|
+
|
|
204
|
+
Mirrors PonyORM's staged-commit strategy:
|
|
205
|
+
|
|
206
|
+
1. Flush all databases first. On any flush error every database is rolled
|
|
207
|
+
back and the exception is re-raised.
|
|
208
|
+
2. Commit the *primary* database (first in the list) first. On failure
|
|
209
|
+
all secondary databases are rolled back and a
|
|
210
|
+
:exc:`~nextorm.exceptions.CommitException` is raised.
|
|
211
|
+
3. Commit the remaining databases. On any failure a
|
|
212
|
+
:exc:`~nextorm.exceptions.PartialCommitException` is raised (the
|
|
213
|
+
primary commit is already durable at this point).
|
|
214
|
+
|
|
215
|
+
When called outside a session this is a no-op.
|
|
216
|
+
For async databases use ``await db.acommit()`` directly.
|
|
217
|
+
"""
|
|
218
|
+
from nextorm.session import _get_session_stack # noqa: PLC0415
|
|
219
|
+
|
|
220
|
+
cache = _get_session_stack().current
|
|
221
|
+
if cache is None:
|
|
222
|
+
return
|
|
223
|
+
seen: set[int] = set()
|
|
224
|
+
dbs: list[Database] = []
|
|
225
|
+
for entity in list(cache._objects.values()) + list(cache._to_save) + list(cache._dirty):
|
|
226
|
+
db = vars(entity).get("_db_")
|
|
227
|
+
if db is not None and isinstance(db, Database) and id(db) not in seen:
|
|
228
|
+
seen.add(id(db))
|
|
229
|
+
dbs.append(db)
|
|
230
|
+
if not dbs:
|
|
231
|
+
return
|
|
232
|
+
|
|
233
|
+
# Step 1 — flush all; on error roll back everything.
|
|
234
|
+
try:
|
|
235
|
+
for db in dbs:
|
|
236
|
+
db.flush()
|
|
237
|
+
except Exception:
|
|
238
|
+
for _db in dbs:
|
|
239
|
+
with contextlib.suppress(Exception):
|
|
240
|
+
_db._rollback_transaction()
|
|
241
|
+
raise
|
|
242
|
+
|
|
243
|
+
# Step 2 — commit primary first.
|
|
244
|
+
primary, secondaries = dbs[0], dbs[1:]
|
|
245
|
+
rollback_exceptions: list[Exception] = []
|
|
246
|
+
try:
|
|
247
|
+
primary._commit_transaction()
|
|
248
|
+
except Exception as primary_exc:
|
|
249
|
+
for _db in secondaries:
|
|
250
|
+
try:
|
|
251
|
+
_db._rollback_transaction()
|
|
252
|
+
except Exception as re:
|
|
253
|
+
rollback_exceptions.append(re)
|
|
254
|
+
raise CommitException(
|
|
255
|
+
str(primary_exc), [primary_exc, *rollback_exceptions]
|
|
256
|
+
) from primary_exc
|
|
257
|
+
|
|
258
|
+
# Step 3 — commit secondaries; primary's work is already durable.
|
|
259
|
+
secondary_exceptions: list[Exception] = []
|
|
260
|
+
for db in secondaries:
|
|
261
|
+
try:
|
|
262
|
+
db._commit_transaction()
|
|
263
|
+
except Exception as e:
|
|
264
|
+
secondary_exceptions.append(e)
|
|
265
|
+
if secondary_exceptions:
|
|
266
|
+
raise PartialCommitException(
|
|
267
|
+
str(secondary_exceptions[0]), secondary_exceptions
|
|
268
|
+
) from secondary_exceptions[0]
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def rollback() -> None:
|
|
272
|
+
"""Roll back all databases that have entities in the current session.
|
|
273
|
+
|
|
274
|
+
Iterates the identity map of the active :func:`~nextorm.session.db_session`,
|
|
275
|
+
collects the unique :class:`Database` objects referenced by cached entities,
|
|
276
|
+
calls :meth:`~nextorm.database.Database.rollback` on each, and then clears
|
|
277
|
+
the session cache.
|
|
278
|
+
|
|
279
|
+
When called outside a session this is a no-op.
|
|
280
|
+
"""
|
|
281
|
+
from nextorm.session import _get_session_stack # noqa: PLC0415
|
|
282
|
+
|
|
283
|
+
cache = _get_session_stack().current
|
|
284
|
+
if cache is None:
|
|
285
|
+
return
|
|
286
|
+
dbs: set[Database] = set()
|
|
287
|
+
for entity in list(cache._objects.values()) + list(cache._to_save) + list(cache._dirty):
|
|
288
|
+
db = vars(entity).get("_db_")
|
|
289
|
+
if db is not None and isinstance(db, Database):
|
|
290
|
+
dbs.add(db)
|
|
291
|
+
for db in dbs:
|
|
292
|
+
db.rollback()
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def flush() -> None:
|
|
296
|
+
"""Flush all pending changes to all databases in the current session.
|
|
297
|
+
|
|
298
|
+
Iterates the dirty set and new-objects queue of the active
|
|
299
|
+
:func:`~nextorm.session.db_session`, groups them by :class:`Database`,
|
|
300
|
+
and calls :meth:`~nextorm.database.Database.flush` on each.
|
|
301
|
+
|
|
302
|
+
When called outside a session this is a no-op.
|
|
303
|
+
"""
|
|
304
|
+
from nextorm.session import _get_session_stack # noqa: PLC0415
|
|
305
|
+
|
|
306
|
+
cache = _get_session_stack().current
|
|
307
|
+
if cache is None:
|
|
308
|
+
return
|
|
309
|
+
# Collect both new and dirty objects to find the involved databases.
|
|
310
|
+
pending = list(cache.objects_to_save) + list(cache.dirty_objects)
|
|
311
|
+
dbs: set[Database] = set()
|
|
312
|
+
for entity in pending:
|
|
313
|
+
db = vars(entity).get("_db_")
|
|
314
|
+
if db is not None and isinstance(db, Database):
|
|
315
|
+
dbs.add(db)
|
|
316
|
+
for db in dbs:
|
|
317
|
+
db.flush()
|