Skip to main content

Python First Verification

The first Python verification should prove async execution through a real provider, not just import generated modules.

1. Static package checks

python -m compileall generated/python-lib app tests
python -m pytest -q
rg 'def purpose|execute_for_list|execute_entities_for_list' generated/python-lib

Inspect function signatures. Every execution terminal must receive only ctx; a second data-service argument must produce Python's normal TypeError.

2. SQLite round trip

Use tmp_path so every test owns its database. Build a trusted context with the generated metadata and aiosqlite data service, ensure schema, save an audited entity, query it, recreate the provider/context, and query it again.

@pytest.mark.asyncio
async def test_sqlite_round_trip(tmp_path):
ctx = await new_sqlite_context(tmp_path / "first.db")
order = (
Q.customer_orders().comment("Create verification order")
.purpose("Verify SQLite persistence").new_entity(ctx)
)
order.update_order_number("VERIFY-10001")
await order.audit_as("Create verification fixture").save(ctx)

rows = await (
Q.customer_orders().comment("Read verification order")
.with_order_number_containing("VERIFY-10001")
.purpose("Verify persisted result")
.execute_entities_for_list(ctx)
)
assert len(rows) == 1

Use generated names from your package. The test is incomplete until a reopened connection also sees the row.

3. Loaded-state check

Run a partial projection containing a nullable field. Prove that a loaded null differs from an unselected field through the generated E facade. This prevents application logic from treating “not fetched” as a database null.

4. Governance failures

Add tests for missing comment, missing purpose, uninitialized context, missing audit_as, stale version, unknown dynamic field/operator, invalid range/paging, and attempts to supply tenant, actor, permissions, provider, or policy in JSON. Expected behavior is an explicit error, never an empty or broader query.

with pytest.raises(TypeError):
await executable.execute_for_list(ctx, data_service)

The explicit arity test protects the context-only API from regression.

5. Native SQL check

Retain a masked trace showing bound parameters, stable ordering, native aggregate SQL, and ROW_NUMBER() OVER (PARTITION BY ...) for an exact per-parent limit. Rows, count, sum, and facets must share the same active filter.

6. Regeneration check

Add a field, regenerate the whole package, reinstall it, compile, and rerun tests. Confirm centralized plural/predicate naming remains correct. Never preserve a manual edit under generated models/ or requests/.

Record Python/runtime/generator/provider versions, model hash, commands, exit codes, masked native response, and SQL shape as the baseline evidence.