Skip to content

test(gfql): run the #1788/#1790 suites on all four engines, in a lane that exists - #1807

Merged
lmeyerov merged 2 commits into
masterfrom
audit/gpu-engine-params-1788-1790
Jul 28, 2026
Merged

test(gfql): run the #1788/#1790 suites on all four engines, in a lane that exists#1807
lmeyerov merged 2 commits into
masterfrom
audit/gpu-engine-params-1788-1790

Conversation

@lmeyerov

Copy link
Copy Markdown
Contributor

CB3 (a) and (b): the two test files the owner flagged, both engine-parametrized properly and both now running in a lane that exists.

What was wrong

file before
test_rows_table_named_middle.py (#1788) pandas + polars only; module-level pytest.importorskip("polars"); not in bin/test-polars.sh → the test-gfql-core lane installs no polars, so the whole file skipped there and ran in no CI lane at all
test_rewrite_param_discard.py (#1790) named cuDF but skipped polars-gpu outright; also absent from bin/test-polars.sh, so every polars assertion in it was dead in CI

Both files pin which table a query returns — engine-agnostic semantics, not a polars question.

What this changes

Fixed engine list (pandas, cudf, polars, polars-gpu) — deliberately not available_nonpandas_engines(), which builds its list by importability so a missing engine vanishes from the report instead of showing as SKIPPED. Both files added to bin/test-polars.sh; the module-level importorskip is gone, which also makes 5 pandas cases live in test-gfql-core.

Two probe traps, both hit by trying rather than reasoned about

1. A probe that runs the shape under test disarms its own file. My first version smoke-tested with rows(table='edges'). Reverting the #1788 table guard then made the probe raise, and all 20 parameters reported SKIPPED instead of failing — a regression disguised as a missing environment. The smoke query is now a plain traversal with no rows() in it.

2. A probe that swallows every exception is worse than no probe. A transient MemoryError: std::bad_alloc: out_of_memory: CUDA error (failed to allocate 32 bytes) … cudaErrorMemoryAllocation in a fresh GPU container silently dropped cuDF from a run that otherwise passed. A skipped GPU parameter reads as evidence of passing. engine_skip_reason (new, in polars_test_utils.py) now classifies: a missing module skips, a recognisable GPU-stack error skips with its text quoted in the skip reason, and any other failure propagates.

GPU receipts

dgx GB10 · graphistry/test-rapids-official:26.02-gfql-polars · docker run --gpus all · cuDF 26.02.01 / polars 1.35.2:

45 passed, 3 xfailed, 0 skipped        (repeated — all four engines running)

Mutation-checked on the same box, reverting the #1788 and #1790 table guards:

24 failed, 21 passed, 3 xfailed, 0 skipped
   6 [pandas]   6 [cudf]   6 [polars]   6 [polars-gpu]

Evenly spread across all four engines, so the added parameters are not decorative.

Two real gaps the new parameters surfaced — pinned, not papered over

Strict xfails in both cases, so whoever fixes either is told to delete the marker rather than leaving a stale "known gap" behind.

Runtime delta: zero

No production line changed — the diff is two test files, one shared test helper, bin/test-polars.sh and the CHANGELOG. Per CB5 no pyg-bench lane run is required, and that claim is checkable from the diff rather than merely asserted.

Note for the reviewer

bin/test-polars.sh is also touched by #1801 and by the CA4 allowlist PR; the edits are to different lines of the same array and are independently mergeable.

🤖 Generated with Claude Code

https://claude.ai/code/session_015YsqAZQLbqjSDrYSFz2GoB

@lmeyerov

Copy link
Copy Markdown
Contributor Author

Overlap note for whoever merges this. #1805 (fix/gfql-polars-lane-invisible-tests, opened concurrently) also adds test_rows_table_named_middle.py and test_rewrite_param_discard.py to bin/test-polars.sh, and restructures that array — so the two will conflict textually even though they agree on the outcome.

Left in here deliberately rather than removed: this PR's whole point is that these two files' non-pandas parameters actually execute, and dropping the lane lines would make that contingent on a PR that has not landed. If #1805 goes first, resolve by keeping #1805's array and dropping the two lines from this diff — nothing else here touches that file.

The substance of this PR (the four-engine parametrization, the classified availability check, the GPU receipts, and the two strict xfails for #1803/#1804) is independent of #1805 and does not overlap it.

Also worth flagging against #1797 (the polars coverage cell sitting at its timeout ceiling): this PR's additions measured ~15s per lane run locally, and CI came back green on all 77 checks including every test-polars matrix cell — so it did not tip that cell over. That is an observation from one run, not a guarantee.

… that exists (CB3 a+b)

Both suites tested the semantics of WHICH TABLE a query returns — engine-agnostic
semantics — on pandas + polars only, and neither file was in `bin/test-polars.sh`.
`test_rows_table_named_middle.py` also carried a module-level
`pytest.importorskip("polars")`, and the `test-gfql-core` lane installs no polars,
so that file ran in NO CI LANE AT ALL. `test_rewrite_param_discard.py` named cuDF
but skipped polars-gpu outright.

Now: fixed engine list (pandas / cuDF / polars / polars-gpu), classified
availability check, both files in the polars lane, module-level importorskip
dropped (5 pandas cases become live in test-gfql-core).

TWO PROBE TRAPS, BOTH HIT BY TRYING RATHER THAN REASONED ABOUT:

 * A probe that runs THE SHAPE UNDER TEST disarms its own file. Reverting the
   #1788 `table` guard made the probe raise, and all 20 parameters reported
   SKIPPED instead of failing. The smoke query is now a plain traversal with no
   `rows()` call in it.
 * A probe that SWALLOWS every exception is worse than none. A transient
   `MemoryError: ... cudaErrorMemoryAllocation` in a fresh GPU container silently
   dropped cuDF from a run that otherwise passed — and a skipped GPU parameter
   reads as evidence of passing. `engine_skip_reason` now CLASSIFIES: a missing
   module skips, a recognisable GPU-stack error skips with its text quoted, and
   ANY other failure propagates.

It is deliberately not `available_nonpandas_engines()`, which builds its list by
importability, so a missing engine vanishes from the report rather than showing
as SKIPPED.

GPU RECEIPTS — dgx GB10, `graphistry/test-rapids-official:26.02-gfql-polars`,
`docker run --gpus all`, cuDF 26.02.01 / polars 1.35.2:
  45 passed, 3 xfailed, 0 skipped (repeated; all four engines running)
MUTATION-CHECKED on the same box by reverting the #1788 and #1790 `table` guards:
  24 failed / 0 skipped, spread EVENLY over the four engines (6 each)
so the added parameters are not decorative.

TWO REAL GAPS SURFACED BY THE NEW PARAMETERS, pinned strict-xfail, not papered over:
 * #1803 — the indexed bindings bypass gate admits only (PANDAS, CUDF, POLARS),
   while the native polars chain hands it `Engine.POLARS_GPU` whenever the GPU
   target is active. So polars-gpu ALWAYS reports `served: False,
   reason: 'unsupported_engine'` and silently runs the canonical scan. Values are
   unaffected; the optimization is lost with no signal.
 * #1804 — the native polars bindings builder never receives `alias_prefilters`
   (5 rows on pandas/cuDF vs 12 on polars). Already xfailed before this change,
   but with no issue number, so there was nothing to close and nothing to find.

RUNTIME DELTA: zero. No production line changed — the diff is two test files, a
shared test helper, `bin/test-polars.sh` and the CHANGELOG — so no pyg-bench lane
run is required (CB5), and that claim is checkable from the diff.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015YsqAZQLbqjSDrYSFz2GoB
@lmeyerov
lmeyerov force-pushed the audit/gpu-engine-params-1788-1790 branch from f913f1a to b07e330 Compare July 28, 2026 03:01
return None


def engine_skip_reason(engine, smoke):

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static typing

Resolves both conflicts and corrects two defects the conflict exposed.

bin/test-polars.sh -- take master's version unchanged. This branch adds
graphistry/tests/compute/gfql/test_rows_table_named_middle.py and
test_rewrite_param_discard.py to POLARS_TEST_FILES, but #1805 (49db91c,
this branch's own merge-base) already added both. Keeping the branch side
would list each file twice, so the polars lane would run both modules twice
-- and that lane's py3.12 cell is the coverage cell, currently 442s against
a 600s cap. Master's version also carries #1814's xdist plumbing, which the
branch side predates.

CHANGELOG.md -- the entry claimed "neither file was in bin/test-polars.sh,
so test_rows_table_named_middle.py ... ran in no CI lane at all". That is
false at this branch's base: both files are listed there at lines 43 and 50.
Rewritten to the residual that is true -- the suites were parametrized over
pandas + polars only, so cuDF and polars-gpu never exercised the table
guards; and the module-level pytest.importorskip("polars") skipped the whole
file in test-gfql-core, so its pandas cases ran only in the polars lane.
The measured claims (45 passed / 3 xfailed / 0 skipped on GB10; 24 mutation
failures, 6 per engine) are unchanged.

Also types engine_skip_reason, per review: the engine -> required-modules
map is hoisted to a module-level Mapping[str, Tuple[str, ...]] constant
rather than rebuilt inline per call, the signature is
(engine: str, smoke: Callable[[], object]) -> Optional[str], and
gpu_environment_reason's "str | None" string annotation is normalized to
Optional[str] to match (this file is imported under py3.8 lanes).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YYZRXegrALuXd3NHH5evqx
@lmeyerov

Copy link
Copy Markdown
Contributor Author

Merged master (a10173575) in as f6fa7fb7e. Both conflicts resolved, and the conflict exposed two defects in this branch that I fixed rather than carried forward.

Defect 1 — bin/test-polars.sh would have run two modules twice. This branch adds test_rows_table_named_middle.py and test_rewrite_param_discard.py to POLARS_TEST_FILES. But #1805 — which is this branch's merge-base (49db91cc9) — already added both, at lines 43 and 50. So the addition was redundant at the moment it was written, and taking the branch side would have listed each path twice and run each module twice. That lane's py3.12 cell is the coverage cell and has been up against its budget: 442s on master's latest green run, cap 600s. Resolution is master's file verbatim, which also keeps #1814's xdist plumbing that the branch side predates. bin/test-polars.sh no longer appears in this PR's diff at all.

Defect 2 — a false claim in the CHANGELOG. The entry said "neither file was in bin/test-polars.sh, so test_rows_table_named_middle.py … ran in no CI lane at all". Same root cause: both files were listed at the base, so the polars params did run. Rewritten to the residual that is actually true — the suites were parametrized over pandas + polars only, so cuDF and polars-gpu never exercised the table guards these suites exist to pin; and the module-level pytest.importorskip("polars") skipped the whole file in test-gfql-core, so its pandas cases ran only in the polars lane. Every measured claim is untouched (45 passed / 3 xfailed / 0 skipped on GB10; 24 mutation failures, 6 per engine).

Typing on engine_skip_reason, per review. The engine → required-modules map was a dict literal rebuilt inline on every call inside the for; it is now a module-level _ENGINE_REQUIRED_MODULES: Mapping[str, Tuple[str, ...]]. Signature is (engine: str, smoke: Callable[[], object]) -> Optional[str]. gpu_environment_reason's "str | None" string annotation is normalized to Optional[str] to match — this module is imported under the py3.8 lanes, so the deferred-annotation form was load-bearing, not stylistic. flake8 and mypy 1.18.2 clean under the repo config.

Net diff vs master is now CHANGELOG + the three files under graphistry/tests/compute/gfql/ — no production line and no CI-manifest line changed.

@lmeyerov
lmeyerov merged commit d0515d3 into master Jul 28, 2026
57 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant