feat: assert no unnamed nodes and no null or empty values in final graph QC - #106
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughStage-7 graph QC now recursively rejects null or empty values and rejects nodes without non-empty names. The scan reports capped violation examples, while ChangesStage-7 Graph QC
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to This change strengthens final graph validation for unnamed, null, and empty values while documenting and testing the behavior; no actionable merge-blocking risk remains beyond normal checks and review. Sequence Diagram(s)sequenceDiagram
participant study_kgx
participant _scan_ndjson
participant _is_empty_or_null
study_kgx->>_scan_ndjson: scan emitted NDJSON
_scan_ndjson->>_is_empty_or_null: inspect field values recursively
_is_empty_or_null-->>_scan_ndjson: return empty or null result
_scan_ndjson-->>study_kgx: return QC counters
study_kgx-->>study_kgx: emit capped violations
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Cut 13.0.0 and bump the package version in pyproject.toml, uv.lock, and CITATION.cff. Major: three breaking changes since 12.1.0. The inlined supporting study now carries current Biolink Study metadata with disjoint ids and names and no `#` composition; biolink-model 4.4.4 types the statistical edge slots, so `effect_size` ships as a real JSON number and `statistical_significance_qualifier` rides the edge as a bare enum token (both 99099a1); and an unpaired `effect_size`/`effect_type` half is now DROPPED with an `UnpairedEffectAnnotationWarning` instead of failing the section, retiring the `annotation-effect-size-without-type` / `annotation-effect-type-without-size` codes (#105). Also ships the two final-graph QC assertion sets (#106, #107), the resolve_batch single-materialization win (#110), and the agent's task pre-rendering, planning-off, improve-round cap, and build memoization (#113). The legacy TableConfigs importer (#105) is deliberately absent from the changelog: it landed and was removed (58787f4) inside this window, so it never appeared in a released version and is a net no-op for users. main was red at 7140c37; fixed here so the release is cuttable. Both failures are #112 fixtures/expectations written against biolink-model 4.4.3 and merged after the 4.4.4 bump landed: - The vendored DAKP configs listed `AffinityMeasurement` in `avoid:`, a class 4.4.4 renamed to `ProteinLigandAssayResult`. DAKP generates `avoid` as the sorted complement of each side's prioritize tuple, so the old name is a 4.4.3 generation artifact rather than an intentional deviation; rewritten in place and recorded in the fixture README. - test_copysign_transformation_in_pipeline asserted `effect_size == "-0.85"`, the pre-4.4.4 `{:.4g}` string form. It is a real JSON number now. Deliberate Biolink departures are untouched: p-value columns keep their controlled scientific notation despite the model typing them `float`, and `approval_ids` remains a curated pending pass-through. docs/cli.md's validate-kgx section still printed `biolink-model 4.4.3` and claimed `effect_size`/`effect_type` were pending; rewritten around the fields that are actually pending today (`approval_ids` plus the KGX denormalized carryovers), noting the pair graduated when 4.4.4 shipped #1774. Testing: - uv run pytest -q -> 1047 passed, 15 skipped (94% coverage) - uv run ruff check . && uv run ruff format --check . && uv run pyright -> clean / 0 errors Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HZQ8rLfhvtyErcq9S4Ao6b
The
--qcstage-7 study pass now asserts that every node in the final NDJSON carries a name and that no field in either output file is null or empty — checked recursively — failing the build on the first violation instead of letting it ship.Study assertions (
src/tablassert/study.py)unnamed-nodes: a node record whosenamekey is missing,null, or strips to empty fails the study; offenders are keyed by node id (or<no id>), capped at 10 examples like the other assertions. On pipeline output the missing-key branch is what fires — the writer'sstrip_nullsdeletes empty and null-like names before the file is written, and was verified to apply to the nodes file too (dedup_stream(nodes_tmp, is_edges=False)→finalize_record→strip_nullsinrust/src/ndjson.rs).empty-or-null-values: any field in the nodes or edges file whose value is JSONnull, a string that strips to empty, or an empty container fails, counted per field with examples likename (2); recursion means a null nested inside anattributeslist counts under its top-level field.Design
strip_nulls(rust/src/json.rs) scrubs dict entries at every depth but passes array scalars (["x", ""],["x", null]) and emptied nested objects ({},[{}]) through verbatim; the study asserts the stronger no-empty-anywhere contract so the first such shape to reach an emitted file fails loudly rather than shipping silently. Deferred: tightening the Ruststrip_nullsto scrub array scalars and drop emptied nested dicts, so writer and study agree at the source.NA/NaN/null/noneare dropped by the writer's bad-token sweep but are neither null nor empty; the assertion targets absent values, not spellings.original_*exemption narrowed to whitespace. Verbatim source padding stays exempt fromwhitespace-values(the PR fix(qc): allow whitespace in original_* fields in the KGX study #90 convention), but empty/nulloriginal_*values are now flagged — the writer drops them everywhere, so they are never legitimate. Accepted caveat: a whitespace-only value intentionally trips bothwhitespace-valuesandempty-or-null-values.0andfalseare kept by the writer and pass the study (p_value: 0,negated: false), pinned by test.Docs
docs/cli.md(--qcrow), thebuild_kgdocstring insrc/tablassert/cli.py(rendered by--help), andCHANGELOG.md(Unreleased).Testing
uv run --no-sync pytest -q --no-cov→1050 passed, 15 skippeduv run --no-sync pytest tests/test_study.py --no-cov -q→21 passed,study.pyat 100% line coverageuv run --no-sync ruff check+ruff format --check→ clean;uv run --no-sync pyright src/tablassert/study.py src/tablassert/cli.py tests/test_study.py→0 errorsSummary by CodeRabbit
Quality Checks
build-kg --qcauditing to detect unnamed nodes, duplicate or undeclared nodes, malformed lines, whitespace issues, and recursively empty or null values."NA"and"null".Documentation
Tests