diff --git a/CHANGELOG.md b/CHANGELOG.md index 34dd3d9cc..3aa527a7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - Update Projection Extension to version 2 - proj:epsg -> proj:code ([#1287](https://github.com/stac-utils/pystac/pull/1287)) - Update migrate code to handle license changes in STAC spec 1.1.0 ([#1491](https://github.com/stac-utils/pystac/pull/1491)) - Allow links to have `file://` prefix - but don't write them that way by default ([#1489](https://github.com/stac-utils/pystac/pull/1489)) +- Raise `STACError` with message when a link is expected to resolve to a STAC object but doesn't ([#1500](https://github.com/stac-utils/pystac/pull/1500)) ### Fixed diff --git a/pystac/link.py b/pystac/link.py index 916c8ec32..e82ddad5a 100644 --- a/pystac/link.py +++ b/pystac/link.py @@ -6,6 +6,7 @@ from typing import TYPE_CHECKING, Any, TypeVar import pystac +from pystac.errors import STACError from pystac.html.jinja_env import get_jinja_env from pystac.utils import ( HREF as HREF, @@ -327,8 +328,12 @@ def resolve_stac_object(self, root: Catalog | None = None) -> Link: stac_io = owner_root._stac_io if stac_io is None: stac_io = pystac.StacIO.default() - - obj = stac_io.read_stac_object(target_href, root=root) + try: + obj = stac_io.read_stac_object(target_href, root=root) + except Exception as e: + raise STACError( + f"HREF: '{target_href}' does not resolve to a STAC object" + ) from e obj.set_self_href(target_href) if root is not None: obj = root._resolved_objects.get_or_cache(obj) diff --git a/tests/test_catalog.py b/tests/test_catalog.py index 45b7aa536..1d76b0e84 100644 --- a/tests/test_catalog.py +++ b/tests/test_catalog.py @@ -24,6 +24,7 @@ Item, MediaType, ) +from pystac.errors import STACError from pystac.layout import ( BestPracticesLayoutStrategy, HrefLayoutStrategy, @@ -674,7 +675,7 @@ def test_save_unresolved(self) -> None: assert len(os.listdir(temporary_directory)) == 2 with tempfile.TemporaryDirectory() as temporary_directory: - with pytest.raises(FileNotFoundError): + with pytest.raises(STACError, match="does not resolve to a STAC object"): catalog.normalize_and_save(temporary_directory, skip_unresolved=False) def test_generate_subcatalogs_works_with_custom_properties(self) -> None: diff --git a/tests/test_link.py b/tests/test_link.py index 0461a2598..aff1939fa 100644 --- a/tests/test_link.py +++ b/tests/test_link.py @@ -10,6 +10,7 @@ import pystac from pystac import Collection, Item, Link +from pystac.errors import STACError from pystac.link import HIERARCHICAL_LINKS from pystac.utils import make_posix_style from tests.utils.test_cases import ARBITRARY_EXTENT @@ -98,6 +99,14 @@ def test_resolve_stac_object_no_root_and_target_is_item(self) -> None: link = pystac.Link("my rel", target=self.item) link.resolve_stac_object() + @pytest.mark.skipif(os.name == "nt", reason="Non-windows test") + def test_resolve_stac_object_throws_informative_error(self) -> None: + link = pystac.Link("root", target="/a/b/foo.json") + with pytest.raises( + STACError, match="HREF: '/a/b/foo.json' does not resolve to a STAC object" + ): + link.resolve_stac_object() + def test_resolved_self_href(self) -> None: catalog = pystac.Catalog(id="test", description="test desc") with TemporaryDirectory() as temporary_directory: