Skip to content

Commit 684b317

Browse files
committed
feat: AssetDefinitions work with raster extension
1 parent f10a7de commit 684b317

File tree

5 files changed

+104
-24
lines changed

5 files changed

+104
-24
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- MGRS Extension ([#1088](https://github.com/stac-utils/pystac/pull/1088))
1111
- All HTTP requests are logged when level is set to `logging.DEBUG` ([#1096](https://github.com/stac-utils/pystac/pull/1096))
1212
- `keep_parent` to Catalog `add_item` and `add_child` to avoid overriding existing parents ([#1117](https://github.com/stac-utils/pystac/pull/1117))
13+
- `owner` attribute to `AssetDefinition` in the item-assets extension ([#1110](https://github.com/stac-utils/pystac/pull/1110))
1314

1415
### Changed
1516

@@ -21,6 +22,7 @@
2122
- `DefaultStacIO` now raises an error if it tries to write to a non-local url ([#1107](https://github.com/stac-utils/pystac/pull/1107))
2223
- Allow instantiation of pystac objects even with `"stac_extensions": null` ([#1109](https://github.com/stac-utils/pystac/pull/1109))
2324
- Make `Link.to_dict()` only contain strings ([#1114](https://github.com/stac-utils/pystac/pull/1114))
25+
- Updated raster extension to work with the item_assets extension's AssetDefinition objects ([#1110](https://github.com/stac-utils/pystac/pull/1110))
2426

2527
### Deprecated
2628

pystac/extensions/item_assets.py

+18-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,13 @@ class AssetDefinition:
3030

3131
properties: Dict[str, Any]
3232

33-
def __init__(self, properties: Dict[str, Any]) -> None:
33+
owner: Optional[pystac.Collection]
34+
35+
def __init__(
36+
self, properties: Dict[str, Any], owner: Optional[pystac.Collection] = None
37+
) -> None:
3438
self.properties = properties
39+
self.owner = owner
3540

3641
def __eq__(self, o: object) -> bool:
3742
if not isinstance(o, AssetDefinition):
@@ -107,6 +112,17 @@ def apply(
107112
self.description = description
108113
self.media_type = media_type
109114
self.roles = roles
115+
self.owner = None
116+
117+
def set_owner(self, obj: pystac.Collection) -> None:
118+
"""Sets the owning item of this AssetDefinition.
119+
120+
The owning item will be used to resolve relative HREFs of this asset.
121+
122+
Args:
123+
obj: The Collection that owns this asset.
124+
"""
125+
self.owner = obj
110126

111127
@property
112128
def title(self) -> Optional[str]:
@@ -202,7 +218,7 @@ def item_assets(self) -> Dict[str, AssetDefinition]:
202218
result: Dict[str, Any] = get_required(
203219
self.collection.extra_fields.get(ITEM_ASSETS_PROP), self, ITEM_ASSETS_PROP
204220
)
205-
return {k: AssetDefinition(v) for k, v in result.items()}
221+
return {k: AssetDefinition(v, self.collection) for k, v in result.items()}
206222

207223
@item_assets.setter
208224
def item_assets(self, v: Dict[str, AssetDefinition]) -> None:

pystac/extensions/raster.py

+70-22
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,18 @@
22

33
from __future__ import annotations
44

5-
from typing import Any, Dict, Iterable, List, Optional, Set, Union
5+
from typing import (
6+
Any,
7+
Dict,
8+
Generic,
9+
Iterable,
10+
List,
11+
Optional,
12+
Set,
13+
TypeVar,
14+
Union,
15+
cast,
16+
)
617

718
import pystac
819
from pystac.extensions.base import (
@@ -11,8 +22,11 @@
1122
SummariesExtension,
1223
)
1324
from pystac.extensions.hooks import ExtensionHooks
25+
import pystac.extensions.item_assets as item_assets
1426
from pystac.utils import StringEnum, get_opt, get_required, map_opt
1527

28+
T = TypeVar("T", pystac.Asset, item_assets.AssetDefinition)
29+
1630
SCHEMA_URI = "https://stac-extensions.github.io/raster/v1.1.0/schema.json"
1731
SCHEMA_URIS = [
1832
"https://stac-extensions.github.io/raster/v1.0.0/schema.json",
@@ -644,38 +658,27 @@ def to_dict(self) -> Dict[str, Any]:
644658

645659

646660
class RasterExtension(
647-
PropertiesExtension, ExtensionManagementMixin[Union[pystac.Item, pystac.Collection]]
661+
Generic[T],
662+
PropertiesExtension,
663+
ExtensionManagementMixin[Union[pystac.Item, pystac.Collection]],
648664
):
649665
"""An abstract class that can be used to extend the properties of an
650-
:class:`~pystac.Item` or :class:`~pystac.Asset` with properties from
666+
:class:`~pystac.Item`, :class:`~pystac.Asset`, or
667+
:class:`~pystac.extension.item_assets.AssetDefinition` with properties from
651668
the :stac-ext:`Raster Extension <raster>`. This class is generic over
652669
the type of STAC Object to be extended (e.g. :class:`~pystac.Item`,
653670
:class:`~pystac.Asset`).
654671
655672
This class will generally not be used directly. Instead, use the concrete
656673
implementation associated with the STAC Object you want to extend (e.g.
657-
:class:`~ItemRasterExtension` to extend an :class:`~pystac.Item`).
674+
:class:`~ItemRasterExtension` to extend an :class:`~pystac.Item`). You may
675+
prefer to use the `ext` class method of this class to construct the correct
676+
instance type for you.
658677
"""
659678

660-
asset_href: str
661-
"""The ``href`` value of the :class:`~pystac.Asset` being extended."""
662-
663679
properties: Dict[str, Any]
664680
"""The :class:`~pystac.Asset` fields, including extension properties."""
665681

666-
additional_read_properties: Optional[Iterable[Dict[str, Any]]] = None
667-
"""If present, this will be a list containing 1 dictionary representing the
668-
properties of the owning :class:`~pystac.Item`."""
669-
670-
def __init__(self, asset: pystac.Asset):
671-
self.asset_href = asset.href
672-
self.properties = asset.extra_fields
673-
if asset.owner and isinstance(asset.owner, pystac.Item):
674-
self.additional_read_properties = [asset.owner.properties]
675-
676-
def __repr__(self) -> str:
677-
return "<AssetRasterExtension Asset href={}>".format(self.asset_href)
678-
679682
def apply(self, bands: List[RasterBand]) -> None:
680683
"""Applies raster extension properties to the extended :class:`pystac.Item` or
681684
:class:`pystac.Asset`.
@@ -715,7 +718,7 @@ def get_schema_uris(cls) -> List[str]:
715718
return SCHEMA_URIS
716719

717720
@classmethod
718-
def ext(cls, obj: pystac.Asset, add_if_missing: bool = False) -> RasterExtension:
721+
def ext(cls, obj: T, add_if_missing: bool = False) -> RasterExtension[T]:
719722
"""Extends the given STAC Object with properties from the :stac-ext:`Raster
720723
Extension <raster>`.
721724
@@ -727,7 +730,12 @@ def ext(cls, obj: pystac.Asset, add_if_missing: bool = False) -> RasterExtension
727730
"""
728731
if isinstance(obj, pystac.Asset):
729732
cls.validate_owner_has_extension(obj, add_if_missing)
730-
return cls(obj)
733+
return cast(RasterExtension[T], AssetRasterExtension(obj))
734+
elif isinstance(obj, item_assets.AssetDefinition):
735+
cls.validate_has_extension(
736+
cast(Union[pystac.Item, pystac.Collection], obj.owner), add_if_missing
737+
)
738+
return cast(RasterExtension[T], ItemAssetsRasterExtension(obj))
731739
else:
732740
raise pystac.ExtensionTypeError(
733741
f"Raster extension does not apply to type '{type(obj).__name__}'"
@@ -741,6 +749,46 @@ def summaries(
741749
return SummariesRasterExtension(obj)
742750

743751

752+
class AssetRasterExtension(RasterExtension[pystac.Asset]):
753+
asset_href: str
754+
"""The ``href`` value of the :class:`~pystac.Asset` being extended."""
755+
756+
properties: Dict[str, Any]
757+
"""The :class:`~pystac.Asset` fields, including extension properties."""
758+
759+
additional_read_properties: Optional[Iterable[Dict[str, Any]]] = None
760+
"""If present, this will be a list containing 1 dictionary representing the
761+
properties of the owning :class:`~pystac.Item`."""
762+
763+
def __init__(self, asset: pystac.Asset):
764+
self.asset_href = asset.href
765+
self.properties = asset.extra_fields
766+
if asset.owner and isinstance(asset.owner, pystac.Item):
767+
self.additional_read_properties = [asset.owner.properties]
768+
769+
def __repr__(self) -> str:
770+
return "<AssetRasterExtension Asset href={}>".format(self.asset_href)
771+
772+
773+
class ItemAssetsRasterExtension(RasterExtension[item_assets.AssetDefinition]):
774+
asset_definition: item_assets.AssetDefinition
775+
"""A reference to the :class:`~pystac.extensions.item_assets.AssetDefinition`
776+
being extended."""
777+
778+
properties: Dict[str, Any]
779+
"""The :class:`~pystac.extensions.item_assets.AssetDefinition` fields, including
780+
extension properties."""
781+
782+
def __init__(self, item_asset: item_assets.AssetDefinition):
783+
self.properties = item_asset.properties
784+
self.asset_definition = item_asset
785+
786+
def __repr__(self) -> str:
787+
return "<ItemAssetsRasterExtension AssetDefinition={}>".format(
788+
self.asset_definition
789+
)
790+
791+
744792
class SummariesRasterExtension(SummariesExtension):
745793
"""A concrete implementation of :class:`~SummariesExtension` that extends
746794
the ``summaries`` field of a :class:`~pystac.Collection` to include properties

0 commit comments

Comments
 (0)