graphddb-runtime 1.0.6__tar.gz → 1.0.8__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.
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/PKG-INFO +2 -2
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/behavior_exec.py +62 -42
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime.egg-info/PKG-INFO +2 -2
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime.egg-info/requires.txt +1 -1
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/pyproject.toml +2 -2
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/README.md +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/__init__.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/async_runtime.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/batch.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/concurrency.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/cursor.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/errors.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/filters.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/handler_registry.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/hydration.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/limits.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/middleware.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/per_key_cursor.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/runtime.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/templates.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime/transactions.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime.egg-info/SOURCES.txt +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime.egg-info/dependency_links.txt +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime.egg-info/top_level.txt +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/setup.cfg +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_atomic_add_command.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_concurrency.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_contract_runtime.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_crosslang_python_cells.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_description.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_description_followups.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_description_jsdoc.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_error_policy.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_generated_module.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_guard_eval.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_handler_registry.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_batch_write.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_binding_contract.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_command.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_compose.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_contract.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_edge_derive.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_edge_write.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_events.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_maintain.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_middleware.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_referential.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_relations.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_unique.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_maintain.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_middleware.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_relations.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_spec_version_guard.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_ttl.py +0 -0
- {graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_unit.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: graphddb-runtime
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.8
|
|
4
4
|
Summary: Thin DynamoDB executor for GraphDDB-generated Python repositories (single-operation core, issue #44).
|
|
5
5
|
License: MIT
|
|
6
6
|
Requires-Python: >=3.9
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
Requires-Dist: boto3>=1.26
|
|
9
|
-
Requires-Dist: behavior-contracts==0.
|
|
9
|
+
Requires-Dist: behavior-contracts==0.7.3
|
|
10
10
|
Provides-Extra: test
|
|
11
11
|
Requires-Dist: pytest>=7.0; extra == "test"
|
|
12
12
|
|
|
@@ -122,16 +122,22 @@ _READ_META_PORTS = frozenset(
|
|
|
122
122
|
"filter",
|
|
123
123
|
"projection",
|
|
124
124
|
"cardinality",
|
|
125
|
-
"implicitSourceField",
|
|
126
125
|
)
|
|
127
126
|
)
|
|
128
127
|
|
|
129
128
|
|
|
130
129
|
def _node_parts(node: Mapping[str, Any]) -> Tuple[str, Optional[Mapping[str, Any]], Mapping[str, Any]]:
|
|
131
|
-
"""``(id, map|None, ports)`` of a body node (componentRef
|
|
130
|
+
"""``(id, map|None, ports)`` of a body node (componentRef / map / fanout)."""
|
|
132
131
|
m = node.get("map")
|
|
133
132
|
if m is not None:
|
|
134
133
|
return node["id"], m, m["ports"]
|
|
134
|
+
fo = node.get("fanout")
|
|
135
|
+
if fo is not None:
|
|
136
|
+
# A `refs` fan-out (bc 0.7.3 v3): its per-element BatchGet ports drive the
|
|
137
|
+
# SAME batched handler a batched map did. bc's `run_behavior` owns the
|
|
138
|
+
# dedupe/drop/wrap (fanout_dedup_drop) — graphddb only supplies the aligned
|
|
139
|
+
# bodies. Return its ports for the structural/config consumers.
|
|
140
|
+
return node["id"], None, fo["ports"]
|
|
135
141
|
return node["id"], None, node["ports"]
|
|
136
142
|
|
|
137
143
|
|
|
@@ -240,11 +246,6 @@ def execute_read_component(
|
|
|
240
246
|
"is_root": node_id == "root",
|
|
241
247
|
}
|
|
242
248
|
|
|
243
|
-
# Batched fan-out bookkeeping for the refs fold: node id → the per-element
|
|
244
|
-
# dedupe markers, ALIGNED to the map's driver elements (first-seen dedupe /
|
|
245
|
-
# missing-drop needs the element→key identity the handler computed).
|
|
246
|
-
refs_markers: Dict[str, List[str]] = {}
|
|
247
|
-
|
|
248
249
|
def _key_of(ports: Mapping[str, Any], key_attrs: List[str]) -> Dict[str, Any]:
|
|
249
250
|
return {attr: ports[attr] for attr in key_attrs}
|
|
250
251
|
|
|
@@ -381,8 +382,12 @@ def execute_read_component(
|
|
|
381
382
|
ports["items"] if batched else [ports] # type: ignore[assignment]
|
|
382
383
|
)
|
|
383
384
|
|
|
384
|
-
#
|
|
385
|
-
#
|
|
385
|
+
# PHYSICAL dedupe INSIDE the handler (CONSUMER) — the ONE deduped/chunked
|
|
386
|
+
# BatchGet the request needs to avoid over-fetch. The RESULT-level dedupe /
|
|
387
|
+
# dangling-drop / connection-wrap is NO LONGER graphddb's: bc's `fanout`
|
|
388
|
+
# node (v3, run_behavior → fanout_dedup_drop) owns it, keyed off the result
|
|
389
|
+
# body's `dedupeKey` field. The handler returns the list ALIGNED to the
|
|
390
|
+
# input element order (null for a missing body) — the fanout's contract.
|
|
386
391
|
plain_keys: List[Dict[str, Any]] = []
|
|
387
392
|
markers: List[str] = []
|
|
388
393
|
seen: set = set()
|
|
@@ -394,8 +399,6 @@ def execute_read_component(
|
|
|
394
399
|
continue
|
|
395
400
|
seen.add(marker)
|
|
396
401
|
plain_keys.append(plain_key)
|
|
397
|
-
if batched:
|
|
398
|
-
refs_markers[ctx["nodeId"]] = markers
|
|
399
402
|
|
|
400
403
|
if len(plain_keys) > rt._limits.max_items:
|
|
401
404
|
raise LimitExceededError(
|
|
@@ -491,25 +494,30 @@ def execute_read_component(
|
|
|
491
494
|
if exc.code == "OP_FAILED" and ddb_error:
|
|
492
495
|
raise ddb_error[-1]
|
|
493
496
|
raise
|
|
494
|
-
return _fold_read_output(component, out
|
|
497
|
+
return _fold_read_output(component, out)
|
|
495
498
|
|
|
496
499
|
|
|
497
500
|
def _fold_read_output(
|
|
498
501
|
component: Mapping[str, Any],
|
|
499
502
|
out: Any,
|
|
500
|
-
refs_markers: Mapping[str, List[str]],
|
|
501
503
|
) -> Any:
|
|
502
|
-
"""The documented mechanical, id-driven fold from the
|
|
504
|
+
"""The documented mechanical, id-driven fold from the v3 ``run_behavior``
|
|
503
505
|
output to the old assembled result shape (components.ts module doc; proven
|
|
504
506
|
golden-equal by ``__tests__/spec/components.test.ts``):
|
|
505
507
|
|
|
506
508
|
- a chained connection's flat per-element ``into`` keys re-nest along the
|
|
507
509
|
node-id path (``groups.items.group.permissions.items`` → move each
|
|
508
510
|
element's ``permissions`` under its ``group``);
|
|
509
|
-
- a
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
511
|
+
- a ``refs`` fan-out node's connection ``{items, cursor: None}`` is produced
|
|
512
|
+
ENTIRELY by bc's ``fanout`` node (v3, ``fanout_dedup_drop``): first-seen
|
|
513
|
+
dedupe (by the result body's ``dedupeKey`` field), dangling drop, and the
|
|
514
|
+
connection wrap all happen inside ``run_behavior`` now — graphddb folds it
|
|
515
|
+
through unchanged (the dedup/drop is no longer here);
|
|
516
|
+
- the implicitly-projected ``refs`` SOURCE id-list (``tagRefs``) is stripped
|
|
517
|
+
from the assembled root: it is a bare-return field the fanout ``over`` read,
|
|
518
|
+
absent from the caller-visible ``outputType`` (the annotation omits it), so
|
|
519
|
+
any root field NOT in ``outputType.root`` is dropped (the old
|
|
520
|
+
``_strip_implicit_sources``, now derived from the type-notation).
|
|
513
521
|
"""
|
|
514
522
|
output = component["output"]
|
|
515
523
|
body: List[Mapping[str, Any]] = list(component["body"])
|
|
@@ -535,23 +543,10 @@ def _fold_read_output(
|
|
|
535
543
|
)
|
|
536
544
|
val = out_obj[prop]
|
|
537
545
|
if "ref" in spec_node:
|
|
538
|
-
|
|
539
|
-
node
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
# Batched refs fan-out: aligned list → dedupe/drop → connection.
|
|
543
|
-
markers = refs_markers.get(node_id, [])
|
|
544
|
-
seen: set = set()
|
|
545
|
-
items: List[Any] = []
|
|
546
|
-
for i, item_body in enumerate(val or []):
|
|
547
|
-
marker = markers[i]
|
|
548
|
-
if item_body is None or marker in seen:
|
|
549
|
-
continue
|
|
550
|
-
seen.add(marker)
|
|
551
|
-
items.append(item_body)
|
|
552
|
-
result[prop] = {"items": items, "cursor": None}
|
|
553
|
-
else:
|
|
554
|
-
result[prop] = val
|
|
546
|
+
# A `refs` fan-out node result is ALREADY the deduped/dropped
|
|
547
|
+
# `{items, cursor: None}` connection (bc's fanout node owns it); a
|
|
548
|
+
# plain relation ref is its value verbatim. Either way: pass through.
|
|
549
|
+
result[prop] = val
|
|
555
550
|
elif "obj" in spec_node:
|
|
556
551
|
# Chained connection: {cursor, items:<augmented tail>} — re-nest the
|
|
557
552
|
# per-element flat `into` keys along each chain map's id.
|
|
@@ -565,13 +560,38 @@ def _fold_read_output(
|
|
|
565
560
|
f"components[]: unsupported output node for '{prop}' (fail-closed)"
|
|
566
561
|
)
|
|
567
562
|
|
|
568
|
-
# Implicit-strip
|
|
569
|
-
#
|
|
570
|
-
#
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
563
|
+
# Implicit refs-source strip (gap 5): a `refs` fan-out's SOURCE id-list
|
|
564
|
+
# (`tagRefs`) is physically projected onto the root ONLY to feed the fanout
|
|
565
|
+
# `over`; it is a bare-return field the caller never sees. The type-notation
|
|
566
|
+
# annotation encodes exactly this: the root NODE's `outType` carries the
|
|
567
|
+
# source, while the component `outputType.root` OMITS it. So strip precisely
|
|
568
|
+
# the field(s) a root-level `fanout.over` reads that are ABSENT from
|
|
569
|
+
# `outputType.root` (a field the query SELECTS stays in `outputType.root` and
|
|
570
|
+
# is kept). Untyped IR (legacy/hand-built, no annotation) strips nothing —
|
|
571
|
+
# the pre-#347 behavior; nested/non-root fanout over is emitter-rejected.
|
|
572
|
+
output_type = component.get("outputType")
|
|
573
|
+
root_out = (
|
|
574
|
+
output_type.get("obj", {}).get("root")
|
|
575
|
+
if isinstance(output_type, Mapping)
|
|
576
|
+
else None
|
|
577
|
+
)
|
|
578
|
+
kept = (
|
|
579
|
+
set(root_out["obj"].keys())
|
|
580
|
+
if isinstance(root_out, Mapping) and isinstance(root_out.get("obj"), Mapping)
|
|
581
|
+
else None
|
|
582
|
+
)
|
|
583
|
+
if kept is not None:
|
|
584
|
+
for node in body:
|
|
585
|
+
fo = node.get("fanout")
|
|
586
|
+
if fo is None:
|
|
587
|
+
continue
|
|
588
|
+
over = fo.get("over")
|
|
589
|
+
ref = over.get("ref") if isinstance(over, Mapping) else None
|
|
590
|
+
# `over: {ref: ["root", "<source>"]}` — the implicit driver field.
|
|
591
|
+
if isinstance(ref, list) and len(ref) == 2 and ref[0] == "root":
|
|
592
|
+
source = ref[1]
|
|
593
|
+
if source not in kept:
|
|
594
|
+
result.pop(source, None)
|
|
575
595
|
|
|
576
596
|
return result
|
|
577
597
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: graphddb-runtime
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.8
|
|
4
4
|
Summary: Thin DynamoDB executor for GraphDDB-generated Python repositories (single-operation core, issue #44).
|
|
5
5
|
License: MIT
|
|
6
6
|
Requires-Python: >=3.9
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
Requires-Dist: boto3>=1.26
|
|
9
|
-
Requires-Dist: behavior-contracts==0.
|
|
9
|
+
Requires-Dist: behavior-contracts==0.7.3
|
|
10
10
|
Provides-Extra: test
|
|
11
11
|
Requires-Dist: pytest>=7.0; extra == "test"
|
|
12
12
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "graphddb-runtime"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.8"
|
|
8
8
|
description = "Thin DynamoDB executor for GraphDDB-generated Python repositories (single-operation core, issue #44)."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -14,7 +14,7 @@ license = { text = "MIT" }
|
|
|
14
14
|
# canonicalisation) are delegated to the extracted shared package
|
|
15
15
|
# ``behavior-contracts`` (import name ``behavior_contracts``). The runtime
|
|
16
16
|
# imports it unconditionally, so it is a HARD dependency.
|
|
17
|
-
dependencies = ["boto3>=1.26", "behavior-contracts==0.
|
|
17
|
+
dependencies = ["boto3>=1.26", "behavior-contracts==0.7.3"]
|
|
18
18
|
|
|
19
19
|
[project.optional-dependencies]
|
|
20
20
|
test = ["pytest>=7.0"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/graphddb_runtime.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{graphddb_runtime-1.0.6 → graphddb_runtime-1.0.8}/tests/test_integration_binding_contract.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|