graphddb-runtime 1.0.1__tar.gz → 1.0.3__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.1 → graphddb_runtime-1.0.3}/PKG-INFO +2 -2
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/runtime.py +25 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime.egg-info/PKG-INFO +2 -2
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime.egg-info/requires.txt +1 -1
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/pyproject.toml +2 -2
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_atomic_add_command.py +16 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_unit.py +8 -4
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/README.md +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/__init__.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/async_runtime.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/batch.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/behavior_exec.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/concurrency.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/cursor.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/errors.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/filters.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/handler_registry.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/hydration.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/limits.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/middleware.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/per_key_cursor.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/templates.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime/transactions.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime.egg-info/SOURCES.txt +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime.egg-info/dependency_links.txt +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/graphddb_runtime.egg-info/top_level.txt +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/setup.cfg +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_concurrency.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_contract_runtime.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_crosslang_python_cells.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_description.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_description_followups.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_description_jsdoc.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_error_policy.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_generated_module.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_guard_eval.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_handler_registry.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration_batch_write.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration_binding_contract.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration_command.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration_compose.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration_contract.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration_edge_derive.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration_edge_write.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration_events.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration_maintain.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration_middleware.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration_referential.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration_relations.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_integration_unique.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_maintain.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_middleware.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_relations.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_spec_version_guard.py +0 -0
- {graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/tests/test_ttl.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.3
|
|
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.6.0
|
|
10
10
|
Provides-Extra: test
|
|
11
11
|
Requires-Dist: pytest>=7.0; extra == "test"
|
|
12
12
|
|
|
@@ -2327,6 +2327,31 @@ class GraphDDBRuntime:
|
|
|
2327
2327
|
command_id, spec, params, names, values, sets
|
|
2328
2328
|
)
|
|
2329
2329
|
|
|
2330
|
+
# #333: an UpdateItem that CREATES a row (create-if-absent) must carry the
|
|
2331
|
+
# model's key-source field attributes, like PutItem does. SET each field a
|
|
2332
|
+
# `keyCondition` template references from the command's key params. A
|
|
2333
|
+
# key-source field is immutable for a given key, so a plain SET to the
|
|
2334
|
+
# key-derived value is a safe no-op on existing rows and populates it on
|
|
2335
|
+
# create. Without this, a row first created by an update lacks e.g. `child`,
|
|
2336
|
+
# so a projection of that field returns empty. (Skipped when add_only — the
|
|
2337
|
+
# #301 fallback only fires on rows that already exist.)
|
|
2338
|
+
seen_ks: set = set()
|
|
2339
|
+
for tmpl in spec["keyCondition"].values():
|
|
2340
|
+
for m in _PLACEHOLDER_RE.finditer(str(tmpl)):
|
|
2341
|
+
field = m.group(0)[1:-1]
|
|
2342
|
+
if "." in field or field in seen_ks or field not in params:
|
|
2343
|
+
continue
|
|
2344
|
+
raw = params[field]
|
|
2345
|
+
if raw is None:
|
|
2346
|
+
continue
|
|
2347
|
+
seen_ks.add(field)
|
|
2348
|
+
idx = len(seen_ks) - 1
|
|
2349
|
+
n = f"#ks{idx}"
|
|
2350
|
+
v = f":ks{idx}"
|
|
2351
|
+
names[n] = field
|
|
2352
|
+
values[v] = self._serializer.serialize(raw)
|
|
2353
|
+
sets.append(f"{n} = {v}")
|
|
2354
|
+
|
|
2330
2355
|
# #301: atomic-`ADD` clauses (`ADD #a :d`, a caller `param.number()` delta).
|
|
2331
2356
|
# Built AFTER the SET so an ADD-only expression (`add_only`, or an update
|
|
2332
2357
|
# whose SET change set is empty) is legal — DynamoDB's `SET … ADD …` is one
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: graphddb-runtime
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
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.6.0
|
|
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.3"
|
|
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.6.0"]
|
|
18
18
|
|
|
19
19
|
[project.optional-dependencies]
|
|
20
20
|
test = ["pytest>=7.0"]
|
|
@@ -168,6 +168,22 @@ def test_mark_fallback_add_only_on_condition_fail():
|
|
|
168
168
|
assert any(v == {"N": "1"} for v in fvals.values()), fvals
|
|
169
169
|
|
|
170
170
|
|
|
171
|
+
def test_mark_stores_key_source_fields():
|
|
172
|
+
"""#333: an UpdateItem that CREATES the row must persist the key-source field
|
|
173
|
+
attributes (part/child) via a plain SET — like PutItem — so a row first created
|
|
174
|
+
by the mark carries them and a projection of e.g. ``child`` is not empty."""
|
|
175
|
+
client = _MarkClient(fail_first=False)
|
|
176
|
+
rt = _mark_runtime(client)
|
|
177
|
+
|
|
178
|
+
rt.execute_command("StatsTreeCmd__mark", _MARK_PARAMS)
|
|
179
|
+
|
|
180
|
+
req = client.updates[0]
|
|
181
|
+
assert _has_set_clause(req["UpdateExpression"]), req["UpdateExpression"]
|
|
182
|
+
names = set(req["ExpressionAttributeNames"].values())
|
|
183
|
+
for field in ("part", "child"):
|
|
184
|
+
assert field in names, f"key-source field {field!r} must be SET (#333); {names}"
|
|
185
|
+
|
|
186
|
+
|
|
171
187
|
def test_mark_non_ccf_error_propagates():
|
|
172
188
|
"""A NON-condition error on the primary must NOT be swallowed by the two-stage —
|
|
173
189
|
it propagates and no ADD-only fallback fires. Parity with the Rust
|
|
@@ -253,9 +253,12 @@ def test_update_item_builds_set_expression():
|
|
|
253
253
|
method, req = client.calls[0]
|
|
254
254
|
assert method == "update_item"
|
|
255
255
|
assert plain(req["Key"]) == {"PK": "USER#alice", "SK": "PROFILE"}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
256
|
+
# #333: the update also SETs the key-source field(s) the PK/SK templates
|
|
257
|
+
# reference (here `userId`, from `USER#{userId}`) so a row first created by this
|
|
258
|
+
# update carries them like a PutItem would — a no-op on an existing row.
|
|
259
|
+
assert req["UpdateExpression"] == "SET #c0 = :c0, #ks0 = :ks0"
|
|
260
|
+
assert req["ExpressionAttributeNames"] == {"#c0": "status", "#ks0": "userId"}
|
|
261
|
+
assert plain(req["ExpressionAttributeValues"]) == {":c0": "disabled", ":ks0": "alice"}
|
|
259
262
|
|
|
260
263
|
|
|
261
264
|
def test_update_item_rederives_affected_gsi_key():
|
|
@@ -303,7 +306,8 @@ def test_update_item_does_not_touch_unaffected_gsi():
|
|
|
303
306
|
rt.execute_command("UserConfCommands__disableUser", {"userId": "alice", "status": "disabled"})
|
|
304
307
|
_method, req = client.calls[0]
|
|
305
308
|
assert "GSI1PK" not in req["ExpressionAttributeNames"].values()
|
|
306
|
-
|
|
309
|
+
# #333: the change SET plus the key-source SET (`userId`); no GSI re-derive.
|
|
310
|
+
assert req["UpdateExpression"] == "SET #c0 = :c0, #ks0 = :ks0"
|
|
307
311
|
|
|
308
312
|
|
|
309
313
|
def test_put_item_injects_key_attributes():
|
|
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.1 → graphddb_runtime-1.0.3}/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
|
{graphddb_runtime-1.0.1 → graphddb_runtime-1.0.3}/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
|