Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raise an error on APILayoutStrategy when root_href is non-url #1498

Merged
merged 3 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 6 additions & 1 deletion pystac/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@

import pystac
from pystac.cache import ResolvedObjectCache
from pystac.errors import STACTypeError
from pystac.errors import STACError, STACTypeError
from pystac.layout import (
APILayoutStrategy,
BestPracticesLayoutStrategy,
HrefLayoutStrategy,
LayoutTemplate,
Expand All @@ -32,6 +33,7 @@
HREF,
StringEnum,
is_absolute_href,
is_url,
make_absolute_href,
make_relative_href,
)
Expand Down Expand Up @@ -769,6 +771,9 @@ def normalize_hrefs(
if not is_absolute_href(root_href):
root_href = make_absolute_href(root_href, os.getcwd(), start_is_dir=True)

if isinstance(_strategy, APILayoutStrategy) and not is_url(root_href):
raise STACError("When using APILayoutStrategy the root_href must be a URL")

def process_item(
item: Item, _root_href: str, is_root: bool, parent: Catalog | None
) -> Callable[[], None] | None:
Expand Down
13 changes: 4 additions & 9 deletions pystac/stac_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
merge_common_properties,
migrate_to_latest,
)
from pystac.utils import HREF, safe_urlparse
from pystac.utils import HREF, is_url, safe_urlparse

# Use orjson if available
try:
Expand Down Expand Up @@ -294,7 +294,7 @@ def read_text_from_href(self, href: str) -> str:
href : The URI of the file to open.
"""
href_contents: str
if _is_url(href):
if is_url(href):
try:
logger.debug(f"GET {href} Headers: {self.headers}")
req = Request(href, headers=self.headers)
Expand Down Expand Up @@ -327,7 +327,7 @@ def write_text_to_href(self, href: str, txt: str) -> None:
href : The path to which the file will be written.
txt : The string content to write to the file.
"""
if _is_url(href):
if is_url(href):
raise NotImplementedError("DefaultStacIO cannot write to urls")
href = safe_urlparse(href).path
dirname = os.path.dirname(href)
Expand Down Expand Up @@ -390,11 +390,6 @@ def _report_duplicate_object_names(
return result


def _is_url(href: str) -> bool:
parsed = safe_urlparse(href)
return parsed.scheme not in ["", "file"]


if HAS_URLLIB3:
from typing import cast

Expand Down Expand Up @@ -433,7 +428,7 @@ def read_text_from_href(self, href: str) -> str:
Args:
href : The URI of the file to open.
"""
if _is_url(href):
if is_url(href):
# TODO provide a pooled StacIO to enable more efficient network
# access (probably named `PooledStacIO`).
http = PoolManager()
Expand Down
5 changes: 5 additions & 0 deletions pystac/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,3 +605,8 @@ def is_file_path(href: str) -> bool:
"""
parsed = urlparse(href)
return bool(os.path.splitext(parsed.path)[1])


def is_url(href: str) -> bool:
gadomski marked this conversation as resolved.
Show resolved Hide resolved
parsed = safe_urlparse(href)
return parsed.scheme not in ["", "file"]
13 changes: 13 additions & 0 deletions tests/test_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
MediaType,
)
from pystac.layout import (
APILayoutStrategy,
BestPracticesLayoutStrategy,
HrefLayoutStrategy,
TemplateLayoutStrategy,
Expand Down Expand Up @@ -1968,3 +1969,15 @@ def test_add_item_layout_strategy(
template = template.format(id=item.id).replace("$", "")

assert item.self_href == f"{base_url}/{template}/{item_id}.json"


def test_APILayoutStrategy_requires_root_to_be_url(
catalog: Catalog, collection: Collection, item: Item
) -> None:
collection.add_item(item)
catalog.add_child(collection)
with pytest.raises(
pystac.errors.STACError,
match="When using APILayoutStrategy the root_href must be a URL",
):
catalog.normalize_hrefs(root_href="issues-1486", strategy=APILayoutStrategy())
Loading