graphddb-runtime 1.0.8__tar.gz → 1.0.9__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.
Files changed (56) hide show
  1. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/PKG-INFO +1 -1
  2. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/behavior_exec.py +8 -4
  3. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/runtime.py +11 -31
  4. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/transactions.py +0 -30
  5. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime.egg-info/PKG-INFO +1 -1
  6. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/pyproject.toml +1 -1
  7. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/README.md +0 -0
  8. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/__init__.py +0 -0
  9. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/async_runtime.py +0 -0
  10. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/batch.py +0 -0
  11. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/concurrency.py +0 -0
  12. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/cursor.py +0 -0
  13. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/errors.py +0 -0
  14. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/filters.py +0 -0
  15. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/handler_registry.py +0 -0
  16. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/hydration.py +0 -0
  17. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/limits.py +0 -0
  18. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/middleware.py +0 -0
  19. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/per_key_cursor.py +0 -0
  20. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime/templates.py +0 -0
  21. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime.egg-info/SOURCES.txt +0 -0
  22. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime.egg-info/dependency_links.txt +0 -0
  23. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime.egg-info/requires.txt +0 -0
  24. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/graphddb_runtime.egg-info/top_level.txt +0 -0
  25. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/setup.cfg +0 -0
  26. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_atomic_add_command.py +0 -0
  27. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_concurrency.py +0 -0
  28. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_contract_runtime.py +0 -0
  29. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_crosslang_python_cells.py +0 -0
  30. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_description.py +0 -0
  31. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_description_followups.py +0 -0
  32. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_description_jsdoc.py +0 -0
  33. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_error_policy.py +0 -0
  34. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_generated_module.py +0 -0
  35. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_guard_eval.py +0 -0
  36. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_handler_registry.py +0 -0
  37. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration.py +0 -0
  38. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration_batch_write.py +0 -0
  39. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration_binding_contract.py +0 -0
  40. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration_command.py +0 -0
  41. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration_compose.py +0 -0
  42. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration_contract.py +0 -0
  43. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration_edge_derive.py +0 -0
  44. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration_edge_write.py +0 -0
  45. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration_events.py +0 -0
  46. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration_maintain.py +0 -0
  47. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration_middleware.py +0 -0
  48. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration_referential.py +0 -0
  49. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration_relations.py +0 -0
  50. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_integration_unique.py +0 -0
  51. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_maintain.py +0 -0
  52. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_middleware.py +0 -0
  53. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_relations.py +0 -0
  54. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_spec_version_guard.py +0 -0
  55. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_ttl.py +0 -0
  56. {graphddb_runtime-1.0.8 → graphddb_runtime-1.0.9}/tests/test_unit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graphddb-runtime
3
- Version: 1.0.8
3
+ Version: 1.0.9
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
@@ -755,10 +755,14 @@ def collect_transaction_items(
755
755
 
756
756
  if component_name == "PutItem":
757
757
  plain = _group(ports, "item")
758
- # A raw marker-row write (literalKey) carries its PK/SK verbatim; a
759
- # modeled Put derives PK/SK/GSI from the manifest entity (C4 config).
760
- if not ports.get("literalKey"):
761
- expander._add_key_attributes(entity, plain)
758
+ # A modeled Put's PK/SK/GSI key attributes now ride as DECLARATIVE
759
+ # `key.*` ports (attribute evaluated `concat`/`ref` template the
760
+ # same symbolic derivation reads/updates use, issue #350), so fold
761
+ # them into the written item directly. NO runtime manifest key
762
+ # derivation. A raw marker-row write (literalKey) carries its PK/SK
763
+ # verbatim in `item` and emits no `key.*` group, so the fold is a
764
+ # no-op for it.
765
+ plain.update(_group(ports, "key"))
762
766
  serialized = {k: rt._serializer.serialize(v) for k, v in plain.items()}
763
767
  put: Dict[str, Any] = {"TableName": table, "Item": serialized}
764
768
  expander._apply_condition(cond_spec, put, cond_params, None)
@@ -1951,7 +1951,12 @@ class GraphDDBRuntime:
1951
1951
  field: self._serializer.serialize(resolve_value_template(tmpl, params))
1952
1952
  for field, tmpl in spec.get("item", {}).items()
1953
1953
  }
1954
- self._add_key_attributes(spec["entity"], item, params)
1954
+ # A put's PK/SK/GSI key attributes ride as DECLARATIVE key
1955
+ # templates on `keyCondition` (the same symbolic derivation
1956
+ # read/update/delete use, issue #350); resolve + fold — NO runtime
1957
+ # manifest key derivation.
1958
+ for attr, tmpl in spec.get("keyCondition", {}).items():
1959
+ item[attr] = self._serializer.serialize(resolve_template(tmpl, params))
1955
1960
  requests.append({"PutRequest": {"Item": item}})
1956
1961
  else: # DeleteItem
1957
1962
  dynamo_key = {
@@ -2269,7 +2274,11 @@ class GraphDDBRuntime:
2269
2274
  field: self._serializer.serialize(resolve_value_template(tmpl, params))
2270
2275
  for field, tmpl in item_tmpl.items()
2271
2276
  }
