Summary
to_geotiff rejects two combos that write_geotiff_gpu accepts and processes successfully:
to_geotiff(gpu=True, path=BytesIO) raises ValueError ("gpu=True is not supported for file-like destinations"). write_geotiff_gpu(cupy_data, BytesIO) writes valid TIFF bytes to the buffer.
to_geotiff(cog=True, path=BytesIO) raises ValueError. write_geotiff_gpu(cupy_data, BytesIO, cog=True) writes a COG to the buffer.
The path : str annotation on write_geotiff_gpu says only string paths are accepted, so the file-like support is undocumented yet functional. The cog=True block on to_geotiff predates the BytesIO support that landed for the eager numpy path.
Reproducer
import io, numpy as np, xarray as xr, cupy
import xrspatial.geotiff as geo
arr = np.arange(64*64, dtype=np.float32).reshape(64, 64)
da_cpu = xr.DataArray(arr, dims=['y', 'x'])
da_gpu = xr.DataArray(cupy.asarray(arr), dims=['y', 'x'])
# 1. to_geotiff(gpu=True, file-like) rejected
buf = io.BytesIO()
try:
geo.to_geotiff(da_gpu, buf) # auto-dispatches to GPU
except ValueError as e:
print('to_geotiff(gpu_data, BytesIO):', e)
# 2. write_geotiff_gpu(file-like) accepted (round-trips fine)
buf = io.BytesIO()
geo.write_geotiff_gpu(da_gpu, buf)
print('write_geotiff_gpu(BytesIO): bytes=', len(buf.getvalue()))
# 3. write_geotiff_gpu(file-like, cog=True) accepted
buf = io.BytesIO()
geo.write_geotiff_gpu(da_gpu, buf, cog=True)
print('write_geotiff_gpu(BytesIO, cog=True): bytes=', len(buf.getvalue()))
Severity
MEDIUM (Cat 5, public API surface drift). to_geotiff is the documented preferred entry point; users who follow that path miss capabilities that the explicit GPU writer exposes silently.
Fix options
- Drop the file-like block in
to_geotiff for the GPU path now that write_geotiff_gpu proves it works. Verify the BytesIO round-trip through open_geotiff in CI.
- Drop the
cog=True file-like block in to_geotiff. The CPU COG assembler also writes to bytes via _write_bytes; the comment about "atomic rename" is only true for the streaming path.
- Add matching
ValueError guards to write_geotiff_gpu to mirror to_geotiff's stricter contract. Document path as "string path only" in both writer docstrings.
Option 1 + 2 expose existing capabilities. Option 3 is the conservative direction.
Related
This is the GPU-write analog to #1511 (which fixed reader file-like support). The reader side now consistently accepts BytesIO; the writer side still has the gpu=True and cog=True gates on to_geotiff that don't apply to the lower-layer writer.
Deprecation impact
None. The contract change is additive (accepting cases that currently raise).
Found by /sweep-api-consistency on 2026-05-11.
Summary
to_geotiffrejects two combos thatwrite_geotiff_gpuaccepts and processes successfully:to_geotiff(gpu=True, path=BytesIO)raisesValueError("gpu=True is not supported for file-like destinations").write_geotiff_gpu(cupy_data, BytesIO)writes valid TIFF bytes to the buffer.to_geotiff(cog=True, path=BytesIO)raisesValueError.write_geotiff_gpu(cupy_data, BytesIO, cog=True)writes a COG to the buffer.The
path : strannotation onwrite_geotiff_gpusays only string paths are accepted, so the file-like support is undocumented yet functional. Thecog=Trueblock onto_geotiffpredates the BytesIO support that landed for the eager numpy path.Reproducer
Severity
MEDIUM (Cat 5, public API surface drift).
to_geotiffis the documented preferred entry point; users who follow that path miss capabilities that the explicit GPU writer exposes silently.Fix options
to_geotifffor the GPU path now thatwrite_geotiff_gpuproves it works. Verify the BytesIO round-trip throughopen_geotiffin CI.cog=Truefile-like block into_geotiff. The CPU COG assembler also writes to bytes via_write_bytes; the comment about "atomic rename" is only true for the streaming path.ValueErrorguards towrite_geotiff_gputo mirrorto_geotiff's stricter contract. Documentpathas "string path only" in both writer docstrings.Option 1 + 2 expose existing capabilities. Option 3 is the conservative direction.
Related
This is the GPU-write analog to #1511 (which fixed reader file-like support). The reader side now consistently accepts BytesIO; the writer side still has the
gpu=Trueandcog=Truegates onto_geotiffthat don't apply to the lower-layer writer.Deprecation impact
None. The contract change is additive (accepting cases that currently raise).
Found by
/sweep-api-consistencyon 2026-05-11.