|  | 
|  | 1 | +"""Implements the :stac-ext:`Archive Extension <archive>`.""" | 
|  | 2 | + | 
|  | 3 | +from __future__ import annotations | 
|  | 4 | + | 
|  | 5 | +#from abc import ABC | 
|  | 6 | +from typing import Any, Generic, Literal, TypeVar, Union, cast | 
|  | 7 | + | 
|  | 8 | +import pystac | 
|  | 9 | +from pystac.extensions import item_assets | 
|  | 10 | +from pystac.extensions.base import ExtensionManagementMixin, PropertiesExtension, SummariesExtension | 
|  | 11 | +from pystac.extensions.hooks import ExtensionHooks | 
|  | 12 | +from pystac.utils import StringEnum | 
|  | 13 | + | 
|  | 14 | +T = TypeVar( | 
|  | 15 | +    "T",  pystac.Asset, item_assets.AssetDefinition | 
|  | 16 | +) | 
|  | 17 | + | 
|  | 18 | +# For time being set the URL to repo location. | 
|  | 19 | +# Later to be in standard location like | 
|  | 20 | +# "https://stac-extensions.github.io/archive/v1.0.0/schema.json" | 
|  | 21 | + | 
|  | 22 | +SCHEMA_URI = "https://github.com/stac-extensions/archive/blob/main/json-schema/schema.json" | 
|  | 23 | +PREFIX: str = "archive:" | 
|  | 24 | + | 
|  | 25 | +# Field names | 
|  | 26 | +ARCHIVE_HREF_PROP = PREFIX + "href" | 
|  | 27 | +ARCHIVE_FORMAT_PROP = PREFIX + "format" | 
|  | 28 | +ARCHIVE_TYPE_PROP = PREFIX + "type" | 
|  | 29 | +ARCHIVE_START_PROP = PREFIX + "start" | 
|  | 30 | +ARCHIVE_END_PROP = PREFIX + "end" | 
|  | 31 | + | 
|  | 32 | + | 
|  | 33 | +class ArchiveExtension( | 
|  | 34 | +    Generic[T], | 
|  | 35 | +    PropertiesExtension, | 
|  | 36 | +    ExtensionManagementMixin[Union[pystac.Collection, pystac.Item]], | 
|  | 37 | +): | 
|  | 38 | +    """An abstract class that can be used to extend the properties of a | 
|  | 39 | +    :class:`~pystac.Collection`, :class:`~pystac.Item`, or :class:`~pystac.Asset` with | 
|  | 40 | +    properties from the :stac-ext:`Archive Extension <archive>`. This class is | 
|  | 41 | +    generic over the type of STAC Object to be extended (e.g. :class:`~pystac.Item`, | 
|  | 42 | +    :class:`~pystac.Asset`). | 
|  | 43 | +
 | 
|  | 44 | +    To create a concrete instance of :class:`ArchiveExtension`, use the | 
|  | 45 | +    :meth:`ArchiveExtension.ext` method. For example: | 
|  | 46 | +
 | 
|  | 47 | +    .. code-block:: python | 
|  | 48 | +
 | 
|  | 49 | +       >>> item: pystac.Item = ... | 
|  | 50 | +       >>> arch_ext = ArchiveExtension.ext(item) | 
|  | 51 | +    """ | 
|  | 52 | + | 
|  | 53 | +    name: Literal["archive"] = "archive" | 
|  | 54 | + | 
|  | 55 | +    def apply( | 
|  | 56 | +        self, | 
|  | 57 | +        href: str |  None = None, | 
|  | 58 | +        format: str |  None = None, | 
|  | 59 | +        type: str |  None = None, | 
|  | 60 | +        start: int |  None = None, | 
|  | 61 | +        end: int |  None = None, | 
|  | 62 | +    ) -> None: | 
|  | 63 | +        """Applies Archive Extension properties to the extended | 
|  | 64 | +        :class:`~pystac.Collection`, :class:`~pystac.Item` or :class:`~pystac.Asset`. | 
|  | 65 | +
 | 
|  | 66 | +        Args: | 
|  | 67 | +            href (str) : The location of the file within the archive specified by the href field. | 
|  | 68 | +            format (str): The mimetype of the archive format. | 
|  | 69 | +            type (str): The mimetype of the file within the archive specified by the href field. | 
|  | 70 | +            start (int) : The offset of the first byte of the file within the archive. | 
|  | 71 | +            end (int) : The offset of the last byte of the file within the archive. | 
|  | 72 | +        """ | 
|  | 73 | +        self.href = href | 
|  | 74 | +        self.format = format | 
|  | 75 | +        self.type = type | 
|  | 76 | +        self.start = start | 
|  | 77 | +        self.end = end | 
|  | 78 | + | 
|  | 79 | +    @property | 
|  | 80 | +    def href(self) -> str | None: | 
|  | 81 | +        """Get or sets the href,the location of the file within the archive. | 
|  | 82 | +        """ | 
|  | 83 | +        return self._get_property(ARCHIVE_HREF_PROP, str) | 
|  | 84 | + | 
|  | 85 | +    @href.setter | 
|  | 86 | +    def href(self, v: str | None) -> None: | 
|  | 87 | +        self._set_property(ARCHIVE_HREF_PROP, v) | 
|  | 88 | + | 
|  | 89 | +    @property | 
|  | 90 | +    def format(self) -> str | None: | 
|  | 91 | +        """Get or sets the format,the mimetype of the archive. | 
|  | 92 | +        """ | 
|  | 93 | +        return self._get_property(ARCHIVE_FORMAT_PROP, str) | 
|  | 94 | + | 
|  | 95 | +    @format.setter | 
|  | 96 | +    def format(self, v: str | None) -> None: | 
|  | 97 | +        self._set_property(ARCHIVE_FORMAT_PROP, v) | 
|  | 98 | + | 
|  | 99 | +    @property | 
|  | 100 | +    def type(self) -> str | None: | 
|  | 101 | +        """Get or sets the type,the mimetype of the file within the archive | 
|  | 102 | +           specified by the href field. | 
|  | 103 | +        """ | 
|  | 104 | +        return self._get_property(ARCHIVE_TYPE_PROP, str) | 
|  | 105 | + | 
|  | 106 | +    @type.setter | 
|  | 107 | +    def type(self, v: str | None) -> None: | 
|  | 108 | +        self._set_property(ARCHIVE_TYPE_PROP, v) | 
|  | 109 | + | 
|  | 110 | +    @property | 
|  | 111 | +    def start(self) -> int | None: | 
|  | 112 | +        """Get or sets the start,the offset of the first byte of the file  | 
|  | 113 | +           within the archive. | 
|  | 114 | +        """ | 
|  | 115 | +        return self._get_property(ARCHIVE_START_PROP, int) | 
|  | 116 | + | 
|  | 117 | +    @start.setter | 
|  | 118 | +    def start(self, v: int | None) -> None: | 
|  | 119 | +        self._set_property(ARCHIVE_START_PROP, v) | 
|  | 120 | + | 
|  | 121 | +    @property | 
|  | 122 | +    def end(self) -> int | None: | 
|  | 123 | +        """Get or sets the end,the offset of the last byte of the file  | 
|  | 124 | +           within the archive. | 
|  | 125 | +        """ | 
|  | 126 | +        return self._get_property(ARCHIVE_END_PROP, int) | 
|  | 127 | + | 
|  | 128 | +    @end.setter | 
|  | 129 | +    def start(self, v: int | None) -> None: | 
|  | 130 | +        self._set_property(ARCHIVE_END_PROP, v) | 
|  | 131 | + | 
|  | 132 | +    @classmethod | 
|  | 133 | +    def get_schema_uri(cls) -> str: | 
|  | 134 | +        return SCHEMA_URI | 
|  | 135 | + | 
|  | 136 | +    @classmethod | 
|  | 137 | +    def ext(cls, obj: T, add_if_missing: bool = False) -> ArchiveExtension[T]: | 
|  | 138 | +        """Extends the given STAC Object with properties from the :stac-ext:`Archive | 
|  | 139 | +        Extension <archive>`. | 
|  | 140 | +
 | 
|  | 141 | +        This extension can be applied to instances of :class:`~pystac.Asset`. | 
|  | 142 | +
 | 
|  | 143 | +        Raises: | 
|  | 144 | +
 | 
|  | 145 | +            pystac.ExtensionTypeError : If an invalid object type is passed. | 
|  | 146 | +        """ | 
|  | 147 | +        if isinstance(obj, pystac.Item): | 
|  | 148 | +            cls.ensure_has_extension(obj, add_if_missing) | 
|  | 149 | +            return cast(ArchiveExtension[T], ItemArchiveExtension(obj)) | 
|  | 150 | +        if isinstance(obj, pystac.Asset): | 
|  | 151 | +            cls.ensure_owner_has_extension(obj, add_if_missing) | 
|  | 152 | +            return cast(ArchiveExtension[T], AssetArchiveExtension(obj)) | 
|  | 153 | +        elif isinstance(obj, item_assets.AssetDefinition): | 
|  | 154 | +            cls.ensure_owner_has_extension(obj, add_if_missing) | 
|  | 155 | +            return cast(ArchiveExtension[T], ItemAssetsArchiveExtension(obj)) | 
|  | 156 | +        else: | 
|  | 157 | +            raise pystac.ExtensionTypeError(cls._ext_error_message(obj)) | 
|  | 158 | + | 
|  | 159 | +    @classmethod | 
|  | 160 | +    def summaries( | 
|  | 161 | +        cls, obj: pystac.Collection, add_if_missing: bool = False | 
|  | 162 | +    ) -> SummariesStorageExtension: | 
|  | 163 | +        """Returns the extended summaries object for the given collection.""" | 
|  | 164 | +        cls.ensure_has_extension(obj, add_if_missing) | 
|  | 165 | +        return SummariesStorageExtension(obj) | 
|  | 166 | + | 
|  | 167 | + | 
|  | 168 | +#class ItemArchiveExtension(ArchiveExtension[pystac.Item]): | 
|  | 169 | +#    """A concrete implementation of :class:`ArchiveExtension` on an | 
|  | 170 | +#    :class:`~pystac.Item` that extends the properties of the Item to include properties | 
|  | 171 | +#    defined in the :stac-ext:`Archive Extension <archive>`. | 
|  | 172 | +# | 
|  | 173 | +#    This class should generally not be instantiated directly. Instead, call | 
|  | 174 | +#    :meth:`ArchiveExtension.ext` on an :class:`~pystac.Item` to extend it. | 
|  | 175 | +#    """ | 
|  | 176 | +# | 
|  | 177 | +#    item: pystac.Item | 
|  | 178 | +#    properties: dict[str, Any] | 
|  | 179 | +# | 
|  | 180 | +#    def __init__(self, item: pystac.Item): | 
|  | 181 | +#        self.item = item | 
|  | 182 | +#        self.properties = item.properties | 
|  | 183 | +# | 
|  | 184 | +#    def __repr__(self) -> str: | 
|  | 185 | +#        return f"<ItemArchiveExtension Item id={self.item.id}>" | 
|  | 186 | + | 
|  | 187 | + | 
|  | 188 | +class AssetArchiveExtension(ArchiveExtension[pystac.Asset]): | 
|  | 189 | +    """A concrete implementation of :class:`ArchiveExtension` on an | 
|  | 190 | +    :class:`~pystac.Asset` that extends the Asset fields to include properties defined | 
|  | 191 | +    in the :stac-ext:`Archive Extension <archive>`. | 
|  | 192 | +
 | 
|  | 193 | +    This class should generally not be instantiated directly. Instead, call | 
|  | 194 | +    :meth:`ArchiveExtension.ext` on an :class:`~pystac.Asset` to extend it. | 
|  | 195 | +    """ | 
|  | 196 | + | 
|  | 197 | +    asset_href: str | 
|  | 198 | +    properties: dict[str, Any] | 
|  | 199 | +    additional_read_properties: list[dict[str, Any]] | None | 
|  | 200 | + | 
|  | 201 | +    def __init__(self, asset: pystac.Asset): | 
|  | 202 | +        self.asset_href = asset.href | 
|  | 203 | +        self.properties = asset.extra_fields | 
|  | 204 | +        if asset.owner and isinstance(asset.owner, pystac.Item): | 
|  | 205 | +            self.additional_read_properties = [asset.owner.properties] | 
|  | 206 | +        else: | 
|  | 207 | +            self.additional_read_properties = None | 
|  | 208 | + | 
|  | 209 | +    def __repr__(self) -> str: | 
|  | 210 | +        return f"<AssetArchiveExtension Item id={self.asset_href}>" | 
|  | 211 | + | 
|  | 212 | + | 
|  | 213 | +class ItemAssetsArchiveExtension(ArchiveExtension[item_assets.AssetDefinition]): | 
|  | 214 | +    properties: dict[str, Any] | 
|  | 215 | +    asset_defn: item_assets.AssetDefinition | 
|  | 216 | + | 
|  | 217 | +    def __init__(self, item_asset: item_assets.AssetDefinition): | 
|  | 218 | +        self.asset_defn = item_asset | 
|  | 219 | +        self.properties = item_asset.properties | 
|  | 220 | + | 
|  | 221 | + | 
|  | 222 | +class SummariesArchiveExtension(SummariesExtension): | 
|  | 223 | +    """A concrete implementation of :class:`~SummariesExtension` that extends | 
|  | 224 | +    the ``summaries`` field of a :class:`~pystac.Collection` to include properties | 
|  | 225 | +    defined in the :stac-ext:`Archive Extension <storage>`. | 
|  | 226 | +    """ | 
|  | 227 | + | 
|  | 228 | +    @property | 
|  | 229 | +    def href(self) -> list[str] | None: | 
|  | 230 | +        """Get or sets the summary of :attr:`ArchiveExtension.href` values | 
|  | 231 | +        for this Collection. | 
|  | 232 | +        """ | 
|  | 233 | +        return self.summaries.get_list(ARCHIVE_HREF_PROP) | 
|  | 234 | + | 
|  | 235 | +    @href.setter | 
|  | 236 | +    def href(self, v: list[str] | None) -> None: | 
|  | 237 | +        self._set_summary(ARCHIVE_HREF_PROP, v) | 
|  | 238 | + | 
|  | 239 | +    @property | 
|  | 240 | +    def format(self) -> list[str] | None: | 
|  | 241 | +        """Get or sets the summary of :attr:`ArchiveExtension.format` values | 
|  | 242 | +        for this Collection. | 
|  | 243 | +        """ | 
|  | 244 | +        return self.summaries.get_list(ARCHIVE_FORMAT_PROP) | 
|  | 245 | + | 
|  | 246 | +    @format.setter | 
|  | 247 | +    def format(self, v: list[str] | None) -> None: | 
|  | 248 | +        self._set_summary(ARCHIVE_FORMAT_PROP, v) | 
|  | 249 | + | 
|  | 250 | +    @property | 
|  | 251 | +    def type(self) -> list[str] | None: | 
|  | 252 | +        """Get or sets the summary of :attr:`ArchiveExtension.type` values | 
|  | 253 | +        for this Collection. | 
|  | 254 | +        """ | 
|  | 255 | +        return self.summaries.get_list(ARCHIVE_TYPE_PROP) | 
|  | 256 | + | 
|  | 257 | +    @type.setter | 
|  | 258 | +    def type(self, v: list[str] | None) -> None: | 
|  | 259 | +        self._set_summary(ARCHIVE_TYPE_PROP, v) | 
|  | 260 | + | 
|  | 261 | +    @property | 
|  | 262 | +    def start(self) -> list[int] | None: | 
|  | 263 | +        """Get or sets the summary of :attr:`ArchiveExtension.start` values | 
|  | 264 | +        for this Collection. | 
|  | 265 | +        """ | 
|  | 266 | +        return self.summaries.get_list(ARCHIVE_START_PROP) | 
|  | 267 | + | 
|  | 268 | +    @start.setter | 
|  | 269 | +    def start(self, v: list[int] | None) -> None: | 
|  | 270 | +        self._set_summary(ARCHIVE_START_PROP, v) | 
|  | 271 | + | 
|  | 272 | +    @property | 
|  | 273 | +    def end(self) -> list[int] | None: | 
|  | 274 | +        """Get or sets the summary of :attr:`ArchiveExtension.end` values | 
|  | 275 | +        for this Collection. | 
|  | 276 | +        """ | 
|  | 277 | +        return self.summaries.get_list(ARCHIVE_END_PROP) | 
|  | 278 | + | 
|  | 279 | +    @end.setter | 
|  | 280 | +    def end(self, v: list[int] | None) -> None: | 
|  | 281 | +        self._set_summary(ARCHIVE_END_PROP, v) | 
|  | 282 | + | 
|  | 283 | + | 
|  | 284 | +class ArchiveExtensionHooks(ExtensionHooks): | 
|  | 285 | +    schema_uri: str = SCHEMA_URI | 
|  | 286 | + | 
|  | 287 | +    #For time being empty set  | 
|  | 288 | +    prev_extension_ids: set[str] = set() | 
|  | 289 | +    stac_object_types = { | 
|  | 290 | +        pystac.STACObjectType.COLLECTION, | 
|  | 291 | +        pystac.STACObjectType.ITEM, | 
|  | 292 | +    } | 
|  | 293 | + | 
|  | 294 | + | 
|  | 295 | +ARCHIVE_EXTENSION_HOOKS: ExtensionHooks = ArchiveExtensionHooks() | 
0 commit comments