From 1be0027fbaf2dd31187ccf646e30edb401455834 Mon Sep 17 00:00:00 2001 From: Tyler <31015976+tylanderson@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:38:37 -0400 Subject: [PATCH 1/2] Add roles to common metadata (#1444) * add roles * update changelog * Update pystac/common_metadata.py --------- Co-authored-by: Pete Gadomski --- CHANGELOG.md | 1 + pystac/common_metadata.py | 9 ++++++++ .../item/sample-item-asset-properties.json | 1 + tests/test_common_metadata.py | 22 +++++++++++++++++++ 4 files changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 254536bea..55652f938 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Add netCDF to pystac.media_type ([#1386](https://github.com/stac-utils/pystac/pull/1386)) - Add convenience method for accessing pystac_client ([#1365](https://github.com/stac-utils/pystac/pull/1365)) - Fix field ordering when saving `Item`s ([#1423](https://github.com/stac-utils/pystac/pull/1423)) +- Add roles to common metadata ([#1444](https://github.com/stac-utils/pystac/pull/1444/files)) ### Changed diff --git a/pystac/common_metadata.py b/pystac/common_metadata.py index c2d12e71d..77404b5b5 100644 --- a/pystac/common_metadata.py +++ b/pystac/common_metadata.py @@ -213,3 +213,12 @@ def updated(self) -> datetime | None: @updated.setter def updated(self, v: datetime | None) -> None: self._set_field("updated", utils.map_opt(utils.datetime_to_str, v)) + + @property + def roles(self) -> list[str] | None: + """Get or set the semantic roles of the entity.""" + return self._get_field("roles", list[str]) + + @roles.setter + def roles(self, v: list[str] | None) -> None: + self._set_field("roles", v) diff --git a/tests/data-files/item/sample-item-asset-properties.json b/tests/data-files/item/sample-item-asset-properties.json index a47273ea0..78be8ac57 100644 --- a/tests/data-files/item/sample-item-asset-properties.json +++ b/tests/data-files/item/sample-item-asset-properties.json @@ -74,6 +74,7 @@ "start_datetime": "2017-05-01T13:22:30.040Z", "end_datetime": "2017-05-02T13:22:30.040Z", "license": "CC-BY-4.0", + "roles": ["a_role"], "providers": [ { "name": "USGS", diff --git a/tests/test_common_metadata.py b/tests/test_common_metadata.py index f7113481c..e18072672 100644 --- a/tests/test_common_metadata.py +++ b/tests/test_common_metadata.py @@ -538,3 +538,25 @@ def test_updated(self) -> None: self.assertEqual( analytic.to_dict()["updated"], utils.datetime_to_str(set_value) ) + + def test_roles(self) -> None: + item = self.item.clone() + cm = item.common_metadata + analytic = item.assets["analytic"] + analytic_cm = CommonMetadata(analytic) + thumbnail = item.assets["thumbnail"] + thumbnail_cm = CommonMetadata(thumbnail) + + item_value = cm.roles + a2_known_value = ["a_role"] + + # Get + self.assertNotEqual(thumbnail_cm.roles, item_value) + self.assertEqual(thumbnail_cm.roles, a2_known_value) + + # Set + set_value = ["another_role"] + analytic_cm.roles = set_value + + self.assertEqual(analytic_cm.roles, set_value) + self.assertEqual(analytic.to_dict()["roles"], set_value) From 778725d70e5712c73e6a213a5e7afa2db51c32f0 Mon Sep 17 00:00:00 2001 From: Tyler <31015976+tylanderson@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:42:44 -0400 Subject: [PATCH 2/2] Update and clarify description, license, datetime properties (#1445) * fix docstrings for license #1377 * clarify datetime range is inclusive #1382 * ensure description is not empty #1381 * pass tests * test empty description * update changelog * Update pystac/collection.py * Update pystac/common_metadata.py --------- Co-authored-by: Pete Gadomski --- CHANGELOG.md | 1 + pystac/collection.py | 9 +++++---- pystac/common_metadata.py | 24 +++++++++++++++++++++--- pystac/item.py | 8 ++++---- tests/test_common_metadata.py | 2 ++ 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55652f938..3e1a8576f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - Add example of custom `StacIO` for Azure Blob Storage to docs ([#1372](https://github.com/stac-utils/pystac/pull/1372)) - Noted that collection links can be used in non-item objects in STAC v1.1.0 ([#1393](https://github.com/stac-utils/pystac/pull/1393)) - Move test, docs, and bench requirements out of pyproject.toml ([#1407](https://github.com/stac-utils/pystac/pull/1407)) +- Clarify inclusive datetime ranges, update default license, and ensure description is not empty ([#1445](https://github.com/stac-utils/pystac/pull/1445)) ### Fixed diff --git a/pystac/collection.py b/pystac/collection.py index f8e588bfd..9c0c24b7f 100644 --- a/pystac/collection.py +++ b/pystac/collection.py @@ -461,9 +461,10 @@ class Collection(Catalog, Assets): be one of the values in :class`~pystac.CatalogType`. license : Collection's license(s) as a `SPDX License identifier `_, - `various`, or `proprietary`. If collection includes - data with multiple different licenses, use `various` and add a link for - each. Defaults to 'proprietary'. + or `other`. If collection includes data with multiple + different licenses, use `other` and add a link for + each. The licenses `various` and `proprietary` are deprecated. + Defaults to 'other'. keywords : Optional list of keywords describing the collection. providers : Optional list of providers of this Collection. summaries : An optional map of property summaries, @@ -528,7 +529,7 @@ def __init__( href: str | None = None, extra_fields: dict[str, Any] | None = None, catalog_type: CatalogType | None = None, - license: str = "proprietary", + license: str = "other", keywords: list[str] | None = None, providers: list[Provider] | None = None, summaries: Summaries | None = None, diff --git a/pystac/common_metadata.py b/pystac/common_metadata.py index 77404b5b5..11081266a 100644 --- a/pystac/common_metadata.py +++ b/pystac/common_metadata.py @@ -80,12 +80,18 @@ def description(self) -> str | None: @description.setter def description(self, v: str | None) -> None: + if v == "": + raise ValueError("description cannot be an empty string") self._set_field("description", v) # Date and Time Range @property def start_datetime(self) -> datetime | None: - """Get or set the object's start_datetime.""" + """Get or set the object's start_datetime. + + Note: + ``start_datetime`` is an inclusive datetime. + """ return utils.map_opt( utils.str_to_datetime, self._get_field("start_datetime", str) ) @@ -96,7 +102,11 @@ def start_datetime(self, v: datetime | None) -> None: @property def end_datetime(self) -> datetime | None: - """Get or set the item's end_datetime.""" + """Get or set the item's end_datetime. + + Note: + ``end_datetime`` is an inclusive datetime. + """ return utils.map_opt( utils.str_to_datetime, self._get_field("end_datetime", str) ) @@ -108,7 +118,15 @@ def end_datetime(self, v: datetime | None) -> None: # License @property def license(self) -> str | None: - """Get or set the current license.""" + """Get or set the current license. License should be provided + as a `SPDX License identifier `_, + or `other`. If object includes data with multiple + different licenses, use `other` and add a link for + each. + + Note: + The licenses `various` and `proprietary` are deprecated. + """ return self._get_field("license", str) @license.setter diff --git a/pystac/item.py b/pystac/item.py index 054f124d1..c2af036df 100644 --- a/pystac/item.py +++ b/pystac/item.py @@ -51,10 +51,10 @@ class Item(STACObject, Assets): datetime : datetime associated with this item. If None, a start_datetime and end_datetime must be supplied. properties : A dictionary of additional metadata for the item. - start_datetime : Optional start datetime, part of common metadata. This value - will override any `start_datetime` key in properties. - end_datetime : Optional end datetime, part of common metadata. This value - will override any `end_datetime` key in properties. + start_datetime : Optional inclusive start datetime, part of common metadata. + This value will override any `start_datetime` key in properties. + end_datetime : Optional inclusive end datetime, part of common metadata. + This value will override any `end_datetime` key in properties. stac_extensions : Optional list of extensions the Item implements. href : Optional HREF for this item, which be set as the item's self link's HREF. diff --git a/tests/test_common_metadata.py b/tests/test_common_metadata.py index e18072672..21e1a2e78 100644 --- a/tests/test_common_metadata.py +++ b/tests/test_common_metadata.py @@ -176,6 +176,8 @@ def test_common_metadata_basics(self) -> None: x.common_metadata.description = example_description self.assertEqual(x.common_metadata.description, example_description) self.assertEqual(x.properties["description"], example_description) + with self.assertRaises(ValueError): + x.common_metadata.description = "" # License license = "PDDL-1.0"