Skip to content

geotiff: nodata + streaming_buffer_bytes type-hint drift across writer trio #1705

@brendancol

Description

@brendancol

Summary

Follow-up to #1654 (annotate-parity sweep): two more drift sites surfaced by the api-consistency sweep on 2026-05-12. Both are type-hint gaps where the same parameter has an explicit annotation on one public function in the writer trio and bare =None / different breadth on its sibling. Type-checkers and IDE autocomplete therefore see different types for the same parameter depending on which entry point the caller picked.

1. nodata: annotated on write_vrt, unannotated on to_geotiff and write_geotiff_gpu

xrspatial/geotiff/__init__.py

def to_geotiff(data, path, *, crs=..., nodata=None, ...):
    """... nodata : float, int, or None ..."""

def write_geotiff_gpu(data, path, *, crs=..., nodata=None, ...):
    """... nodata : float, int, or None ..."""

def write_vrt(vrt_path, source_files, *, relative=True, crs_wkt=None,
              nodata: float | int | None = None) -> str:
    ...

write_vrt got the float | int | None annotation in #1684. The two sibling writers still expose nodata=None with no annotation, even though every docstring in the trio describes the same accepted-type set ("float, int, or None"). mypy --strict therefore infers Any for to_geotiff(..., nodata=...) and write_geotiff_gpu(..., nodata=...) while inferring float | int | None for write_vrt(..., nodata=...).

2. streaming_buffer_bytes: int on to_geotiff, int | None on write_geotiff_gpu

xrspatial/geotiff/__init__.py

def to_geotiff(..., streaming_buffer_bytes: int = 256 * 1024 * 1024, ...):

def write_geotiff_gpu(..., streaming_buffer_bytes: int | None = None):

write_geotiff_gpu's implementation immediately does del streaming_buffer_bytes (the kwarg is accepted only for API parity with to_geotiff; the GPU writer has no streaming concept). The default and type annotation differ from to_geotiff even though the documented purpose and accepted-value set are the same. Either both should be int = <default> (the CPU writer's contract) or both int | None = None (the GPU writer's no-op contract). Matching to_geotiff's int annotation is the cheaper fix: users who pass through the same kwargs to either entry point get the same type signature, and the GPU writer's no-op semantics are unchanged by tightening the type alone.

Severity

MEDIUM (Cat 3, type hint drift). Annotation-only; no runtime behaviour change. Same shape as the gap #1654 closed for window, path, and on_gpu_failure.

Proposed fix

  1. Add nodata: float | int | None = None to to_geotiff and write_geotiff_gpu.
  2. Change write_geotiff_gpu's streaming_buffer_bytes annotation from int | None = None to int = 256 * 1024 * 1024, matching to_geotiff. The existing del streaming_buffer_bytes no-op stays.
  3. Extend tests/test_signature_annotations_1654.py with pinned-annotation assertions for both kwargs across the writer trio so future drift fails CI.

Non-breaking. nodata=None and streaming_buffer_bytes=256*1024*1024 are the existing defaults and the existing call sites in the codebase already match those types.

Discovered by

/sweep-api-consistency against the geotiff module on 2026-05-12.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions