From 3fead3103f6a367ffe2c26d516aad6e13ce9ace4 Mon Sep 17 00:00:00 2001 From: Jon Duckworth Date: Wed, 7 Jul 2021 08:01:18 -0400 Subject: [PATCH 1/6] Update Sat Extension docstrings --- pystac/extensions/sat.py | 86 +++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 23 deletions(-) diff --git a/pystac/extensions/sat.py b/pystac/extensions/sat.py index c775f56c2..ad5ff8d62 100644 --- a/pystac/extensions/sat.py +++ b/pystac/extensions/sat.py @@ -4,7 +4,7 @@ """ import enum -from typing import Generic, Optional, Set, TypeVar, cast +from typing import Dict, Any, Generic, Iterable, Optional, Set, TypeVar, cast import pystac from pystac.extensions.base import ( @@ -18,11 +18,12 @@ SCHEMA_URI = "https://stac-extensions.github.io/sat/v1.0.0/schema.json" -ORBIT_STATE: str = "sat:orbit_state" -RELATIVE_ORBIT: str = "sat:relative_orbit" +PREFIX: str = "sat:" +ORBIT_STATE: str = PREFIX + "orbit_state" +RELATIVE_ORBIT: str = PREFIX + "relative_orbit" -class OrbitState(enum.Enum): +class OrbitState(str, enum.Enum): ASCENDING = "ascending" DESCENDING = "descending" GEOSTATIONARY = "geostationary" @@ -31,17 +32,19 @@ class OrbitState(enum.Enum): class SatExtension( Generic[T], PropertiesExtension, ExtensionManagementMixin[pystac.Item] ): - """SatItemExt extends Item to add sat properties to a STAC Item. + """An abstract class that can be used to extend the properties of an + :class:`~pystac.Item` or :class:`~pystac.Asset` with properties from the + :stac-ext:`Satellite Extension `. This class is generic over the type of + STAC Object to be extended (e.g. :class:`~pystac.Item`, + :class:`~pystac.Collection`). - Args: - item : The item to be extended. + To create a concrete instance of :class:`SatExtension`, use the + :meth:`SatExtension.ext` method. For example: - Attributes: - item : The item that is being extended. + .. code-block:: python - Note: - Using SatItemExt to directly wrap an item will add the 'sat' - extension ID to the item's stac_extensions. + >>> item: pystac.Item = ... + >>> sat_ext = SatExtension.ext(item) """ def apply( @@ -49,7 +52,8 @@ def apply( orbit_state: Optional[OrbitState] = None, relative_orbit: Optional[int] = None, ) -> None: - """Applies ext extension properties to the extended Item. + """Applies ext extension properties to the extended :class:`~pystac.Item` or + class:`~pystac.Asset`. Must specify at least one of orbit_state or relative_orbit in order for the sat extension to properties to be valid. @@ -67,11 +71,7 @@ def apply( @property def orbit_state(self) -> Optional[OrbitState]: - """Get or sets an orbit state of the item. - - Returns: - OrbitState or None - """ + """Get or sets an orbit state of the object.""" return map_opt(lambda x: OrbitState(x), self._get_property(ORBIT_STATE, str)) @orbit_state.setter @@ -80,11 +80,7 @@ def orbit_state(self, v: Optional[OrbitState]) -> None: @property def relative_orbit(self) -> Optional[int]: - """Get or sets a relative orbit number of the item. - - Returns: - int or None - """ + """Get or sets a relative orbit number of the item.""" return self._get_property(RELATIVE_ORBIT, int) @relative_orbit.setter @@ -97,6 +93,16 @@ def get_schema_uri(cls) -> str: @classmethod def ext(cls, obj: T, add_if_missing: bool = False) -> "SatExtension[T]": + """Extends the given STAC Object with properties from the :stac-ext:`Satellite + Extension `. + + This extension can be applied to instances of :class:`~pystac.Item` or + :class:`~pystac.Asset`. + + Raises: + + pystac.ExtensionTypeError : If an invalid object type is passed. + """ if isinstance(obj, pystac.Item): if add_if_missing: cls.add_to(obj) @@ -114,6 +120,21 @@ def ext(cls, obj: T, add_if_missing: bool = False) -> "SatExtension[T]": class ItemSatExtension(SatExtension[pystac.Item]): + """A concrete implementation of :class:`SatExtension` on an :class:`~pystac.Item` + that extends the properties of the Item to include properties defined in the + :stac-ext:`Satellite Extension `. + + This class should generally not be instantiated directly. Instead, call + :meth:`SatExtension.ext` on an :class:`~pystac.Item` to + extend it. + """ + + item: pystac.Item + """The :class:`~pystac.Item` being extended.""" + + properties: Dict[str, Any] + """The :class:`~pystac.Item` properties, including extension properties.""" + def __init__(self, item: pystac.Item): self.item = item self.properties = item.properties @@ -123,6 +144,25 @@ def __repr__(self) -> str: class AssetSatExtension(SatExtension[pystac.Asset]): + """A concrete implementation of :class:`SatExtension` on an :class:`~pystac.Asset` + that extends the properties of the Asset to include properties defined in the + :stac-ext:`Satellite Extension `. + + This class should generally not be instantiated directly. Instead, call + :meth:`SatExtension.ext` on an :class:`~pystac.Asset` to + extend it. + """ + + asset_href: str + """The ``href`` value of the :class:`~pystac.Asset` being extended.""" + + properties: Dict[str, Any] + """The :class:`~pystac.Asset` fields, including extension properties.""" + + additional_read_properties: Optional[Iterable[Dict[str, Any]]] = None + """If present, this will be a list containing 1 dictionary representing the + properties of the owning :class:`~pystac.Item`.""" + def __init__(self, asset: pystac.Asset): self.asset_href = asset.href self.properties = asset.properties From cfb7a2ac2bc9a513e1698bb6ef034f627b6a4501 Mon Sep 17 00:00:00 2001 From: Jon Duckworth Date: Wed, 7 Jul 2021 08:01:18 -0400 Subject: [PATCH 2/6] Add missing Sat Extension fields --- pystac/extensions/sat.py | 55 +++++++++++++++++++++++++++++----- tests/extensions/test_sat.py | 57 ++++++++++++++++++++++++++++++++---- 2 files changed, 99 insertions(+), 13 deletions(-) diff --git a/pystac/extensions/sat.py b/pystac/extensions/sat.py index ad5ff8d62..236556ae0 100644 --- a/pystac/extensions/sat.py +++ b/pystac/extensions/sat.py @@ -4,6 +4,7 @@ """ import enum +from datetime import datetime as Datetime from typing import Dict, Any, Generic, Iterable, Optional, Set, TypeVar, cast import pystac @@ -12,15 +13,20 @@ PropertiesExtension, ) from pystac.extensions.hooks import ExtensionHooks -from pystac.utils import map_opt +from pystac.utils import str_to_datetime, datetime_to_str, map_opt T = TypeVar("T", pystac.Item, pystac.Asset) SCHEMA_URI = "https://stac-extensions.github.io/sat/v1.0.0/schema.json" PREFIX: str = "sat:" -ORBIT_STATE: str = PREFIX + "orbit_state" -RELATIVE_ORBIT: str = PREFIX + "relative_orbit" +PLATFORM_INTERNATIONAL_DESIGNATOR_PROP: str = ( + PREFIX + "platform_international_designator" +) +ABSOLUTE_ORBIT_PROP: str = PREFIX + "absolute_orbit" +ORBIT_STATE_PROP: str = PREFIX + "orbit_state" +RELATIVE_ORBIT_PROP: str = PREFIX + "relative_orbit" +ANX_DATETIME_PROP: str = PREFIX + "anx_datetime" class OrbitState(str, enum.Enum): @@ -51,6 +57,9 @@ def apply( self, orbit_state: Optional[OrbitState] = None, relative_orbit: Optional[int] = None, + absolute_orbit: Optional[int] = None, + platform_international_designator: Optional[str] = None, + anx_datetime: Optional[Datetime] = None, ) -> None: """Applies ext extension properties to the extended :class:`~pystac.Item` or class:`~pystac.Asset`. @@ -66,26 +75,58 @@ def apply( the time of acquisition. """ + self.platform_international_designator = platform_international_designator self.orbit_state = orbit_state + self.absolute_orbit = absolute_orbit self.relative_orbit = relative_orbit + self.anx_datetime = anx_datetime + + @property + def platform_international_designator(self) -> Optional[str]: + """Gets or sets the International Designator, also known as COSPAR ID, and + NSSDCA ID.""" + return self._get_property(PLATFORM_INTERNATIONAL_DESIGNATOR_PROP, str) + + @platform_international_designator.setter + def platform_international_designator(self, v: Optional[str]) -> None: + self._set_property(PLATFORM_INTERNATIONAL_DESIGNATOR_PROP, v) @property def orbit_state(self) -> Optional[OrbitState]: """Get or sets an orbit state of the object.""" - return map_opt(lambda x: OrbitState(x), self._get_property(ORBIT_STATE, str)) + return map_opt( + lambda x: OrbitState(x), self._get_property(ORBIT_STATE_PROP, str) + ) @orbit_state.setter def orbit_state(self, v: Optional[OrbitState]) -> None: - self._set_property(ORBIT_STATE, map_opt(lambda x: x.value, v)) + self._set_property(ORBIT_STATE_PROP, map_opt(lambda x: x.value, v)) + + @property + def absolute_orbit(self) -> Optional[int]: + """Get or sets a absolute orbit number of the item.""" + return self._get_property(ABSOLUTE_ORBIT_PROP, int) + + @absolute_orbit.setter + def absolute_orbit(self, v: Optional[int]) -> None: + self._set_property(ABSOLUTE_ORBIT_PROP, v) @property def relative_orbit(self) -> Optional[int]: """Get or sets a relative orbit number of the item.""" - return self._get_property(RELATIVE_ORBIT, int) + return self._get_property(RELATIVE_ORBIT_PROP, int) @relative_orbit.setter def relative_orbit(self, v: Optional[int]) -> None: - self._set_property(RELATIVE_ORBIT, v) + self._set_property(RELATIVE_ORBIT_PROP, v) + + @property + def anx_datetime(self) -> Optional[Datetime]: + return map_opt(str_to_datetime, self._get_property(ANX_DATETIME_PROP, str)) + + @anx_datetime.setter + def anx_datetime(self, v: Optional[Datetime]) -> None: + self._set_property(ANX_DATETIME_PROP, map_opt(datetime_to_str, v)) @classmethod def get_schema_uri(cls) -> str: diff --git a/tests/extensions/test_sat.py b/tests/extensions/test_sat.py index 686ec4e4d..597253235 100644 --- a/tests/extensions/test_sat.py +++ b/tests/extensions/test_sat.py @@ -5,6 +5,7 @@ import unittest import pystac +from pystac.utils import str_to_datetime from pystac import ExtensionTypeError from pystac.extensions import sat from pystac.extensions.sat import SatExtension @@ -32,6 +33,21 @@ def setUp(self) -> None: def test_stac_extensions(self) -> None: self.assertTrue(SatExtension.has_extension(self.item)) + def test_item_repr(self) -> None: + sat_item_ext = SatExtension.ext(self.item) + self.assertEqual( + f"", sat_item_ext.__repr__() + ) + + def test_asset_repr(self) -> None: + item = pystac.Item.from_file(self.sentinel_example_uri) + asset = item.assets["measurement_iw1_vh"] + sat_asset_ext = SatExtension.ext(asset) + + self.assertEqual( + f"", sat_asset_ext.__repr__() + ) + def test_no_args_fails(self) -> None: SatExtension.ext(self.item).apply() with self.assertRaises(pystac.STACValidationError): @@ -41,16 +57,45 @@ def test_orbit_state(self) -> None: orbit_state = sat.OrbitState.ASCENDING SatExtension.ext(self.item).apply(orbit_state) self.assertEqual(orbit_state, SatExtension.ext(self.item).orbit_state) - self.assertNotIn(sat.RELATIVE_ORBIT, self.item.properties) - self.assertFalse(SatExtension.ext(self.item).relative_orbit) + self.assertNotIn(sat.RELATIVE_ORBIT_PROP, self.item.properties) + self.assertIsNone(SatExtension.ext(self.item).relative_orbit) self.item.validate() def test_relative_orbit(self) -> None: relative_orbit = 1234 SatExtension.ext(self.item).apply(None, relative_orbit) self.assertEqual(relative_orbit, SatExtension.ext(self.item).relative_orbit) - self.assertNotIn(sat.ORBIT_STATE, self.item.properties) - self.assertFalse(SatExtension.ext(self.item).orbit_state) + self.assertNotIn(sat.ORBIT_STATE_PROP, self.item.properties) + self.assertIsNone(SatExtension.ext(self.item).orbit_state) + self.item.validate() + + def test_absolute_orbit(self) -> None: + absolute_orbit = 1234 + SatExtension.ext(self.item).apply(absolute_orbit=absolute_orbit) + self.assertEqual(absolute_orbit, SatExtension.ext(self.item).absolute_orbit) + self.assertNotIn(sat.RELATIVE_ORBIT_PROP, self.item.properties) + self.assertIsNone(SatExtension.ext(self.item).relative_orbit) + self.item.validate() + + def test_anx_datetime(self) -> None: + anx_datetime = str_to_datetime("2020-01-01T00:00:00Z") + SatExtension.ext(self.item).apply(anx_datetime=anx_datetime) + self.assertEqual(anx_datetime, SatExtension.ext(self.item).anx_datetime) + self.assertNotIn(sat.RELATIVE_ORBIT_PROP, self.item.properties) + self.assertIsNone(SatExtension.ext(self.item).relative_orbit) + self.item.validate() + + def test_platform_international_designator(self) -> None: + platform_international_designator = "2018-080A" + SatExtension.ext(self.item).apply( + platform_international_designator=platform_international_designator + ) + self.assertEqual( + platform_international_designator, + SatExtension.ext(self.item).platform_international_designator, + ) + self.assertNotIn(sat.ORBIT_STATE_PROP, self.item.properties) + self.assertIsNone(SatExtension.ext(self.item).orbit_state) self.item.validate() def test_relative_orbit_no_negative(self) -> None: @@ -104,8 +149,8 @@ def test_to_from_dict(self) -> None: relative_orbit = 1002 SatExtension.ext(self.item).apply(orbit_state, relative_orbit) d = self.item.to_dict() - self.assertEqual(orbit_state.value, d["properties"][sat.ORBIT_STATE]) - self.assertEqual(relative_orbit, d["properties"][sat.RELATIVE_ORBIT]) + self.assertEqual(orbit_state.value, d["properties"][sat.ORBIT_STATE_PROP]) + self.assertEqual(relative_orbit, d["properties"][sat.RELATIVE_ORBIT_PROP]) item = pystac.Item.from_dict(d) self.assertEqual(orbit_state, SatExtension.ext(item).orbit_state) From fc3be8074915809494676196797e26f6ecf32eaf Mon Sep 17 00:00:00 2001 From: Jon Duckworth Date: Wed, 7 Jul 2021 08:01:18 -0400 Subject: [PATCH 3/6] Add Sat Extension summaries --- pystac/extensions/sat.py | 78 ++++++++++++++++++++++++- tests/extensions/test_sat.py | 110 ++++++++++++++++++++++++++++++++++- 2 files changed, 185 insertions(+), 3 deletions(-) diff --git a/pystac/extensions/sat.py b/pystac/extensions/sat.py index 236556ae0..db08b8ee5 100644 --- a/pystac/extensions/sat.py +++ b/pystac/extensions/sat.py @@ -5,12 +5,14 @@ import enum from datetime import datetime as Datetime -from typing import Dict, Any, Generic, Iterable, Optional, Set, TypeVar, cast +from pystac.summaries import RangeSummary +from typing import Dict, Any, List, Generic, Iterable, Optional, Set, TypeVar, cast import pystac from pystac.extensions.base import ( ExtensionManagementMixin, PropertiesExtension, + SummariesExtension, ) from pystac.extensions.hooks import ExtensionHooks from pystac.utils import str_to_datetime, datetime_to_str, map_opt @@ -159,6 +161,11 @@ def ext(cls, obj: T, add_if_missing: bool = False) -> "SatExtension[T]": f"Satellite extension does not apply to type '{type(obj).__name__}'" ) + @staticmethod + def summaries(obj: pystac.Collection) -> "SummariesSatExtension": + """Returns the extended summaries object for the given collection.""" + return SummariesSatExtension(obj) + class ItemSatExtension(SatExtension[pystac.Item]): """A concrete implementation of :class:`SatExtension` on an :class:`~pystac.Item` @@ -214,6 +221,75 @@ def __repr__(self) -> str: return "".format(self.asset_href) +class SummariesSatExtension(SummariesExtension): + """A concrete implementation of :class:`~SummariesExtension` that extends + the ``summaries`` field of a :class:`~pystac.Collection` to include properties + defined in the :stac-ext:`Satellite Extension `. + """ + + @property + def platform_international_designator(self) -> Optional[List[str]]: + """Get or sets the summary of + :attr:`SatExtension.platform_international_designator` values for this + Collection. + """ + + return self.summaries.get_list(PLATFORM_INTERNATIONAL_DESIGNATOR_PROP) + + @platform_international_designator.setter + def platform_international_designator(self, v: Optional[List[str]]) -> None: + self._set_summary(PLATFORM_INTERNATIONAL_DESIGNATOR_PROP, v) + + @property + def orbit_state(self) -> Optional[List[OrbitState]]: + """Get or sets the summary of :attr:`SatExtension.orbit_state` values + for this Collection. + """ + + return self.summaries.get_list(ORBIT_STATE_PROP) + + @orbit_state.setter + def orbit_state(self, v: Optional[List[OrbitState]]) -> None: + self._set_summary(ORBIT_STATE_PROP, v) + + @property + def absolute_orbit(self) -> Optional[RangeSummary[int]]: + return self.summaries.get_range(ABSOLUTE_ORBIT_PROP) + + @absolute_orbit.setter + def absolute_orbit(self, v: Optional[RangeSummary[int]]) -> None: + self._set_summary(ABSOLUTE_ORBIT_PROP, v) + + @property + def relative_orbit(self) -> Optional[RangeSummary[int]]: + return self.summaries.get_range(RELATIVE_ORBIT_PROP) + + @relative_orbit.setter + def relative_orbit(self, v: Optional[RangeSummary[int]]) -> None: + self._set_summary(RELATIVE_ORBIT_PROP, v) + + @property + def anx_datetime(self) -> Optional[RangeSummary[Datetime]]: + return map_opt( + lambda s: RangeSummary( + str_to_datetime(s.minimum), str_to_datetime(s.maximum) + ), + self.summaries.get_range(ANX_DATETIME_PROP), + ) + + @anx_datetime.setter + def anx_datetime(self, v: Optional[RangeSummary[Datetime]]) -> None: + self._set_summary( + ANX_DATETIME_PROP, + map_opt( + lambda s: RangeSummary( + datetime_to_str(s.minimum), datetime_to_str(s.maximum) + ), + v, + ), + ) + + class SatExtensionHooks(ExtensionHooks): schema_uri: str = SCHEMA_URI prev_extension_ids: Set[str] = set(["sat"]) diff --git a/tests/extensions/test_sat.py b/tests/extensions/test_sat.py index 597253235..391e92071 100644 --- a/tests/extensions/test_sat.py +++ b/tests/extensions/test_sat.py @@ -1,14 +1,15 @@ """Tests for pystac.extensions.sat.""" import datetime +from pystac.summaries import RangeSummary from typing import Any, Dict import unittest import pystac -from pystac.utils import str_to_datetime +from pystac.utils import str_to_datetime, datetime_to_str from pystac import ExtensionTypeError from pystac.extensions import sat -from pystac.extensions.sat import SatExtension +from pystac.extensions.sat import OrbitState, SatExtension from tests.utils import TestCases @@ -216,3 +217,108 @@ def test_should_raise_exception_when_passing_invalid_extension_object( SatExtension.ext, object(), ) + + +class SatSummariesTest(unittest.TestCase): + def setUp(self) -> None: + self.maxDiff = None + + self.collection = pystac.Collection.from_file( + TestCases.get_path("data-files/collections/multi-extent.json") + ) + + def test_platform_international_designation(self) -> None: + summaries_ext = SatExtension.summaries(self.collection) + platform_international_designator_list = ["2018-080A"] + + summaries_ext.platform_international_designator = ["2018-080A"] + + self.assertEqual( + summaries_ext.platform_international_designator, + platform_international_designator_list, + ) + + summaries_dict = self.collection.to_dict()["summaries"] + + self.assertEqual( + summaries_dict["sat:platform_international_designator"], + platform_international_designator_list, + ) + + def test_orbit_state(self) -> None: + summaries_ext = SatExtension.summaries(self.collection) + orbit_state_list = [OrbitState.ASCENDING] + + summaries_ext.orbit_state = orbit_state_list + + self.assertEqual( + summaries_ext.orbit_state, + orbit_state_list, + ) + + summaries_dict = self.collection.to_dict()["summaries"] + + self.assertEqual( + summaries_dict["sat:orbit_state"], + orbit_state_list, + ) + + def test_absolute_orbit(self) -> None: + summaries_ext = SatExtension.summaries(self.collection) + absolute_orbit_range = RangeSummary(2000, 3000) + + summaries_ext.absolute_orbit = absolute_orbit_range + + self.assertEqual( + summaries_ext.absolute_orbit, + absolute_orbit_range, + ) + + summaries_dict = self.collection.to_dict()["summaries"] + + self.assertEqual( + summaries_dict["sat:absolute_orbit"], + absolute_orbit_range.to_dict(), + ) + + def test_relative_orbit(self) -> None: + summaries_ext = SatExtension.summaries(self.collection) + relative_orbit_range = RangeSummary(50, 100) + + summaries_ext.relative_orbit = relative_orbit_range + + self.assertEqual( + summaries_ext.relative_orbit, + relative_orbit_range, + ) + + summaries_dict = self.collection.to_dict()["summaries"] + + self.assertEqual( + summaries_dict["sat:relative_orbit"], + relative_orbit_range.to_dict(), + ) + + def test_anx_datetime(self) -> None: + summaries_ext = SatExtension.summaries(self.collection) + anx_datetime_range = RangeSummary( + str_to_datetime("2020-01-01T00:00:00.000Z"), + str_to_datetime("2020-01-02T00:00:00.000Z"), + ) + + summaries_ext.anx_datetime = anx_datetime_range + + self.assertEqual( + summaries_ext.anx_datetime, + anx_datetime_range, + ) + + summaries_dict = self.collection.to_dict()["summaries"] + + self.assertDictEqual( + summaries_dict["sat:anx_datetime"], + { + "minimum": datetime_to_str(anx_datetime_range.minimum), + "maximum": datetime_to_str(anx_datetime_range.maximum), + }, + ) From ea9aebc3a29a4025811949005a88e2842f9dd661 Mon Sep 17 00:00:00 2001 From: Jon Duckworth Date: Thu, 1 Jul 2021 17:21:47 -0400 Subject: [PATCH 4/6] Update CHANGELOG and docs --- CHANGELOG.md | 3 +++ docs/api.rst | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fdd3dac9..63b6b518b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Timestamps Extension summaries ([#513](https://github.com/stac-utils/pystac/pull/513)) - Define equality and `__repr__` of `RangeSummary` instances based on `to_dict` representation ([#513](https://github.com/stac-utils/pystac/pull/513)) +- Sat Extension summaries ([#509](https://github.com/stac-utils/pystac/pull/509)) ### Changed @@ -24,6 +25,8 @@ - `Link` constructor classes (e.g. `Link.from_dict`, `Link.canonical`, etc.) now return the calling class instead of always returning the `Link` class ([#512](https://github.com/stac-utils/pystac/pull/512)) +- Sat extension now includes all fields defined in v1.0.0 + ([#509](https://github.com/stac-utils/pystac/pull/509)) ### Removed diff --git a/docs/api.rst b/docs/api.rst index f191cf6f9..dcd7db582 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -499,6 +499,45 @@ RasterExtension :show-inheritance: :inherited-members: +Satellite Extension +------------------- + +OrbitState +~~~~~~~~~~ + +.. autoclass:: pystac.extensions.sat.OrbitState + :members: + :show-inheritance: + :undoc-members: + +SatExtension +~~~~~~~~~~~~ + +.. autoclass:: pystac.extensions.sat.SatExtension + :members: + :show-inheritance: + +ItemSatExtension +~~~~~~~~~~~~ + +.. autoclass:: pystac.extensions.sat.ItemSatExtension + :members: + :show-inheritance: + +AssetSatExtension +~~~~~~~~~~~~ + +.. autoclass:: pystac.extensions.sat.AssetSatExtension + :members: + :show-inheritance: + +SummariesSatExtension +~~~~~~~~~~~~ + +.. autoclass:: pystac.extensions.sat.SummariesSatExtension + :members: + :show-inheritance: + Scientific Extension -------------------- From 4601a84e999aa60f842f93d687046770f0b8049b Mon Sep 17 00:00:00 2001 From: Jon Duckworth Date: Thu, 1 Jul 2021 17:29:49 -0400 Subject: [PATCH 5/6] Fix doc lint error --- docs/api.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index dcd7db582..e84c0ae39 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -518,21 +518,21 @@ SatExtension :show-inheritance: ItemSatExtension -~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~ .. autoclass:: pystac.extensions.sat.ItemSatExtension :members: :show-inheritance: AssetSatExtension -~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~ .. autoclass:: pystac.extensions.sat.AssetSatExtension :members: :show-inheritance: SummariesSatExtension -~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: pystac.extensions.sat.SummariesSatExtension :members: From 9a972d8f91921bc4afe7c1f21e083cd802a3149e Mon Sep 17 00:00:00 2001 From: Jon Duckworth Date: Thu, 1 Jul 2021 21:54:27 -0400 Subject: [PATCH 6/6] Create new catalog for each SAT extension test --- tests/extensions/test_sat.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/tests/extensions/test_sat.py b/tests/extensions/test_sat.py index 391e92071..850a43f3c 100644 --- a/tests/extensions/test_sat.py +++ b/tests/extensions/test_sat.py @@ -223,12 +223,15 @@ class SatSummariesTest(unittest.TestCase): def setUp(self) -> None: self.maxDiff = None - self.collection = pystac.Collection.from_file( + @staticmethod + def collection() -> pystac.Collection: + return pystac.Collection.from_file( TestCases.get_path("data-files/collections/multi-extent.json") ) def test_platform_international_designation(self) -> None: - summaries_ext = SatExtension.summaries(self.collection) + collection = self.collection() + summaries_ext = SatExtension.summaries(collection) platform_international_designator_list = ["2018-080A"] summaries_ext.platform_international_designator = ["2018-080A"] @@ -238,7 +241,7 @@ def test_platform_international_designation(self) -> None: platform_international_designator_list, ) - summaries_dict = self.collection.to_dict()["summaries"] + summaries_dict = collection.to_dict()["summaries"] self.assertEqual( summaries_dict["sat:platform_international_designator"], @@ -246,7 +249,8 @@ def test_platform_international_designation(self) -> None: ) def test_orbit_state(self) -> None: - summaries_ext = SatExtension.summaries(self.collection) + collection = self.collection() + summaries_ext = SatExtension.summaries(collection) orbit_state_list = [OrbitState.ASCENDING] summaries_ext.orbit_state = orbit_state_list @@ -256,7 +260,7 @@ def test_orbit_state(self) -> None: orbit_state_list, ) - summaries_dict = self.collection.to_dict()["summaries"] + summaries_dict = collection.to_dict()["summaries"] self.assertEqual( summaries_dict["sat:orbit_state"], @@ -264,7 +268,8 @@ def test_orbit_state(self) -> None: ) def test_absolute_orbit(self) -> None: - summaries_ext = SatExtension.summaries(self.collection) + collection = self.collection() + summaries_ext = SatExtension.summaries(collection) absolute_orbit_range = RangeSummary(2000, 3000) summaries_ext.absolute_orbit = absolute_orbit_range @@ -274,7 +279,7 @@ def test_absolute_orbit(self) -> None: absolute_orbit_range, ) - summaries_dict = self.collection.to_dict()["summaries"] + summaries_dict = collection.to_dict()["summaries"] self.assertEqual( summaries_dict["sat:absolute_orbit"], @@ -282,7 +287,8 @@ def test_absolute_orbit(self) -> None: ) def test_relative_orbit(self) -> None: - summaries_ext = SatExtension.summaries(self.collection) + collection = self.collection() + summaries_ext = SatExtension.summaries(collection) relative_orbit_range = RangeSummary(50, 100) summaries_ext.relative_orbit = relative_orbit_range @@ -292,7 +298,7 @@ def test_relative_orbit(self) -> None: relative_orbit_range, ) - summaries_dict = self.collection.to_dict()["summaries"] + summaries_dict = collection.to_dict()["summaries"] self.assertEqual( summaries_dict["sat:relative_orbit"], @@ -300,7 +306,8 @@ def test_relative_orbit(self) -> None: ) def test_anx_datetime(self) -> None: - summaries_ext = SatExtension.summaries(self.collection) + collection = self.collection() + summaries_ext = SatExtension.summaries(collection) anx_datetime_range = RangeSummary( str_to_datetime("2020-01-01T00:00:00.000Z"), str_to_datetime("2020-01-02T00:00:00.000Z"), @@ -313,7 +320,7 @@ def test_anx_datetime(self) -> None: anx_datetime_range, ) - summaries_dict = self.collection.to_dict()["summaries"] + summaries_dict = collection.to_dict()["summaries"] self.assertDictEqual( summaries_dict["sat:anx_datetime"],