litedbmodel-runtime 2.0.2__tar.gz → 2.1.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.
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/PKG-INFO +2 -2
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime/__init__.py +1 -5
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime/livedb_runner.py +1 -1
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime/runtime.py +5 -7
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime/static_bundle.py +96 -37
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime/vectors_runner.py +1 -1
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime.egg-info/PKG-INFO +2 -2
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime.egg-info/requires.txt +1 -1
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/pyproject.toml +2 -2
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/tests/test_consumes_bc_core.py +14 -6
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/tests/test_parallel_read.py +6 -5
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/tests/test_runtime.py +9 -18
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/README.md +0 -0
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime/dialect.py +0 -0
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime/driver.py +0 -0
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime/errors.py +0 -0
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime/relation.py +0 -0
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime.egg-info/SOURCES.txt +0 -0
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime.egg-info/dependency_links.txt +0 -0
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime.egg-info/top_level.txt +0 -0
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/setup.cfg +0 -0
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/tests/test_conformance_corpus.py +0 -0
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/tests/test_dialect.py +0 -0
- {litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/tests/test_render.py +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: litedbmodel-runtime
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
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.
|
|
10
|
+
Requires-Dist: behavior-contracts==0.8.0
|
|
11
11
|
Provides-Extra: test
|
|
12
12
|
Requires-Dist: pytest>=7.0; extra == "test"
|
|
13
13
|
Provides-Extra: livedb
|
|
@@ -16,8 +16,6 @@ from .dialect import SQLITE, POSTGRES, MYSQL, Dialect, dialect_for, to_dollar_pl
|
|
|
16
16
|
from .driver import Driver, MysqlDriver, PostgresDriver, PreparedStatement, RunInfo, SqliteDriver
|
|
17
17
|
from .errors import SqlFailure, map_sqlite_error
|
|
18
18
|
from .static_bundle import (
|
|
19
|
-
NODE_COMPONENT,
|
|
20
|
-
SCOPE_PORT,
|
|
21
19
|
assemble_make_sql,
|
|
22
20
|
compose_make_sql,
|
|
23
21
|
execute_read_graph,
|
|
@@ -38,7 +36,7 @@ from .relation import (
|
|
|
38
36
|
run_relation_op,
|
|
39
37
|
)
|
|
40
38
|
|
|
41
|
-
__version__ = "2.0
|
|
39
|
+
__version__ = "2.1.0"
|
|
42
40
|
|
|
43
41
|
__all__ = [
|
|
44
42
|
"__version__",
|
|
@@ -60,8 +58,6 @@ __all__ = [
|
|
|
60
58
|
"SqlFailure",
|
|
61
59
|
"map_sqlite_error",
|
|
62
60
|
# static makeSQL bundle runtime (the sole read/render path)
|
|
63
|
-
"NODE_COMPONENT",
|
|
64
|
-
"SCOPE_PORT",
|
|
65
61
|
"assemble_make_sql",
|
|
66
62
|
"compose_make_sql",
|
|
67
63
|
"execute_read_graph",
|
{litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime/livedb_runner.py
RENAMED
|
@@ -42,7 +42,7 @@ from litedbmodel_runtime import ( # noqa: E402
|
|
|
42
42
|
read_bundle,
|
|
43
43
|
)
|
|
44
44
|
|
|
45
|
-
SUPPORTED_CORPUS_VERSION =
|
|
45
|
+
SUPPORTED_CORPUS_VERSION = 3
|
|
46
46
|
# A distinct namespace per language so 4 languages share ONE docker stack without cross-talk.
|
|
47
47
|
PG_SCHEMA = os.environ.get("LIVEDB_PG_SCHEMA", "scp_py")
|
|
48
48
|
MYSQL_DB = os.environ.get("LIVEDB_MYSQL_DB", "scp_py")
|
|
@@ -6,10 +6,10 @@ static-makeSQL artifacts the corpus ships (pure JSON: a read ``ReadGraph`` = a b
|
|
|
6
6
|
gate-first makeSQL statements) and executes them against a SQL driver — SEMANTICS-IDENTICAL to the
|
|
7
7
|
TS reference (``src/scp/runtime.ts`` + ``src/scp/makesql/*``).
|
|
8
8
|
|
|
9
|
-
It re-implements NO generic
|
|
10
|
-
plan/map/wire/output orchestration and
|
|
11
|
-
(ref/refOpt/coalesce/eq/…, the SKIP guards + deferred value-specs)
|
|
12
|
-
SQL-backend concerns (spec §11): assemble the static makeSQL statements per dialect → bind params →
|
|
9
|
+
It re-implements NO generic expression evaluation: the NATIVE read-graph walker (#12) owns the
|
|
10
|
+
plan/map/wire/output orchestration and bc's ``evaluate_expression`` owns the CLOSED Expression-IR
|
|
11
|
+
(ref/refOpt/coalesce/eq/…, the SKIP guards + deferred value-specs) — NO bc ``run_behavior``. This
|
|
12
|
+
module adds ONLY the SQL-backend concerns (spec §11): assemble the static makeSQL statements per dialect → bind params →
|
|
13
13
|
execute REAL SQL → row→result assembly; and, for a Command bundle, the gate-first write transaction
|
|
14
14
|
(``execute_transaction_bundle``). This mirrors the TS runtime's division of labor exactly (bc-core
|
|
15
15
|
+ a makeSQL handler). The reduced fragment-tree render path (``render.py``) is RETIRED for the SQL
|
|
@@ -25,7 +25,6 @@ from .dialect import dialect_for
|
|
|
25
25
|
from .driver import Driver
|
|
26
26
|
from .errors import SqlFailure, map_sqlite_error
|
|
27
27
|
from .static_bundle import (
|
|
28
|
-
SCOPE_PORT,
|
|
29
28
|
assemble_make_sql,
|
|
30
29
|
execute_read_graph,
|
|
31
30
|
render_placeholders,
|
|
@@ -40,7 +39,6 @@ _RETURNING_RE = re.compile(r"\breturning\b", re.IGNORECASE)
|
|
|
40
39
|
_SELECT_RE = re.compile(r"\bselect\b", re.IGNORECASE)
|
|
41
40
|
|
|
42
41
|
__all__ = [
|
|
43
|
-
"SCOPE_PORT",
|
|
44
42
|
"ENTITY_ROOT",
|
|
45
43
|
"execute_bundle",
|
|
46
44
|
"execute_transaction_bundle",
|
|
@@ -73,7 +71,7 @@ def _to_driver_param_tx(v: Any) -> Any:
|
|
|
73
71
|
|
|
74
72
|
|
|
75
73
|
def execute_bundle(bundle: Mapping[str, Any], input_scope: Mapping[str, Any], driver: Driver) -> Any:
|
|
76
|
-
"""Execute a read/exec SqlBundle end-to-end (
|
|
74
|
+
"""Execute a read/exec SqlBundle end-to-end (native read-graph walker; no bc run_behavior).
|
|
77
75
|
|
|
78
76
|
The SAME code path a consumer runtime follows: it consumes ONLY the serialized bundle + bc
|
|
79
77
|
runtime-core, never re-running litedbmodel's Backend-Compile. A read bundle carries a
|
{litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime/static_bundle.py
RENAMED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Byte-for-byte port of the TS ``src/scp/makesql/static-bundle.ts`` + ``makesql.ts`` + ``handler.ts``
|
|
4
4
|
runtime halves — the SOLE makeSQL read/render path. It consumes the PRE-COMPILED, portable
|
|
5
|
-
artifacts the corpus ships (a read ``ReadGraph`` =
|
|
6
|
-
|
|
7
|
-
``
|
|
8
|
-
|
|
5
|
+
artifacts the corpus ships (a read ``ReadGraph`` = ``compileBehaviors``' REAL ``Select``/``Count``/map
|
|
6
|
+
``ComponentGraphIR`` + per-node STATIC statement templates keyed by the real node id; #12 — no
|
|
7
|
+
``__makeSqlNode``/``__scope`` surrogate), and EXECUTES them via the NATIVE read-graph walker (owns map /
|
|
8
|
+
Φ-merge / wiring; NO bc ``run_behavior``) + bc ``evaluate_expression`` for the deferred value-specs +
|
|
9
|
+
skip. This module re-implements NO generic evaluator and does
|
|
9
10
|
NO SQL re-derivation — every statement's ``sql`` is fixed text already; the runtime only evaluates
|
|
10
11
|
its deferred params + skip, resolves the WHERE connector from the present set, assembles + renders
|
|
11
12
|
placeholders, and binds.
|
|
@@ -26,19 +27,15 @@ from __future__ import annotations
|
|
|
26
27
|
|
|
27
28
|
import json
|
|
28
29
|
import re
|
|
30
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
29
31
|
from typing import Any, Dict, List, Mapping, Sequence
|
|
30
32
|
|
|
31
|
-
from behavior_contracts import evaluate_expression
|
|
33
|
+
from behavior_contracts import evaluate_expression
|
|
32
34
|
|
|
33
35
|
from .dialect import Dialect, dialect_for
|
|
34
36
|
from .driver import Driver
|
|
35
37
|
from .errors import SqlFailure, map_sqlite_error
|
|
36
38
|
|
|
37
|
-
# The synthetic port that carries a SQL node's render scope (mirrors TS SCOPE_PORT).
|
|
38
|
-
SCOPE_PORT = "__scope"
|
|
39
|
-
# The makeSQL catalog leaf name every rewritten SQL node references (mirrors TS NODE_COMPONENT).
|
|
40
|
-
NODE_COMPONENT = "__makeSqlNode"
|
|
41
|
-
|
|
42
39
|
_RETURNING_RE = re.compile(r"\breturning\b", re.IGNORECASE)
|
|
43
40
|
|
|
44
41
|
|
|
@@ -262,7 +259,7 @@ def render_read_primary(graph: Mapping[str, Any], input_scope: Mapping[str, Any]
|
|
|
262
259
|
"""Render the PRIMARY read node's statements of a ReadGraph → dialect SQL text + params.
|
|
263
260
|
|
|
264
261
|
Byte-for-byte port of the TS ``renderReadPrimary``: the primary node is the first body node in
|
|
265
|
-
the
|
|
262
|
+
the real-node IR order (map nodes reference it). Optional heads are normalized to present-as-null
|
|
266
263
|
first (absent-key SKIP), so an omitted optional head renders the SAME text a runtime would.
|
|
267
264
|
"""
|
|
268
265
|
statements_by_id: Mapping[str, Any] = graph["statementsById"]
|
|
@@ -279,37 +276,99 @@ def render_read_primary(graph: Mapping[str, Any], input_scope: Mapping[str, Any]
|
|
|
279
276
|
# ── ReadGraph execution (port of static-bundle.ts executeReadGraph) ────────────
|
|
280
277
|
|
|
281
278
|
|
|
279
|
+
def _plan_stages(component: Mapping[str, Any]) -> List[List[int]]:
|
|
280
|
+
"""The plan stages (``groups``) as body-index lists, or one-node-per-stage in body order."""
|
|
281
|
+
plan = component.get("plan")
|
|
282
|
+
if isinstance(plan, Mapping):
|
|
283
|
+
groups = plan.get("groups")
|
|
284
|
+
if isinstance(groups, list):
|
|
285
|
+
return [[i for i in st if isinstance(i, int)] for st in groups if isinstance(st, list)]
|
|
286
|
+
return [[i] for i in range(len(component.get("body", [])))]
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def _plan_concurrency(component: Mapping[str, Any]) -> int:
|
|
290
|
+
"""The plan's ``concurrency`` bound (default 1 — serial when absent/<=1), for the fan-out."""
|
|
291
|
+
plan = component.get("plan")
|
|
292
|
+
if isinstance(plan, Mapping):
|
|
293
|
+
c = plan.get("concurrency")
|
|
294
|
+
if isinstance(c, int) and c >= 1:
|
|
295
|
+
return c
|
|
296
|
+
return 1
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _render_execute_node(
|
|
300
|
+
graph: Mapping[str, Any], node_id: str, scope: Mapping[str, Any], driver: Driver
|
|
301
|
+
) -> List[Any]:
|
|
302
|
+
"""Render node ``node_id``'s ``statementsById`` fragments against ``scope`` and run them."""
|
|
303
|
+
statements_by_id: Mapping[str, Any] = graph["statementsById"]
|
|
304
|
+
stmts = statements_by_id.get(node_id)
|
|
305
|
+
if stmts is None:
|
|
306
|
+
raise ValueError(f"static-bundle: no statements for node '{node_id}'")
|
|
307
|
+
rendered = render_statements(stmts, graph["dialect"], scope)
|
|
308
|
+
try:
|
|
309
|
+
return driver.prepare(rendered["sql"]).all(rendered["params"])
|
|
310
|
+
except Exception as e: # driver error → mapped SqlFailure
|
|
311
|
+
raise map_sqlite_error(e)
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def _compute_read_node(
|
|
315
|
+
graph: Mapping[str, Any], node: Mapping[str, Any], base: Mapping[str, Any], driver: Driver
|
|
316
|
+
) -> Any:
|
|
317
|
+
"""Compute ONE read-graph body node's value: a ``cond`` join, a ``map`` (per-element
|
|
318
|
+
render+execute under the ``as`` binding), or a componentRef (render+execute)."""
|
|
319
|
+
if "cond" in node:
|
|
320
|
+
return evaluate_expression(node["cond"], base)
|
|
321
|
+
node_id = node.get("id", "")
|
|
322
|
+
if "map" in node:
|
|
323
|
+
m = node["map"]
|
|
324
|
+
over = evaluate_expression(m.get("over"), base)
|
|
325
|
+
if not isinstance(over, list):
|
|
326
|
+
raise ValueError(f"static-bundle: map '{node_id}': 'over' is not an array")
|
|
327
|
+
as_name = m.get("as") or "$"
|
|
328
|
+
out: List[Any] = []
|
|
329
|
+
for el in over:
|
|
330
|
+
elem_scope = dict(base)
|
|
331
|
+
elem_scope[as_name] = el
|
|
332
|
+
out.append(_render_execute_node(graph, node_id, elem_scope, driver))
|
|
333
|
+
return out
|
|
334
|
+
return _render_execute_node(graph, node_id, base, driver)
|
|
335
|
+
|
|
336
|
+
|
|
282
337
|
def execute_read_graph(graph: Mapping[str, Any], input_scope: Mapping[str, Any], driver: Driver) -> Any:
|
|
283
|
-
"""Execute a compiled ReadGraph via
|
|
338
|
+
"""Execute a compiled ReadGraph via the NATIVE walker (#12): no bc ``run_behavior``.
|
|
284
339
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
and
|
|
288
|
-
|
|
340
|
+
Walks ``compileBehaviors``' REAL ``Select``/``Count``/map node IR in ``plan.groups`` stage order —
|
|
341
|
+
computing each node's rows from its ``statementsById`` fragments (rendered against the walk scope)
|
|
342
|
+
and committing ``nodeId -> value`` — then evaluates the component ``output`` Φ expression.
|
|
343
|
+
litedbmodel owns map iteration / wire binding / Φ output; NO ``__makeSqlNode``/``__scope``
|
|
344
|
+
surrogate. The SAME native model the TS/rust/go/php runtimes follow — interpreter-free.
|
|
289
345
|
"""
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
node_id = ctx["nodeId"]
|
|
295
|
-
stmts = statements_by_id.get(node_id)
|
|
296
|
-
if stmts is None:
|
|
297
|
-
return {"error": f"static-bundle: no statements for node '{node_id}'"}
|
|
298
|
-
scope = ports.get(SCOPE_PORT)
|
|
299
|
-
if not isinstance(scope, dict):
|
|
300
|
-
return {"error": f"static-bundle: node '{node_id}' surrogate scope did not evaluate to an object"}
|
|
301
|
-
rendered = render_statements(stmts, dialect_name, scope)
|
|
302
|
-
try:
|
|
303
|
-
rows = driver.prepare(rendered["sql"]).all(rendered["params"])
|
|
304
|
-
return {"ok": rows}
|
|
305
|
-
except Exception as e: # driver error → mapped {error}
|
|
306
|
-
return {"error": str(map_sqlite_error(e))}
|
|
307
|
-
|
|
308
|
-
handlers = {NODE_COMPONENT: handle}
|
|
309
|
-
ir = graph["ir"]
|
|
346
|
+
component = graph["ir"]["components"][0]
|
|
347
|
+
body = component.get("body", [])
|
|
348
|
+
output = component.get("output")
|
|
349
|
+
concurrency = _plan_concurrency(component)
|
|
310
350
|
normalized = _normalize_optional_heads(list(graph.get("optionalHeads", [])), input_scope)
|
|
311
351
|
try:
|
|
312
|
-
|
|
352
|
+
results: List[tuple] = []
|
|
353
|
+
for stage in _plan_stages(component):
|
|
354
|
+
base = dict(normalized)
|
|
355
|
+
for nid, val in results:
|
|
356
|
+
base[nid] = val
|
|
357
|
+
ordered = sorted(stage) # ascending body index — deterministic commit order
|
|
358
|
+
# Independent siblings of a stage run in bounded parallel (capped at the plan concurrency;
|
|
359
|
+
# concurrency <= 1 or a single member ⇒ serial); each dispatched on its own pooled
|
|
360
|
+
# connection against the driver. Results commit in ascending body index (deterministic).
|
|
361
|
+
if concurrency > 1 and len(ordered) > 1:
|
|
362
|
+
with ThreadPoolExecutor(max_workers=min(concurrency, len(ordered))) as pool:
|
|
363
|
+
vals = list(pool.map(lambda idx: _compute_read_node(graph, body[idx], base, driver), ordered))
|
|
364
|
+
else:
|
|
365
|
+
vals = [_compute_read_node(graph, body[idx], base, driver) for idx in ordered]
|
|
366
|
+
for idx, val in zip(ordered, vals):
|
|
367
|
+
results.append((body[idx]["id"], val))
|
|
368
|
+
scope = dict(normalized)
|
|
369
|
+
for nid, val in results:
|
|
370
|
+
scope[nid] = val
|
|
371
|
+
return evaluate_expression(output, scope)
|
|
313
372
|
except Exception as e:
|
|
314
373
|
raise _re_error_to_sql_failure(e)
|
|
315
374
|
|
{litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime/vectors_runner.py
RENAMED
|
@@ -47,7 +47,7 @@ from litedbmodel_runtime import ( # noqa: E402
|
|
|
47
47
|
from litedbmodel_runtime.driver import SqliteDriver # noqa: E402
|
|
48
48
|
|
|
49
49
|
# The corpus schema version this runner supports (pin — bumped on additive refreeze).
|
|
50
|
-
SUPPORTED_CORPUS_VERSION =
|
|
50
|
+
SUPPORTED_CORPUS_VERSION = 3
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
def _vectors_dir() -> Path:
|
{litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime.egg-info/PKG-INFO
RENAMED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: litedbmodel-runtime
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
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.
|
|
10
|
+
Requires-Dist: behavior-contracts==0.8.0
|
|
11
11
|
Provides-Extra: test
|
|
12
12
|
Requires-Dist: pytest>=7.0; extra == "test"
|
|
13
13
|
Provides-Extra: livedb
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "litedbmodel-runtime"
|
|
7
|
-
version = "2.0
|
|
7
|
+
version = "2.1.0"
|
|
8
8
|
description = "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."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -16,7 +16,7 @@ keywords = ["orm", "sql", "ir", "runtime", "conformance", "litedbmodel"]
|
|
|
16
16
|
# evaluation (ref/refOpt/coalesce/eq/… — the SKIP guards + param slots) to the shared common
|
|
17
17
|
# core, exactly as the TS reference imports `behavior-contracts` from npm. HARD dependency,
|
|
18
18
|
# consumed from the published PyPI registry (NO local path — the no-local-deps gate forbids it).
|
|
19
|
-
dependencies = ["behavior-contracts==0.
|
|
19
|
+
dependencies = ["behavior-contracts==0.8.0"]
|
|
20
20
|
|
|
21
21
|
[project.optional-dependencies]
|
|
22
22
|
test = ["pytest>=7.0"]
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"""Guardrail test (WS7b, #31): bc runtime-core is CONSUMED, not reimplemented.
|
|
2
2
|
|
|
3
|
-
The hard rule: the Python runtime delegates the CLOSED Expression-IR evaluation
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
The hard rule: the Python runtime delegates the CLOSED Expression-IR evaluation to
|
|
4
|
+
behavior-contracts (the published PyPI package), exactly like the TS reference imports
|
|
5
|
+
`behavior-contracts` from npm — no local generic expression evaluator. (#12: the read-graph
|
|
6
|
+
plan/map/wire/output orchestration is now the crate's OWN NATIVE walker, not bc `run_behavior` —
|
|
7
|
+
mirroring the rust/go native walkers.) This asserts the runtime consumes bc's `evaluate_expression`,
|
|
8
|
+
does NOT call `run_behavior` on the exec path, and pins the PyPI dep with NO local `../` path.
|
|
8
9
|
"""
|
|
9
10
|
|
|
10
11
|
from __future__ import annotations
|
|
@@ -29,7 +30,14 @@ def _imports_from(module: str) -> set[str]:
|
|
|
29
30
|
def test_static_bundle_consumes_bc_evaluate_expression():
|
|
30
31
|
names = _imports_from("static_bundle.py")
|
|
31
32
|
assert "evaluate_expression" in names
|
|
32
|
-
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_static_bundle_does_not_call_run_behavior_on_exec_path():
|
|
36
|
+
# #12: the native read-graph walker replaced bc `run_behavior` on EVERY exec path — the runtime
|
|
37
|
+
# neither imports nor calls it (the CLOSED expression eval still rides bc `evaluate_expression`).
|
|
38
|
+
src = (PKG / "static_bundle.py").read_text(encoding="utf-8") + (PKG / "runtime.py").read_text(encoding="utf-8")
|
|
39
|
+
assert "run_behavior(" not in src, "runtime must not call bc run_behavior on the exec path (#12)"
|
|
40
|
+
assert "run_behavior" not in _imports_from("static_bundle.py")
|
|
33
41
|
|
|
34
42
|
|
|
35
43
|
def test_no_local_generic_evaluator_reimplemented():
|
|
@@ -19,9 +19,6 @@ import time
|
|
|
19
19
|
|
|
20
20
|
from litedbmodel_runtime.static_bundle import execute_read_graph
|
|
21
21
|
|
|
22
|
-
SCOPE_PORT = "__scope"
|
|
23
|
-
NODE_COMPONENT = "__makeSqlNode"
|
|
24
|
-
|
|
25
22
|
|
|
26
23
|
class _LatencyPrepared:
|
|
27
24
|
def __init__(self, driver: "_LatencyDriver", sql: str) -> None:
|
|
@@ -58,13 +55,17 @@ class _LatencyDriver:
|
|
|
58
55
|
|
|
59
56
|
|
|
60
57
|
def _sibling_graph(n: int, concurrency: int = 16) -> dict:
|
|
61
|
-
"""A read graph of n independent sibling nodes in ONE plan stage, each a trivial SELECT.
|
|
58
|
+
"""A read graph of n independent sibling nodes in ONE plan stage, each a trivial SELECT.
|
|
59
|
+
|
|
60
|
+
Each body node is a REAL ``compileBehaviors`` Select node — just an ``id`` the native walker
|
|
61
|
+
renders + executes from ``statementsById`` (#12: no ``__makeSqlNode``/``__scope`` surrogate).
|
|
62
|
+
"""
|
|
62
63
|
body = []
|
|
63
64
|
output_obj = {}
|
|
64
65
|
statements_by_id = {}
|
|
65
66
|
for i in range(n):
|
|
66
67
|
node_id = f"rel{i}"
|
|
67
|
-
body.append({"id": node_id
|
|
68
|
+
body.append({"id": node_id})
|
|
68
69
|
output_obj[node_id] = {"ref": [node_id]}
|
|
69
70
|
statements_by_id[node_id] = [{"sql": f"SELECT {i}", "params": []}]
|
|
70
71
|
return {
|
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
These exercise the static-makeSQL SQL-backend runtime against a REAL in-proc sqlite3 driver,
|
|
4
4
|
independent of the frozen corpus, to prove:
|
|
5
|
-
- read bundle →
|
|
5
|
+
- read bundle → the NATIVE read-graph walker (plan/map/wire/output owned by litedbmodel; #12 —
|
|
6
|
+
no bc run_behavior, no surrogate) → assembled Φ output;
|
|
6
7
|
- write bundle → gate-first transaction (commit; requires short-circuit ROLLBACK; idempotent
|
|
7
8
|
duplicate short-circuit) with `$.entity` RETURNING exposure + emit-payload JSON serialization;
|
|
8
|
-
- bc-core is CONSUMED
|
|
9
|
-
|
|
9
|
+
- bc-core is CONSUMED only for the deferred value-specs + skip (`evaluate_expression`) — the map
|
|
10
|
+
orchestration is the walker's, not reimplemented per node.
|
|
10
11
|
|
|
11
|
-
The bundle is the LOCKED static-makeSQL shape: a read carries a `readGraph` (
|
|
12
|
-
`
|
|
13
|
-
statement templates); a write carries a `transaction` plan of `{sql, params}`
|
|
12
|
+
The bundle is the LOCKED static-makeSQL shape: a read carries a `readGraph` (`compileBehaviors`'
|
|
13
|
+
REAL `Select`/map `ComponentGraphIR` + per-node STATIC `{sql, params, skip?, whereFragment?}`
|
|
14
|
+
statement templates keyed by node id); a write carries a `transaction` plan of `{sql, params}` ops.
|
|
14
15
|
"""
|
|
15
16
|
|
|
16
17
|
from __future__ import annotations
|
|
@@ -63,20 +64,10 @@ def _read_bundle():
|
|
|
63
64
|
"name": "Feed",
|
|
64
65
|
"inputPorts": {"author_id": {"required": True}, "status": {"required": True}},
|
|
65
66
|
"body": [
|
|
66
|
-
{
|
|
67
|
-
"id": "n0",
|
|
68
|
-
"component": "__makeSqlNode",
|
|
69
|
-
"ports": {"__scope": {"obj": {"author_id": {"ref": ["author_id"]}, "status": {"ref": ["status"]}}}},
|
|
70
|
-
},
|
|
67
|
+
{"id": "n0"},
|
|
71
68
|
{
|
|
72
69
|
"id": "n1",
|
|
73
|
-
"map": {
|
|
74
|
-
"over": {"ref": ["n0"]},
|
|
75
|
-
"as": "$e0",
|
|
76
|
-
"component": "__makeSqlNode",
|
|
77
|
-
"parent": "n0",
|
|
78
|
-
"ports": {"__scope": {"obj": {"$e0": {"ref": ["$e0"]}}}},
|
|
79
|
-
},
|
|
70
|
+
"map": {"over": {"ref": ["n0"]}, "as": "$e0", "parent": "n0"},
|
|
80
71
|
},
|
|
81
72
|
],
|
|
82
73
|
"output": {"obj": {"posts": {"ref": ["n0"]}, "authors": {"ref": ["n1"]}}},
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{litedbmodel_runtime-2.0.2 → litedbmodel_runtime-2.1.0}/litedbmodel_runtime.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|