geotiff tests: consolidate GPU reader cluster (Sub-PR A of #2438)#2471
Merged
Conversation
Fold 10 GPU read-side regression files into a new ``xrspatial/geotiff/tests/gpu/test_reader.py``. Sections are grouped by the upstream issue number they pin: - #1605 -- window / band kwarg forwarding on GPU read - stripped multiband (#1582) -- 3-D (y, x, band) reads via stripped fallback - #1753 -- stripped no-georef windowed coord parity - #1732 -- stripped fallback forwards max_pixels/window/band - #1542 -- GPU read nodata promotion + attrs['nodata'] - #2097 -- write_geotiff_gpu rejects MinIsWhite (band-first guard) - #1876 -- chunks= is a real out-of-core dask graph - #2324 -- sidecar overview-inheritance georef parity - #2161 -- HTTP / fsspec URLs on the eager GPU path - #1909 -- GDS chunked path casts each chunk to declared dtype Tests-only. Each file's local ``_gpu_available`` / ``_gpu_only`` helper is replaced by the shared ``requires_gpu`` marker from ``_helpers/markers.py`` (aliased ``_gpu_only`` for ergonomic decoration). 66 tests collected (matches the baseline sum of the 10 deleted files). Cross-cutting touches: - ``docs/source/reference/release_gate_geotiff.rst`` -- GPU nodata row now cites ``gpu/test_reader.py``. - ``docs/source/reference/geotiff.rst`` -- prose pointer updated. - ``read/test_nodata.py`` -- docstring pointer updated. ``CLUSTER_AUDIT_GPU_A.md`` maps every old ``file::test`` to its new ``test_id`` and is deleted on a final commit on this branch before merge.
brendancol
commented
May 27, 2026
Contributor
Author
brendancol
left a comment
There was a problem hiding this comment.
PR Review: geotiff tests: consolidate GPU reader cluster (Sub-PR A of #2438)
Blockers (must fix before merge)
None.
Suggestions (should fix, not blocking)
xrspatial/geotiff/tests/gpu/test_reader.py:852-- the_gds_only_1876skip predicate dropped the runtime CUDA-availability probe from the originaltest_gpu_chunks_out_of_core_1876.py. The original_gds_onlygated on_HAS_GPU and _HAS_KVIKIO, where_HAS_GPUwascupy.cuda.is_available(). The replacement only checksimportlib.util.find_spec("cupy") is not None and _HAS_KVIKIO_1876. On a host with cupy installed but no working CUDA runtime, the GDS-path test will now try to run instead of skipping. Drop the manual skipif and stack@_gpu_only+@pytest.mark.skipif(not _HAS_KVIKIO_1876, reason=...)ontest_read_geotiff_gpu_chunks_uses_gds_path_when_available_1876.
Nits (optional improvements)
xrspatial/geotiff/tests/gpu/test_reader.py:286-339-- the stripped-multiband section is the only group with no_<issue>test-id suffix. The source filename had no issue number, but other consolidated PRs (e.g. #2469) suffix every renamed test. Consider tagging these_stripped_multibandfor grep-friendliness.xrspatial/geotiff/tests/gpu/test_reader.py:825--test_samples_hint_band_first_without_gpu_2097is intentionally CPU-runnable (matches the original) but the section header reads as if the whole #2097 block is GPU-only. A one-line comment noting that the last test in the section is CPU-only by design would save a reader the round-trip.xrspatial/geotiff/tests/CLUSTER_AUDIT_GPU_A.md-- the audit listsTestStrippedGpuWindowedBackendParity::test_dtype_parity[*]with a single[*]wildcard. The full parametrize list (three windows) is short enough to spell out and would make the audit grep-able per-case. Not load-bearing since the file is deleted pre-merge.
What looks good
- Test count matches baseline: 66 before, 66 after. Verified via
--collect-onlyagainst both states. - Shared
requires_gpumarker from_helpers/markers.pyreplaces ten per-file_gpu_available/_gpu_onlyreimplementations; the alias-as-import pattern matches PR #2469 / #2470. - The relative import
from ..integration.test_sidecar import _write_paircorrectly accounts for the extra directory level (tests/gpu/vs the old top-level location). - The three CPU-only originals (
test_samples_hint_band_first_without_gpu_2097,test_chunked_gpu_eager_paths_keep_source_dtype_1909,test_sidecar_without_geokeys_attrs_match_cpu_vs_dask_2324) keep their no-gate disposition rather than being forced behindrequires_gpu. A literal reading of the issue's "apply@requires_gpuon every test" rule would weaken these three; preserving the original CPU-runnable behaviour matches the precedent in PR #2469. - Three docs touchpoints (
release_gate_geotiff.rst,geotiff.rst,read/test_nodata.pydocstring) repointed off the deletedtest_gpu_nodata_1542.pytogpu/test_reader.py. Release-gate checklist-parity test passes. - Fixture and helper class names are issue-suffixed (
single_band_tiff_1605,_FakeArray2097,_RangeHandler2161, etc.) so sibling sub-PRs B/C/D sharing this module's namespace later cannot collide.
Checklist
- Algorithm matches reference/paper -- N/A, tests-only consolidation
- All implemented backends produce consistent results -- preserved from originals
- NaN handling is correct -- preserved from originals
- Edge cases are covered by tests -- preserved from originals
- Dask chunk boundaries handled correctly -- preserved from originals
- No premature materialization or unnecessary copies -- N/A
- Benchmark exists or is not needed -- N/A
- README feature matrix updated (if applicable) -- N/A
- Docstrings present and accurate -- module-level + per-section
- ``gpu/test_reader.py``: restore the ``cupy.cuda.is_available()`` runtime probe on the GDS path test by composing ``@_gpu_only`` (which uses the shared ``gpu_available()`` from ``_helpers/markers.py``) with a kvikio-only skipif. The original ``_gds_only`` checked both gates; the consolidated ``_gds_only_1876`` had dropped the CUDA check, so a host with cupy installed but no working CUDA runtime would have attempted to run the GDS test instead of skipping cleanly. - ``gpu/test_reader.py``: suffix the three stripped-multiband tests with ``_stripped_multiband`` so every test id in the module is grep-friendly (the source filename had no issue number). - ``gpu/test_reader.py``: note in the ``#2097`` section header that the last test in the section is intentionally CPU-only. - ``CLUSTER_AUDIT_GPU_A.md``: spell out individual parametrize ids for the ``TestStrippedGpuWindowedBackendParity`` cases and update the stripped-multiband entries to the new suffixed names.
brendancol
commented
May 27, 2026
Contributor
Author
brendancol
left a comment
There was a problem hiding this comment.
PR Review (round 2): geotiff tests: consolidate GPU reader cluster (Sub-PR A of #2438)
Blockers (must fix before merge)
None.
Suggestions (should fix, not blocking)
None.
Nits (optional improvements)
None.
What looks good
- Round-1 GDS skip predicate fix:
_gds_only_1876is gone. The GDS-path test now stacks@_gpu_only+@_requires_kvikio_1876, so the cupy + CUDA runtime probe lives in one place (_helpers/markers.py) and the kvikio probe stays local to its only consumer. - Round-1 stripped-multiband renames: the three tests carry the
_stripped_multibandsuffix, matching the issue-suffix convention used everywhere else in the module. - Round-1 #2097 section header: the new comment block explicitly calls out the CPU-only
test_samples_hint_band_first_without_gpu_2097so a future hand reading the section header doesn't try to "fix" its missing@_gpu_only. - Round-1 audit parametrize:
TestStrippedGpuWindowedBackendParity1753::test_{dtype,value}_paritynow lists[win0]/[win1]/[win2]with the window tuple beside each, so the audit is grep-able per-case. - 66 tests still collect and pass on the consolidated module.
Checklist
- Algorithm matches reference/paper -- N/A
- All implemented backends produce consistent results
- NaN handling is correct
- Edge cases are covered by tests
- Dask chunk boundaries handled correctly
- No premature materialization or unnecessary copies
- Benchmark exists or is not needed -- N/A
- README feature matrix updated (if applicable) -- N/A
- Docstrings present and accurate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #2438 (Sub-PR A). Cluster 14 of long-tail epic #2424.
Summary
Fold 10 GPU read-side regression files into a new
xrspatial/geotiff/tests/gpu/test_reader.py:test_gpu_window_band_1605.py-- window / band kwarg forwardingtest_gpu_stripped_multiband.py-- 3-D (y, x, band) via stripped fallbacktest_gpu_stripped_no_georef_window_1753.py-- stripped no-georef windowed coord paritytest_gpu_stripped_forwarding_1732.py-- stripped fallback forwards max_pixels/window/bandtest_gpu_nodata_1542.py-- GPU read nodata promotion + attrs['nodata']test_gpu_miniswhite_band_first_2097.py-- band-first MinIsWhite guardtest_gpu_chunks_out_of_core_1876.py-- chunks= out-of-core dask graphtest_gpu_sidecar_georef_parity_2324.py-- sidecar overview-inheritance georef paritytest_read_geotiff_gpu_url_eager_2161.py-- HTTP / fsspec URL eager pathtest_chunked_gpu_declared_dtype_1909.py-- GDS chunked declared-dtype castTests-only. Each file's local
_gpu_available/_gpu_onlyhelper is replaced by the sharedrequires_gpumarker from_helpers/markers.py(aliased_gpu_onlyfor ergonomic decoration). Test IDs that were not already issue-suffixed are renamed with the source issue number so sibling sections do not collide.66 tests collected (matches the baseline sum of the 10 deleted files).
The relative import in
test_gpu_sidecar_georef_parity_2324.py(.integration.test_sidecar._write_pair) was re-anchored to..integration.test_sidecarbecause the consolidated module sits one directory deeper.Cross-cutting touches
docs/source/reference/release_gate_geotiff.rst-- GPU nodata row now citesgpu/test_reader.py.docs/source/reference/geotiff.rst-- prose pointer updated.read/test_nodata.py-- docstring pointer updated.Audit
xrspatial/geotiff/tests/CLUSTER_AUDIT_GPU_A.mdmaps every oldfile::testto its newfile::test_id. The audit file is deleted on a final commit on this branch before merge.Verification
pytest xrspatial/geotiff/tests/gpu/test_reader.py: 66 passed (on a CUDA host).pytest xrspatial/geotiff/tests/release_gates/: 158 passed, 1 xfailed.xrspatial/geotiff/tests/collect: 5890 tests collected (no broken imports).Test plan
gpu/test_reader.pycollects + passes locally.Sub-PR layout
Sibling sub-PRs (B / C / D) for the writer / codec / kernels-and-kwargs clusters are independent and land on parallel branches under the same
gpu/subdirectory.