Skip to content

Commit 278ecf4

Browse files
committed
feat: Added processing extension and properties
1 parent 065a631 commit 278ecf4

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

pystac/extensions/processing.py

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
"""Implements the :stac-ext:`Processing <processing>` STAC Extension.
2+
3+
https://github.com/stac-extensions/processing
4+
"""
5+
6+
from __future__ import annotations
7+
8+
from typing import (
9+
Any,
10+
Generic,
11+
Literal,
12+
Self,
13+
TypeVar,
14+
cast,
15+
)
16+
17+
import pystac
18+
from pystac.extensions import item_assets
19+
from pystac.extensions.base import (
20+
ExtensionManagementMixin,
21+
PropertiesExtension,
22+
)
23+
from pystac.utils import StringEnum
24+
25+
T = TypeVar("T", pystac.Item, pystac.Asset, item_assets.AssetDefinition)
26+
27+
SCHEMA_URI: str = "https://stac-extensions.github.io/processing/v1.2.0/schema.json"
28+
SCHEMA_URIS: list[str] = [
29+
SCHEMA_URI,
30+
]
31+
PREFIX: str = "processing:"
32+
33+
# Field names
34+
LEVEL_PROP: str = PREFIX + "level"
35+
DATETIME_PROP: str = PREFIX + "datetime"
36+
EXPRESSION_PROP: str = PREFIX + "expression"
37+
LINEAGE_PROP: str = PREFIX + "lineage"
38+
FACILITY_PROP: str = PREFIX + "facility"
39+
VERSION_PROP: str = PREFIX + "version"
40+
SOFTWARE_PROP: str = PREFIX + "software"
41+
42+
43+
class ProcessingLevel(StringEnum):
44+
RAW = "RAW"
45+
L0 = "L0"
46+
L1 = "L1"
47+
L2 = "L2"
48+
L3 = "L3"
49+
L4 = "L4"
50+
51+
52+
class ProcessingExtension(
53+
Generic[T],
54+
PropertiesExtension,
55+
ExtensionManagementMixin[pystac.Item | pystac.Collection],
56+
):
57+
"""An abstract class that can be used to extend the properties of an
58+
:class:`~pystac.Item` or :class:`~pystac.Asset` with properties from the
59+
:stac-ext:`Processing Extension <processing>`. This class is generic over the type
60+
of STAC Object to be extended (e.g. :class:`~pystac.Item`,
61+
:class:`~pystac.Collection`).
62+
63+
To create a concrete instance of :class:`ProcessingExtension`, use the
64+
:meth:`ProcessingExtension.ext` method. For example:
65+
66+
.. code-block:: python
67+
68+
>>> item: pystac.Item = ...
69+
>>> proc_ext = ProcessingExtension.ext(item)
70+
71+
"""
72+
73+
def __init__(self: Self, item: pystac.Item) -> None:
74+
self.item = item
75+
self.properties = item.properties
76+
77+
def __repr__(self: Self) -> str:
78+
return f"<ProcessingExtension Item id={self.item.id}>"
79+
80+
def apply(self: Self, level: str | None = None) -> None:
81+
self.level = level
82+
83+
@property
84+
def level(self: Self) -> str | None:
85+
return self._get_property(LEVEL_PROP, str)
86+
87+
@level.setter
88+
def level(self: Self, v: str | None) -> None:
89+
self._set_property(LEVEL_PROP, v, pop_if_none=True)
90+
91+
@property
92+
def datetime(self: Self) -> str | None:
93+
return self._get_property(DATETIME_PROP, str)
94+
95+
@datetime.setter
96+
def datetime(self: Self, v: str | None) -> None:
97+
self._set_property(DATETIME_PROP, v, pop_if_none=True)
98+
99+
@property
100+
def expression(self: Self) -> str | None:
101+
return self._get_property(EXPRESSION_PROP, str)
102+
103+
@expression.setter
104+
def expression(self: Self, v: str | None) -> None:
105+
self._set_property(EXPRESSION_PROP, v, pop_if_none=True)
106+
107+
@property
108+
def lineage(self: Self) -> str | None:
109+
return self._get_property(LINEAGE_PROP, str)
110+
111+
@lineage.setter
112+
def lineage(self: Self, v: str | None) -> None:
113+
self._set_property(LINEAGE_PROP, v, pop_if_none=True)
114+
115+
@property
116+
def facility(self: Self) -> str | None:
117+
return self._get_property(FACILITY_PROP, str)
118+
119+
@facility.setter
120+
def facility(self: Self, v: str | None) -> None:
121+
self._set_property(FACILITY_PROP, v, pop_if_none=True)
122+
123+
@property
124+
def version(self: Self) -> str | None:
125+
return self._get_property(VERSION_PROP, str)
126+
127+
@version.setter
128+
def version(self: Self, v: str | None) -> None:
129+
self._set_property(VERSION_PROP, v, pop_if_none=True)
130+
131+
@property
132+
def software(self: Self) -> str | None:
133+
return self._get_property(SOFTWARE_PROP, str)
134+
135+
@software.setter
136+
def software(self: Self, v: str | None) -> None:
137+
self._set_property(SOFTWARE_PROP, v, pop_if_none=True)
138+
139+
@classmethod
140+
def get_schema_uri(cls) -> str:
141+
return SCHEMA_URI
142+
143+
@classmethod
144+
def ext(cls, obj: T, add_if_missing: bool = False) -> ProcessingExtension[T]:
145+
if isinstance(obj, pystac.Item):
146+
cls.ensure_has_extension(obj, add_if_missing)
147+
return cast(ProcessingExtension, ItemProcessingExtension(obj))
148+
else:
149+
raise pystac.ExtensionTypeError(cls._ext_error_message(obj))
150+
151+
152+
class ItemProcessingExtension(ProcessingExtension[pystac.Item]):
153+
item: pystac.Item
154+
properties: dict[str, Any]
155+
156+
def __init__(self: Self, item: pystac.Item) -> None:
157+
self.item = item
158+
self.properties = item.properties
159+
160+
def __repr__(self: Self) -> str:
161+
return f"<ItemProcessingExtension Item id={self.item.id}>"

0 commit comments

Comments
 (0)