litedbmodel-runtime 2.2.13__tar.gz → 2.2.15__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.
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/PKG-INFO +3 -3
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime/__init__.py +1 -1
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime/connection_routing.py +28 -21
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime/driver.py +384 -74
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime/exec_context.py +111 -42
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime/leaves.py +4 -4
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime/middleware.py +45 -13
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime/tx_options.py +4 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime.egg-info/PKG-INFO +3 -3
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime.egg-info/SOURCES.txt +3 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime.egg-info/requires.txt +2 -2
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/pyproject.toml +3 -3
- litedbmodel_runtime-2.2.15/tests/test_conn_retry_livedb.py +215 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_connection_routing.py +2 -2
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_connection_routing_livedb.py +40 -6
- litedbmodel_runtime-2.2.15/tests/test_driver_cells.py +94 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_exec_context.py +6 -6
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_middleware.py +52 -7
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_middleware_livedb.py +6 -6
- litedbmodel_runtime-2.2.15/tests/test_mysql_returning_livedb.py +345 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_transaction_boundary.py +104 -23
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_tx_boundary_livedb.py +12 -11
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/README.md +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime/dialect.py +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime/errors.py +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime/grouping.py +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime.egg-info/dependency_links.txt +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime.egg-info/top_level.txt +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/setup.cfg +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_conformance_corpus.py +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_consumes_bc_core.py +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_dialect.py +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_dynamic_where.py +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_grouping.py +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_hard_limit_guard.py +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_orm_bench_native.py +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_render.py +0 -0
- {litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/tests/test_tx_options.py +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: litedbmodel-runtime
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.15
|
|
4
4
|
Summary: Thin multi-language runtime for litedbmodel v2 SCP makeSQL bundles (Python port). Executes the published static-makeSQL artifacts (a read ReadGraph = a bc surrogate ComponentGraphIR + per-node static statement templates, or a gate-first TransactionPlan) against a SQL driver — semantics-identical to the TS reference. Delegates the Expression-IR evaluation + map/Φ/wiring orchestration to behavior-contracts.
|
|
5
5
|
Author: foo-ogawa
|
|
6
6
|
License: MIT
|
|
7
7
|
Keywords: orm,sql,ir,runtime,conformance,litedbmodel
|
|
8
8
|
Requires-Python: >=3.9
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
|
-
Requires-Dist: behavior-contracts==0.11.
|
|
10
|
+
Requires-Dist: behavior-contracts==0.11.22
|
|
11
11
|
Provides-Extra: test
|
|
12
12
|
Requires-Dist: pytest>=7.0; extra == "test"
|
|
13
13
|
Provides-Extra: livedb
|
|
14
14
|
Requires-Dist: psycopg[binary]>=3.1; extra == "livedb"
|
|
15
|
-
Requires-Dist: pymysql>=1.1; extra == "livedb"
|
|
15
|
+
Requires-Dist: pymysql>=1.1.1; extra == "livedb"
|
|
16
16
|
|
|
17
17
|
# litedbmodel-runtime (Python)
|
|
18
18
|
|
{litedbmodel_runtime-2.2.13 → litedbmodel_runtime-2.2.15}/litedbmodel_runtime/connection_routing.py
RENAMED
|
@@ -101,7 +101,9 @@ class ConnectionConfig:
|
|
|
101
101
|
- ``idle_timeout_millis``: ms an unused pooled connection stays open before it is closed
|
|
102
102
|
(@default 10000).
|
|
103
103
|
- ``search_path``: PG ``search_path`` set on each pooled connection at checkout (schema routing).
|
|
104
|
-
- ``charset``: MySQL connection charset
|
|
104
|
+
- ``charset``: MySQL connection charset (passed to ``pymysql.connect``, so PyMySQL escapes and
|
|
105
|
+
encodes bound values in the same charset the server parses them in) / PG ``client_encoding``
|
|
106
|
+
set on each pooled connection.
|
|
105
107
|
"""
|
|
106
108
|
|
|
107
109
|
__slots__ = (
|
|
@@ -257,7 +259,11 @@ def session_statements(config: ResolvedConnectionConfig) -> List[str]:
|
|
|
257
259
|
- **statement timeout** (``query_timeout`` > 0): PG ``SET statement_timeout = <ms>``; MySQL
|
|
258
260
|
``SET SESSION max_execution_time = <ms>`` (both server-side, ms).
|
|
259
261
|
- **search_path**: PG ``SET search_path TO <path>``; MySQL has no schema search path ⇒ ignored.
|
|
260
|
-
- **charset**:
|
|
262
|
+
- **charset**: PG ``SET client_encoding TO <charset>`` (psycopg binds params on the server and
|
|
263
|
+
encodes them in the session's ``client_encoding``, so the session statement is the one source).
|
|
264
|
+
MySQL ⇒ nothing here: it is a CONNECT option (:func:`_mysql_connect_kwargs`), because PyMySQL
|
|
265
|
+
escapes and encodes params on the CLIENT in its connect charset — a ``SET NAMES`` alone would
|
|
266
|
+
make the server parse in a charset the client did not escape in (#353).
|
|
261
267
|
|
|
262
268
|
A key with no value emits nothing (⇒ empty list for an all-default config ⇒ the session is
|
|
263
269
|
untouched, backward-compatible). sqlite has no server session ⇒ empty.
|
|
@@ -274,17 +280,15 @@ def session_statements(config: ResolvedConnectionConfig) -> List[str]:
|
|
|
274
280
|
)
|
|
275
281
|
if config.search_path is not None and dialect == "postgres":
|
|
276
282
|
out.append("SET search_path TO %s" % config.search_path)
|
|
277
|
-
if config.charset is not None:
|
|
278
|
-
out.append(
|
|
279
|
-
"SET NAMES %s" % config.charset if dialect == "mysql" else "SET client_encoding TO %s" % config.charset
|
|
280
|
-
)
|
|
283
|
+
if config.charset is not None and dialect == "postgres":
|
|
284
|
+
out.append("SET client_encoding TO %s" % config.charset)
|
|
281
285
|
return out
|
|
282
286
|
|
|
283
287
|
|
|
284
288
|
def session_reset_statements(config: ResolvedConnectionConfig) -> List[str]:
|
|
285
289
|
"""The RESET statements that undo :func:`session_statements` on release (per dialect), so a session
|
|
286
|
-
knob (``statement_timeout`` / ``search_path`` / ``client_encoding`` / ``max_execution_time``
|
|
287
|
-
|
|
290
|
+
knob (``statement_timeout`` / ``search_path`` / ``client_encoding`` / ``max_execution_time``)
|
|
291
|
+
set for THIS configured connection does NOT leak to the next caller that draws the SAME
|
|
288
292
|
underlying pooled connection — psycopg/PyMySQL do NOT auto-reset session state on release.
|
|
289
293
|
``RESET`` / ``SET … DEFAULT`` restores the server default. Only the knobs ``config`` actually set
|
|
290
294
|
are reset (an all-default config ⇒ nothing to reset). Mirrors the TS ``sessionResetStatements``.
|
|
@@ -297,8 +301,8 @@ def session_reset_statements(config: ResolvedConnectionConfig) -> List[str]:
|
|
|
297
301
|
out.append("RESET statement_timeout" if dialect == "postgres" else "SET SESSION max_execution_time = DEFAULT")
|
|
298
302
|
if config.search_path is not None and dialect == "postgres":
|
|
299
303
|
out.append("RESET search_path")
|
|
300
|
-
if config.charset is not None:
|
|
301
|
-
out.append("
|
|
304
|
+
if config.charset is not None and dialect == "postgres":
|
|
305
|
+
out.append("RESET client_encoding")
|
|
302
306
|
return out
|
|
303
307
|
|
|
304
308
|
|
|
@@ -614,22 +618,20 @@ def with_writer(fn: Callable[[], Any]) -> Any:
|
|
|
614
618
|
``connection_for``, so a :func:`with_writer` there is a no-op on routing (matches v1).
|
|
615
619
|
|
|
616
620
|
The read-only (write-reject) half is entered by a bare read-only marker the guarded write seam
|
|
617
|
-
consults, AND —
|
|
618
|
-
|
|
619
|
-
write-reject half
|
|
620
|
-
both halves span the whole ``fn``
|
|
621
|
+
consults, AND — for every :class:`ExecutionContext` pinned in the current scope (one per owner) — by
|
|
622
|
+
pinning its read-only view under the same owner, so ``ambient_read_only()`` (which reads the pinned
|
|
623
|
+
ctxs) also sees the write-reject half and each owner keeps its own open transaction. v1's single
|
|
624
|
+
writerContext is BOTH the writer-routing and the read-only marker; both halves span the whole ``fn``
|
|
625
|
+
because the contextvars are per-scope.
|
|
621
626
|
"""
|
|
622
627
|
if in_writer_scope():
|
|
623
628
|
return fn()
|
|
624
629
|
token = _writer_scope_var.set(True)
|
|
625
630
|
ro_token = _readonly_marker_var.set(True)
|
|
626
631
|
try:
|
|
627
|
-
from .exec_context import
|
|
632
|
+
from .exec_context import pinned_contexts, run_with_pinned_contexts
|
|
628
633
|
|
|
629
|
-
|
|
630
|
-
if ambient is not None and not ambient.read_only():
|
|
631
|
-
return run_with_pinned_context(ambient.with_read_only(), fn)
|
|
632
|
-
return fn()
|
|
634
|
+
return run_with_pinned_contexts([p.with_read_only() for p in pinned_contexts() if not p.read_only()], fn)
|
|
633
635
|
finally:
|
|
634
636
|
_readonly_marker_var.reset(ro_token)
|
|
635
637
|
_writer_scope_var.reset(token)
|
|
@@ -907,8 +909,9 @@ def close_all_pools(closers: Sequence[PoolCloser]) -> None:
|
|
|
907
909
|
# (min_pool/max_pool) + keep_alive — reach the real pool at build time (a pre-built pool can no longer
|
|
908
910
|
# accept them). These factories map a ResolvedConnectionConfig to a psycopg / PyMySQL-backed
|
|
909
911
|
# `_ConnectionPool` sized to `max_pool` and return the ConnectionPool adapter + closer. The configured
|
|
910
|
-
# sizing is thus the SOLE source of the pool cap. Session knobs (query_timeout/search_path
|
|
911
|
-
# layered separately by `configured_pool` on checkout
|
|
912
|
+
# sizing is thus the SOLE source of the pool cap. Session knobs (query_timeout/search_path, and the PG
|
|
913
|
+
# client_encoding) are layered separately by `configured_pool` on checkout; the MySQL charset is a
|
|
914
|
+
# PyMySQL CONNECT option (`_mysql_connect_kwargs`), since PyMySQL escapes params on the client in it.
|
|
912
915
|
#
|
|
913
916
|
# ── keep_alive honesty (per-driver, mirror the TS mysql2 minPool note) ──
|
|
914
917
|
# - psycopg (PG): TCP keepalive is a libpq CONNECTION parameter, so `keep_alive=True` maps to
|
|
@@ -1011,6 +1014,10 @@ def _mysql_connect_kwargs(config: ResolvedConnectionConfig) -> Dict[str, Any]:
|
|
|
1011
1014
|
if config.password is not None:
|
|
1012
1015
|
kwargs["password"] = config.password
|
|
1013
1016
|
kwargs["connect_timeout"] = config.connect_timeout_millis / 1000.0 or _PYMYSQL_MAX_CONNECT_TIMEOUT_SECONDS
|
|
1017
|
+
if config.charset is not None:
|
|
1018
|
+
# PyMySQL escapes and encodes params on the client in this charset and announces it to the
|
|
1019
|
+
# server, so client escaping and server parsing share ONE charset (#353).
|
|
1020
|
+
kwargs["charset"] = config.charset
|
|
1014
1021
|
# NB: PyMySQL exposes no TCP-keepalive connect option ⇒ keep_alive is a documented NO-OP on MySQL
|
|
1015
1022
|
# (mirror the TS mysqlPoolFactory's "mysql2 has no min idle floor" per-driver deviation note).
|
|
1016
1023
|
return kwargs
|