2272
- self._add_key_attributes(spec["entity"], item, params)
2277
+ # A put's PK/SK/GSI key attributes ride as DECLARATIVE key templates on
2278
+ # `keyCondition` (the same symbolic derivation read/update/delete use,
2279
+ # issue #350); resolve + fold — NO runtime manifest key derivation.
2280
+ for attr, tmpl in spec.get("keyCondition", {}).items():
2281
+ item[attr] = self._serializer.serialize(resolve_template(tmpl, params))
2273
2282
 
2274
2283
  request: Dict[str, Any] = {
2275
2284
  "TableName": self._physical_table(spec["tableName"]),
@@ -2549,35 +2558,6 @@ class GraphDDBRuntime:
2549
2558
  values[alias] = self._serializer.serialize(resolved)
2550
2559
  request["ConditionExpression"] = condition["expression"]
2551
2560
 
2552
- def _add_key_attributes(
2553
- self, entity_name: str, item: Dict[str, Any], params: Mapping[str, Any]
2554
- ) -> None:
2555
- entity_meta = self._entities.get(entity_name, {})
2556
- plain = {
2557
- field: self._deserializer.deserialize(av) for field, av in item.items()
2558
- }
2559
- key = entity_meta.get("key")
2560
- if key:
2561
- # pkTemplate is self-contained (segment key model #51); no prefix.
2562
- pk = self._fill(key.get("pkTemplate") or "", plain)
2563
- item["PK"] = self._serializer.serialize(pk)
2564
- sk_tmpl = key.get("skTemplate")
2565
- if sk_tmpl is not None:
2566
- item["SK"] = self._serializer.serialize(self._fill(sk_tmpl, plain))
2567
-
2568
- for gsi in entity_meta.get("gsis", []):
2569
- index = gsi["indexName"]
2570
- pk_tmpl = gsi.get("pkTemplate")
2571
- sk_tmpl = gsi.get("skTemplate")
2572
- if pk_tmpl is not None and self._fillable(pk_tmpl, plain):
2573
- item[f"{index}PK"] = self._serializer.serialize(
2574
- self._fill(pk_tmpl, plain)
2575
- )
2576
- if sk_tmpl is not None and self._fillable(sk_tmpl, plain):
2577
- item[f"{index}SK"] = self._serializer.serialize(
2578
- self._fill(sk_tmpl, plain)
2579
- )
2580
-
2581
2561
  @staticmethod
2582
2562
  def _fillable(template: str, values: Mapping[str, Any]) -> bool:
2583
2563
  return all(
@@ -145,18 +145,6 @@ def _resolve_condition_tree(
145
145
  return out
146
146
 
147
147
 
148
- def _fill_key(template: str, item: Mapping[str, Any]) -> str:
149
- def repl(match: "re.Match[str]") -> str:
150
- name = match.group(0)[1:-1]
151
- return str(item.get(name, ""))
152
-
153
- return _PLACEHOLDER_RE.sub(repl, template)
154
-
155
-
156
- def _key_fillable(template: str, item: Mapping[str, Any]) -> bool:
157
- return all(m.group(0)[1:-1] in item for m in _PLACEHOLDER_RE.finditer(template))
158
-
159
-
160
148
  # ── SCP guard evaluation seam (issue #266, Phase 3 S6) ────────────────────────
161
149
  #
162
150
  # The branch-for-branch port of the TS ``evaluateGuard`` seam
@@ -450,24 +438,6 @@ class TransactionExpander:
450
438
  raise KeyError(f"unknown entity '{name}' in manifest")
451
439
  return entity
452
440
 
453
- def _add_key_attributes(self, entity_name: str, plain: Dict[str, Any]) -> None:
454
- entity = self._entity(entity_name)
455
- key = entity.get("key")
456
- if key:
457
- # pkTemplate is self-contained (segment key model #51); no prefix.
458
- plain["PK"] = _fill_key(key.get("pkTemplate") or "", plain)
459
- sk_tmpl = key.get("skTemplate")
460
- if sk_tmpl is not None:
461
- plain["SK"] = _fill_key(sk_tmpl, plain)
462
- for gsi in entity.get("gsis", []):
463
- index = gsi["indexName"]
464
- pk_tmpl = gsi.get("pkTemplate")
465
- sk_tmpl = gsi.get("skTemplate")
466
- if pk_tmpl is not None and _key_fillable(pk_tmpl, plain):
467
- plain[f"{index}PK"] = _fill_key(pk_tmpl, plain)
468
- if sk_tmpl is not None and _key_fillable(sk_tmpl, plain):
469
- plain[f"{index}SK"] = _fill_key(sk_tmpl, plain)
470
-
471
441
  def _apply_condition(
472
442
  self,
473
443
  condition: Optional[Mapping[str, Any]],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graphddb-runtime
3
- Version: 1.0.8
3
+ Version: 1.0.9
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "graphddb-runtime"
7
- version = "1.0.8"
7
+ version = "1.0.9"
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"