Skip to content

Commit cee1dd0

Browse files
lmeyerovclaude
andcommitted
test(gfql): stop test_index.py fabricating 20 failures without cudf_polars
`_engines()` appended `"polars-gpu"` when **`cudf`** imported. But `polars-gpu` is the `cudf_polars` GPU collect target and raises ImportError: GFQL engine='polars-gpu' requires the RAPIDS cudf_polars stack without it. So any box with cuDF installed and `cudf_polars` absent — a common developer configuration — got 20 failures indistinguishable from product breakage, in a file that IS listed in `bin/test-polars.sh`. CI never caught it because that lane installs neither package, so the parameter did not exist there: a gate can only fabricate failures where it is never exercised. Measured on a box with cuDF 25.10 and no `cudf_polars`: before 20 failed, 116 passed after 0 failed, 105 passed SCOPE NOTE. This branch originally carried the whole CA4 allowlist change (seven files added to `bin/test-polars.sh`). PR #1805 (`fix/gfql-polars-lane-invisible-tests`), opened concurrently, is a SUPERSET of that list AND adds `test_polars_lane_completeness.py`, a guard that fails when a polars-parametrized file is missing from the lane — which makes the fix permanent rather than one-time. It also lands the same pandas-3 case-mapping xfail, against the same issue. Reduced to the one hunk #1805 does not contain, so the owner reviews the allowlist once instead of twice. RUNTIME DELTA: zero. One test file's engine list and a CHANGELOG line; no pyg-bench lane run required (CB5), checkable from the diff. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015YsqAZQLbqjSDrYSFz2GoB
1 parent 49db91c commit cee1dd0

2 files changed

Lines changed: 8 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
2424
- **Seeded typed-hop property projection keeps its fast path through DISTINCT / ORDER BY / SKIP / LIMIT**: those trailing row ops are plain frame operations, so the fast path now delegates them to the canonical chain instead of declining the whole query.
2525

2626
### Changed
27+
- **The polars-engine index tests stop fabricating 20 failures on a cuDF-without-`cudf_polars` box** (tests only; zero runtime delta). `graphistry/tests/compute/gfql/index/test_index.py` built its engine list by appending `"polars-gpu"` when **`cudf`** imported — but `polars-gpu` is the `cudf_polars` GPU collect target and raises `ImportError: GFQL engine='polars-gpu' requires the RAPIDS cudf_polars stack` without it. So any environment with cuDF installed and `cudf_polars` absent (a common developer configuration) got 20 failures indistinguishable from product breakage, in a file that IS in the polars lane. CI never caught it because that lane installs neither package, so the parameter did not exist there — a gate can only fabricate failures where it is never exercised. The gate now tests `cudf_polars`. Measured: 20 failed / 116 passed before, 105 passed / 0 failed after, on a box with cuDF 25.10 and no `cudf_polars`.
2728
- **`is_lazy` is a type predicate, so the polars engine's eager/lazy split is checked instead of asserted**: `dtypes.is_lazy` decides WHICH member of the two-member `PolarsFrame` union a frame is, but it was declared `-> bool`, so that answer was discarded at the call boundary — an eager-only attribute (`.height`, `.columns`, `.schema`) reached after a lazy guard was unprovable, and the native polars chain closed the gap with `cast("pl.DataFrame", frame)`. A cast is not a type: it re-asserts, unchecked, the exact fact the predicate had just established, once per call site, and a wrong one surfaces as a production `AttributeError` rather than a CI error. `is_lazy` is now declared `-> TypeIs["pl.LazyFrame"]` (PEP 742), which narrows the *negative* branch as well as the positive — the eager side is the one that needed it, so `TypeGuard` would not have done — and the cast is gone. Four previously untyped chain-combine helpers (`_semi`, `_combine_edges`, `_apply_node_names`, and the `_known_empty` guard) now carry real signatures: `_semi`'s two frames share the `PolarsT` TypeVar because polars joins do not mix eagerness, and the two combine helpers take the `_LazyShim` collect-once duck-type they are actually called with. Typing `_apply_node_names` also retired a `getattr(next_step, "edges_empty", None)` — the shim declares that tri-state in `__slots__`, so a typo is now a checker error instead of a silent `None` that would have re-armed the very cardinality gate the guard disarms. Internal only: no runtime behaviour, no public API, and the `TypeIs` import is `TYPE_CHECKING`-only, so no new runtime dependency floor.
2829
- **GFQL execution context is declared rather than attached at runtime**: the private `_gfql_*` per-execution fields (index policy and registry, row-pipeline base graph, carried seed nodes, edge aliases, shortest-path backend, and the indexed-bindings handoff) are now declared on `Plottable` with defaults on `PlotterBase`, instead of being set with `setattr` and read back with `getattr(..., default)`. No public API or behaviour change; internal call sites are typed, and hand-rolled `Plottable` stand-ins must now construct the full context.
2930

graphistry/tests/compute/gfql/index/test_index.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,13 @@ def _engines():
2929
import polars # noqa
3030
out.append("polars")
3131
try:
32-
import cudf # noqa
32+
# `cudf_polars`, NOT `cudf`: engine='polars-gpu' is the cudf_polars GPU collect
33+
# target and raises `ImportError: GFQL engine='polars-gpu' requires the RAPIDS
34+
# cudf_polars stack` without it. Gating on `cudf` FABRICATED 20 failures on every
35+
# box that has cuDF but not cudf_polars — a real configuration, and the failures
36+
# are indistinguishable from product breakage. CI never caught it because its
37+
# polars lane installs neither, so the parameter simply did not exist there.
38+
import cudf_polars # noqa
3339
out.append("polars-gpu")
3440
except Exception:
3541
pass

0 commit comments

Comments
 (0)