Skip to content
Open
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
3 changes: 2 additions & 1 deletion .claude/sweep-api-consistency-state.csv
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
module,last_inspected,issue,severity_max,categories_found,notes
module,last_inspected,issue,severity_max,categories_found,notes
geotiff,2026-05-09,1541,HIGH,1;2;3;4;5,"PR adds 4 prod fns to __all__, real DeprecationWarning on plot_geotiff. Other findings (gpu kwarg type drift, sibling param asymmetry, write/dask_data rename, chunks default drift, write docstring drift) listed in issue #1541 for follow-up."
46 changes: 42 additions & 4 deletions xrspatial/geotiff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,27 @@
Public API
----------
open_geotiff(source, ...)
Read a GeoTIFF file to an xarray.DataArray.
Read a GeoTIFF, COG, or VRT file to an xarray.DataArray. Auto-dispatches
to the GPU, dask, or numpy backend based on the ``gpu`` and ``chunks``
kwargs.
read_geotiff_gpu(source, ...)
GPU-only read returning a CuPy-backed DataArray. ``open_geotiff(...,
gpu=True)`` calls this internally; use the explicit name when you want
the strict-mode failure semantics (``gpu='strict'``) or want to bypass
auto-dispatch.
read_geotiff_dask(source, ...)
Dask-only read returning a windowed lazy DataArray. ``open_geotiff(...,
chunks=N)`` calls this internally.
read_vrt(source, ...)
Read a GDAL Virtual Raster Table (.vrt). ``open_geotiff`` routes ``.vrt``
paths here automatically; the explicit entry point is useful for
callers that already know they have a VRT.
to_geotiff(data, path, ...)
Write an xarray.DataArray as a GeoTIFF or COG.
Write an xarray.DataArray as a GeoTIFF or COG. Auto-dispatches to GPU
when the data is CuPy-backed.
write_geotiff_gpu(data, path, ...)
GPU-only writer using nvCOMP. ``to_geotiff(..., gpu=True)`` calls this
internally.
write_vrt(vrt_path, source_files, ...)
Generate a VRT mosaic XML from a list of GeoTIFF files.
"""
Expand All @@ -23,7 +41,18 @@
from ._reader import read_to_array
from ._writer import write

__all__ = ['open_geotiff', 'to_geotiff', 'write_vrt']
# All names below are part of the supported public API. ``plot_geotiff``
# is intentionally omitted: it is deprecated in favour of ``da.xrs.plot()``
# and emits a ``DeprecationWarning`` when called.
__all__ = [
'open_geotiff',
'read_geotiff_gpu',
'read_geotiff_dask',
'read_vrt',
'to_geotiff',
'write_geotiff_gpu',
'write_vrt',
]


def _wkt_to_epsg(wkt_or_proj: str) -> int | None:
Expand Down Expand Up @@ -2246,6 +2275,15 @@ def write_vrt(vrt_path: str, source_files: list[str], **kwargs) -> str:
def plot_geotiff(da: xr.DataArray, **kwargs):
"""Plot a DataArray using its embedded colormap if present.

Deprecated: use ``da.xrs.plot()`` instead.
.. deprecated::
Use ``da.xrs.plot()`` instead. ``plot_geotiff`` is a thin wrapper
kept for backward compatibility and will be removed in a future
release.
"""
warnings.warn(
"plot_geotiff is deprecated and will be removed in a future "
"release. Use ``da.xrs.plot()`` instead.",
DeprecationWarning,
stacklevel=2,
)
return da.xrs.plot(**kwargs)
42 changes: 40 additions & 2 deletions xrspatial/geotiff/tests/test_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -2463,7 +2463,7 @@ def test_xrs_plot_no_palette(self, tmp_path):
plt.close('all')

def test_plot_geotiff_deprecated(self, tmp_path):
"""plot_geotiff still works as deprecated wrapper."""
"""plot_geotiff still works but emits a DeprecationWarning."""
import matplotlib
matplotlib.use('Agg')
import xrspatial.accessor
Expand All @@ -2477,7 +2477,8 @@ def test_plot_geotiff_deprecated(self, tmp_path):
f.write(tiff_data)

da = open_geotiff(path)
artist = plot_geotiff(da)
with pytest.warns(DeprecationWarning, match='plot_geotiff is deprecated'):
artist = plot_geotiff(da)
assert artist is not None
import matplotlib.pyplot as plt
plt.close('all')
Expand Down Expand Up @@ -2629,3 +2630,40 @@ def test_dask_chunk_tuple(self, tmp_path):
result = read_geotiff_dask(path, chunks=(5, 10))
computed = result.compute()
np.testing.assert_array_equal(computed.values, arr)


class TestPublicAPI:
"""`__all__` reflects every supported public function and `from
xrspatial.geotiff import *` does not silently drop production names."""

def test_all_lists_supported_functions(self):
import xrspatial.geotiff as g
# Frozen list of names that callers / tests treat as part of the
# public API. If any of these gets removed or renamed, that is a
# breaking change and should go through a deprecation cycle.
expected = {
'open_geotiff',
'read_geotiff_gpu',
'read_geotiff_dask',
'read_vrt',
'to_geotiff',
'write_geotiff_gpu',
'write_vrt',
}
assert set(g.__all__) == expected

def test_star_import_brings_in_all_public_names(self):
# ``from ... import *`` honours ``__all__``; verify every entry is
# importable that way (catches typos in __all__).
ns: dict = {}
exec('from xrspatial.geotiff import *', ns)
import xrspatial.geotiff as g
for name in g.__all__:
assert name in ns, f"{name} listed in __all__ but not exported"

def test_plot_geotiff_not_in_all_but_still_importable(self):
# plot_geotiff is intentionally omitted from __all__ (deprecated)
# but stays importable so existing user code keeps working.
import xrspatial.geotiff as g
assert 'plot_geotiff' not in g.__all__
assert hasattr(g, 'plot_geotiff')
Loading