Skip to content

Commit 73bbdbd

Browse files
committed
geotiff: re-export #1987 error classes from xrspatial.geotiff
Second-pass review follow-up on PR 2006. The user-facing ambiguity error hierarchy lived in `xrspatial.geotiff._errors`. The leading underscore marks the module as private, so callers writing `except GeoTIFFAmbiguousMetadataError` were coupled to an implementation-detail import path. The neighbouring user-facing errors and warnings (`UnsafeURLError`, `GeoTIFFFallbackWarning`) are re-exported from `xrspatial.geotiff`; the #1987 family now follows the same convention. Adds `GeoTIFFAmbiguousMetadataError` plus the seven case subclasses to `__all__`, updates the frozen-public-API guard test to pin the new names, and adds a regression test that imports each one from the public namespace. No raise-site change; per-case PRs still wire the checks. This is a public-API surface addition only.
1 parent 688eb91 commit 73bbdbd

3 files changed

Lines changed: 58 additions & 0 deletions

File tree

xrspatial/geotiff/__init__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@
5555
coords_to_transform as _coords_to_transform,
5656
require_transform_for_georeferenced as _require_transform_for_georeferenced,
5757
)
58+
from ._errors import (
59+
ConflictingCRSError,
60+
ConflictingNodataError,
61+
GeoTIFFAmbiguousMetadataError,
62+
InvalidCRSCodeError,
63+
MixedBandMetadataError,
64+
NonUniformCoordsError,
65+
RotatedTransformError,
66+
UnparseableCRSError,
67+
)
5868
from ._geotags import GeoTransform, RASTER_PIXEL_IS_AREA, RASTER_PIXEL_IS_POINT
5969
from ._reader import UnsafeURLError
6070
# ``read_to_array`` is internal: it is used by ``open_geotiff`` and the
@@ -108,7 +118,15 @@
108118
# is intentionally omitted: it is deprecated in favour of ``da.xrs.plot()``
109119
# and emits a ``DeprecationWarning`` when called.
110120
__all__ = [
121+
'ConflictingCRSError',
122+
'ConflictingNodataError',
123+
'GeoTIFFAmbiguousMetadataError',
111124
'GeoTIFFFallbackWarning',
125+
'InvalidCRSCodeError',
126+
'MixedBandMetadataError',
127+
'NonUniformCoordsError',
128+
'RotatedTransformError',
129+
'UnparseableCRSError',
112130
'UnsafeURLError',
113131
'open_geotiff',
114132
'read_geotiff_gpu',

xrspatial/geotiff/tests/test_ambiguous_metadata_hooks_1987.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,35 @@ def test_base_is_value_error_subclass():
8888
assert issubclass(GeoTIFFAmbiguousMetadataError, ValueError)
8989

9090

91+
def test_error_classes_reexported_from_public_namespace():
92+
"""User-facing ambiguity errors must be importable from ``xrspatial.geotiff``.
93+
94+
``UnsafeURLError`` and ``GeoTIFFFallbackWarning`` follow the same
95+
convention. Without the re-export, callers would have to dig into
96+
the private ``_errors`` module to write ``except`` clauses, which
97+
couples them to an implementation-detail import path.
98+
"""
99+
import xrspatial.geotiff as geotiff_pkg
100+
101+
for name in (
102+
"GeoTIFFAmbiguousMetadataError",
103+
"InvalidCRSCodeError",
104+
"UnparseableCRSError",
105+
"RotatedTransformError",
106+
"NonUniformCoordsError",
107+
"MixedBandMetadataError",
108+
"ConflictingCRSError",
109+
"ConflictingNodataError",
110+
):
111+
assert hasattr(geotiff_pkg, name), (
112+
f"{name} not exposed on xrspatial.geotiff")
113+
assert name in geotiff_pkg.__all__, (
114+
f"{name} not listed in xrspatial.geotiff.__all__")
115+
# The re-exported class is the same object as the one in ``_errors``.
116+
assert (geotiff_pkg.GeoTIFFAmbiguousMetadataError
117+
is GeoTIFFAmbiguousMetadataError)
118+
119+
91120
def test_subclass_catch_does_not_catch_siblings():
92121
"""``except UnparseableCRSError`` must not catch ``RotatedTransformError``."""
93122
with pytest.raises(RotatedTransformError):

xrspatial/geotiff/tests/test_features.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2726,6 +2726,17 @@ def test_all_lists_supported_functions(self):
27262726
# public API. If any of these gets removed or renamed, that is a
27272727
# breaking change and should go through a deprecation cycle.
27282728
expected = {
2729+
# Ambiguous-metadata error hierarchy (#1987). Re-exported in
2730+
# PR 0 so callers can ``except`` the family or a specific
2731+
# case without importing from the private ``_errors`` module.
2732+
'ConflictingCRSError',
2733+
'ConflictingNodataError',
2734+
'GeoTIFFAmbiguousMetadataError',
2735+
'InvalidCRSCodeError',
2736+
'MixedBandMetadataError',
2737+
'NonUniformCoordsError',
2738+
'RotatedTransformError',
2739+
'UnparseableCRSError',
27292740
'GeoTIFFFallbackWarning',
27302741
'UnsafeURLError',
27312742
'open_geotiff',

0 commit comments

Comments
 (0)