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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions