Skip to content

Commit

Permalink
Add "public" Catalog.stac_io property
Browse files Browse the repository at this point in the history
  • Loading branch information
duckontheweb committed Jul 30, 2021
1 parent 10e1efe commit 9c229d0
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 17 deletions.
35 changes: 25 additions & 10 deletions pystac/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class CatalogType(str, Enum):
See:
:stac-spec:`The best practices documentation on self-contained catalogs
<best-practices.md#self-contained-catalogs>`
<best-practices.md#self-contained-catalogs>`
"""

ABSOLUTE_PUBLISHED = "ABSOLUTE_PUBLISHED"
Expand All @@ -54,7 +54,7 @@ class CatalogType(str, Enum):
See:
:stac-spec:`The best practices documentation on published catalogs
<best-practices.md#published-catalogs>`
<best-practices.md#published-catalogs>`
"""

RELATIVE_PUBLISHED = "RELATIVE_PUBLISHED"
Expand All @@ -64,7 +64,7 @@ class CatalogType(str, Enum):
See:
:stac-spec:`The best practices documentation on published catalogs
<best-practices.md#published-catalogs>`
<best-practices.md#published-catalogs>`
"""

@classmethod
Expand Down Expand Up @@ -135,10 +135,6 @@ class Catalog(STACObject):
STAC_OBJECT_TYPE = pystac.STACObjectType.CATALOG

_stac_io: Optional[pystac.StacIO] = None
"""Optional instance of StacIO that will be used by default
for any IO operations on objects contained by this catalog.
Set while reading in a catalog. This is set when a catalog
is read by a StacIO instance."""

DEFAULT_FILE_NAME = "catalog.json"
"""Default file name that will be given to this STAC object in
Expand Down Expand Up @@ -176,17 +172,36 @@ def __init__(

self._resolved_objects.cache(self)

@property
def stac_io(self) -> Optional[pystac.StacIO]:
"""Optional instance of :class:`~pystac.StacIO` that will be used by default
for any IO operations on objects contained by this catalog. Set while reading
in a catalog. This is set when a catalog is read by a :class:`~pystac.StacIO`
instance."""
return self._stac_io

@stac_io.setter
def stac_io(self, v: Optional[pystac.StacIO]) -> None:
self._stac_io = v

def __repr__(self) -> str:
return "<Catalog id={}>".format(self.id)

def set_root(self, root: Optional["Catalog"]) -> None:
"""Sets the root :class:`~pystac.Catalog` for this :class:`~pystac.Catalog`.
This method also sets the :attr:`~pystac.Catalog.stac_io` for this ``Catalog``
to be the same as ``root.stac_io``.
Args:
root : A :class:`~pystac.Catalog` instance to set as the root.
"""
super().set_root(root)
if root is not None:
root._resolved_objects = ResolvedObjectCache.merge(
root._resolved_objects, self._resolved_objects
)
if root._stac_io is not None:
self._stac_io = root._stac_io
if root.stac_io is not None:
self.stac_io = root.stac_io

def is_relative(self) -> bool:
return self.catalog_type in [
Expand Down Expand Up @@ -1012,7 +1027,7 @@ def from_file(cls, href: str, stac_io: Optional[pystac.StacIO] = None) -> "Catal
result = super().from_file(href, stac_io)
if not isinstance(result, Catalog):
raise pystac.STACTypeError(f"{result} is not a {Catalog}.")
result._stac_io = stac_io
result.stac_io = stac_io

return result

Expand Down
4 changes: 2 additions & 2 deletions pystac/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,14 +252,14 @@ def resolve_stac_object(self, root: Optional["Catalog_Type"] = None) -> "Link":

if root is not None:
obj = root._resolved_objects.get_by_href(target_href)
stac_io = root._stac_io
stac_io = root.stac_io

if obj is None:

if stac_io is None:
if self.owner is not None:
if isinstance(self.owner, pystac.Catalog):
stac_io = self.owner._stac_io
stac_io = self.owner.stac_io
if stac_io is None:
stac_io = pystac.StacIO.default()

Expand Down
2 changes: 1 addition & 1 deletion pystac/stac_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def stac_object_from_dict(
result = pystac.Catalog.from_dict(
d, href=href, root=root, migrate=False, preserve_dict=preserve_dict
)
result._stac_io = self
result.stac_io = self
return result

if info.object_type == pystac.STACObjectType.COLLECTION:
Expand Down
2 changes: 1 addition & 1 deletion pystac/stac_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ def save_object(
if stac_io is None:
root = self.get_root()
if root is not None:
root_stac_io = root._stac_io
root_stac_io = root.stac_io
if root_stac_io is not None:
stac_io = root_stac_io

Expand Down
6 changes: 3 additions & 3 deletions tests/test_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ class CustomStacIO(DefaultStacIO):
with open(path) as f:
cat_dict = json.load(f)
root_cat = pystac.Catalog(id="test", description="test desc")
root_cat._stac_io = CustomStacIO()
root_cat.stac_io = CustomStacIO()

collection = Catalog.from_dict(cat_dict, root=root_cat)
self.assertIsInstance(collection._stac_io, CustomStacIO)
self.assertIsInstance(collection.stac_io, CustomStacIO)

def test_read_remote(self) -> None:
# TODO: Move this URL to the main stac-spec repo once the example JSON is fixed.
Expand Down Expand Up @@ -948,7 +948,7 @@ def test_collections_cache_correctly(self) -> None:
catalogs = TestCases.all_test_catalogs()
mock_io = MockStacIO()
for cat in catalogs:
cat._stac_io = mock_io
cat.stac_io = mock_io
expected_collection_reads = set([])
for root, _, items in cat.walk():
if isinstance(root, Collection) and root != cat:
Expand Down

0 comments on commit 9c229d0

Please sign in to comment.