Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/sweep-api-consistency-state.csv
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module,last_inspected,issue,severity_max,categories_found,notes
geotiff,2026-05-12,1654,MEDIUM,3,"Filed type-annotation drift #1654 (MEDIUM Cat 3): public window/path/on_gpu_failure annotations missing on some siblings while others carry them. Fixed on deep-sweep-api-consistency-geotiff-2026-05-12 with PR (TBD): added tuple|None on open_geotiff/read_vrt window, str|BinaryIO on to_geotiff/write_geotiff_gpu path, str on open_geotiff/read_geotiff_gpu on_gpu_failure plus the deprecated gpu alias. Regression test test_signature_annotations_1654.py pins each annotation. Prior drifts surveyed: chunks default 512 vs None (intentional, read_geotiff_dask is dask-only); crs vs crs_wkt on write_vrt (VRT is WKT-only); write_vrt returns str (intentional backward-compat); nodata float|None vs unannotated (LOW, prior sweep). cuda-validated."
geotiff,2026-05-12,1683;1684;1685,MEDIUM,3;5,"Sweep v2 (deep-sweep-api-consistency-geotiff-2026-05-12-v2). 3 MEDIUM findings filed and fixed: #1683 bigtiff docstring gap on to_geotiff (Cat 3, PR #1686); #1684 write_vrt nodata float|None widened to float|int|None (Cat 3, PR #1687); #1685 open_geotiff silent overview_level/on_gpu_failure drop on VRT sources (Cat 5, PR #1689). Prior v1 fix (#1654) covered type-annotation parity across window/path/on_gpu_failure. cuda-validated."
reproject,2026-05-10,1570,HIGH,2;5,"Filed cross-module attrs['vertical_crs'] type collision (string vs EPSG int) vs xrspatial.geotiff. Fixed in PR (TBD): reproject now writes EPSG int and preserves friendly token under vertical_datum. MEDIUM kwarg-order drift (transform_precision vs chunk_size) and missing type hints vs geotiff documented but not fixed (cosmetic, kwarg-only)."
4 changes: 4 additions & 0 deletions xrspatial/geotiff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,10 @@ def to_geotiff(data: xr.DataArray | np.ndarray,
overview_resampling : str
Resampling method for overviews: 'mean' (default), 'nearest',
'min', 'max', 'median', 'mode', or 'cubic'.
bigtiff : bool or None
Force BigTIFF (64-bit offsets). None (default) auto-promotes
when the estimated file size would exceed the classic-TIFF 4 GB
limit. Matches the same kwarg on ``write_geotiff_gpu``.
gpu : bool or None
Force GPU compression. None (default) auto-detects CuPy data.
streaming_buffer_bytes : int
Expand Down
74 changes: 74 additions & 0 deletions xrspatial/geotiff/tests/test_to_geotiff_bigtiff_doc_1683.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""Regression test for #1683: ``to_geotiff`` Parameters docstring omits
``bigtiff``.

The api-consistency sweep on 2026-05-12 flagged that ``to_geotiff``
accepts a ``bigtiff`` kwarg (signature at ``xrspatial/geotiff/__init__.py``)
but the Parameters block of the docstring jumps from
``overview_resampling`` directly to ``gpu``. ``write_geotiff_gpu``
documents the same kwarg correctly, so users learning the API from
``to_geotiff(...)`` could not tell the option existed.

This module pins the docstring entry against future drift.
"""
from __future__ import annotations

import inspect
import re

from xrspatial.geotiff import to_geotiff, write_geotiff_gpu


def _documented_params(fn) -> list[str]:
"""Return the parameter names listed under the docstring's
``Parameters`` section, in document order.
"""
doc = inspect.getdoc(fn) or ""
documented: list[str] = []
in_params = False
for line in doc.splitlines():
if re.match(r"^Parameters\s*$", line.strip()):
in_params = True
continue
if in_params and re.match(r"^[A-Z][a-z]+\s*$", line.strip()):
# Hit the next docstring section heading (Returns, Notes, ...).
in_params = False
if in_params:
m = re.match(r"^(\S+(?:,\s*\S+)*)\s*:\s*", line)
if m:
for name in m.group(1).split(","):
documented.append(name.strip())
return documented


def test_to_geotiff_bigtiff_documented():
"""``bigtiff`` is in the signature and must be in the docstring too."""
params = list(inspect.signature(to_geotiff).parameters)
assert "bigtiff" in params, (
"to_geotiff signature lost the bigtiff kwarg")
documented = _documented_params(to_geotiff)
assert "bigtiff" in documented, (
f"to_geotiff docstring is missing the bigtiff parameter "
f"description (documented params: {documented})"
)


def test_to_geotiff_parameters_match_signature():
"""Every public kwarg of ``to_geotiff`` is documented."""
params = [p for p in inspect.signature(to_geotiff).parameters]
documented = _documented_params(to_geotiff)
missing = [p for p in params if p not in documented]
assert not missing, (
f"to_geotiff docstring is missing parameter descriptions for "
f"{missing}; documented params were {documented}"
)


def test_write_geotiff_gpu_parameters_match_signature():
"""Sibling writer keeps its full parameter set documented too."""
params = [p for p in inspect.signature(write_geotiff_gpu).parameters]
documented = _documented_params(write_geotiff_gpu)
missing = [p for p in params if p not in documented]
assert not missing, (
f"write_geotiff_gpu docstring is missing parameter "
f"descriptions for {missing}; documented params were {documented}"
)
Loading