Skip to content

Commit 21637cb

Browse files
authored
Merge pull request #251 from stac-utils/fix/relative-assets
Make asset HREFs relative or absolute based on CatalogType during save
2 parents abfa723 + 2944349 commit 21637cb

File tree

6 files changed

+53
-5
lines changed

6 files changed

+53
-5
lines changed

docs/concepts.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ Catalog Types
101101

102102
The STAC `best practices document <https://github.com/radiantearth/stac-spec/blob/v1.0.0-beta.2/best-practices.md>`_ lays out different catalog types, and how their links should be formatted. A brief description is below, but check out the document for the official take on these types:
103103

104-
Note that the catalog types do not dictate the asset HREF formats, only link formats. Asset HREFs in any catalog type can be relative or absolute; see the section on :ref:`rel vs abs asset` below.
104+
The catalog types will also dictate the asset HREF formats. Asset HREFs in any catalog type can be relative or absolute may be absolute depending on their location; see the section on :ref:`rel vs abs asset` below.
105105

106106

107107
Self-Contained Catalogs

pystac/catalog.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,8 +608,10 @@ def save(self, catalog_type=None):
608608
# Ensure relative vs absolute
609609
if catalog_type == CatalogType.ABSOLUTE_PUBLISHED:
610610
self.make_all_links_absolute()
611+
self.make_all_asset_hrefs_absolute()
611612
elif catalog_type in (CatalogType.SELF_CONTAINED, CatalogType.RELATIVE_PUBLISHED):
612613
self.make_all_links_relative()
614+
self.make_all_asset_hrefs_relative()
613615
else:
614616
raise ValueError(f'catalog_type is not a CatalogType: "{catalog_type}"')
615617

pystac/validation/stac_validator.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ def validate_core(self, stac_dict, stac_object_type, stac_version, href=None):
3434
pass
3535

3636
@abstractmethod
37-
def validate_extension(self, stac_dict, stac_object_type, stac_version, extension_id,
37+
def validate_extension(self,
38+
stac_dict,
39+
stac_object_type,
40+
stac_version,
41+
extension_id,
3842
href=None):
3943
"""Validate an extension stac object.
4044
@@ -173,7 +177,11 @@ def validate_core(self, stac_dict, stac_object_type, stac_version, href=None):
173177
stac_dict.get('id'))
174178
raise STACValidationError(msg, source=e) from e
175179

176-
def validate_extension(self, stac_dict, stac_object_type, stac_version, extension_id,
180+
def validate_extension(self,
181+
stac_dict,
182+
stac_object_type,
183+
stac_version,
184+
extension_id,
177185
href=None):
178186
"""Validate an extension stac object.
179187

requirements-dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ sphinx-autobuild==0.7.1
77
sphinxcontrib-fulltoc==1.2.0
88
sphinxcontrib-napoleon==0.7
99
flake8==3.8.*
10-
yapf==0.28.*
10+
yapf==0.30.*
1111
nbsphinx==0.7.1
1212
coverage==5.2.*

scripts/format

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
if [[ -n "${CI}" ]]; then
6+
set -x
7+
fi
8+
9+
function usage() {
10+
echo -n \
11+
"Usage: $(basename "$0")
12+
Format code with yapf
13+
"
14+
}
15+
16+
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
17+
if [ "${1:-}" = "--help" ]; then
18+
usage
19+
else
20+
yapf -ipr pystac tests
21+
fi
22+
fi

tests/test_writing.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from pystac import (STAC_IO, STACObject, Collection, CatalogType, LinkType)
55
from pystac.serialization import (STACObjectType)
6-
from pystac.utils import make_absolute_href
6+
from pystac.utils import is_absolute_href, make_absolute_href, make_relative_href
77
from pystac.validation import validate_dict
88

99
from tests.utils import TestCases
@@ -31,13 +31,29 @@ def validate_file(self, path, object_type):
3131
return validate_dict(d, object_type)
3232

3333
def validate_link_types(self, root_href, catalog_type):
34+
def validate_asset_href_type(item, item_href, link_type):
35+
for asset in item.assets.values():
36+
if link_type == LinkType.ABSOLUTE:
37+
self.assertTrue(is_absolute_href(asset.href))
38+
else:
39+
is_valid = not is_absolute_href(asset.href)
40+
if not is_valid:
41+
# If the item href and asset href don't share
42+
# the same root, the asset href must be absolute
43+
rel_href = make_relative_href(asset.href, item_href)
44+
self.assertEqual(asset.href, rel_href)
45+
else:
46+
self.assertTrue(is_valid)
47+
3448
def validate_item_link_type(href, link_type, should_include_self):
3549
item_dict = STAC_IO.read_json(href)
3650
item = STACObject.from_file(href)
3751
for link in item.get_links():
3852
if not link.rel == 'self':
3953
self.assertEqual(link.link_type, link_type)
4054

55+
validate_asset_href_type(item, href, link_type)
56+
4157
rels = set([link['rel'] for link in item_dict['links']])
4258
self.assertEqual('self' in rels, should_include_self)
4359

0 commit comments

Comments
 (0)