Skip to content

Commit 0040d60

Browse files
committed
Issue #860: align STAC parsing with "name" not being required in "bands"
1 parent bfcd173 commit 0040d60

File tree

4 files changed

+121
-7
lines changed

4 files changed

+121
-7
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414

1515
### Changed
1616

17+
- Harden STAC parsing of "bands"/"eo:bands" when "name" field is not present (which is technically not a required field) ([#860](https://github.com/Open-EO/openeo-python-client/issues/860))
18+
1719
### Removed
1820

1921
### Fixed

openeo/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.48.0a3"
1+
__version__ = "0.48.0a4"

openeo/metadata.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,10 @@ class Band(NamedTuple):
117117
and https://github.com/stac-extensions/eo#band-object
118118
"""
119119

120-
name: str
120+
# Note: "name" is strictly speaking not required per spec,
121+
# but it's probably assumed to be present in a lot of places.
122+
name: Optional[str]
123+
121124
common_name: Optional[str] = None
122125
# wavelength in micrometer
123126
wavelength_um: Optional[float] = None
@@ -799,9 +802,9 @@ def _band_from_eo_bands_metadata(self, band: Union[dict, pystac.extensions.eo.Ba
799802
common_name=band.common_name,
800803
wavelength_um=band.center_wavelength,
801804
)
802-
elif isinstance(band, dict) and "name" in band:
805+
elif isinstance(band, dict):
803806
return Band(
804-
name=band["name"],
807+
name=band.get("name"),
805808
common_name=band.get("common_name"),
806809
wavelength_um=band.get("center_wavelength"),
807810
)
@@ -812,7 +815,7 @@ def _band_from_common_bands_metadata(self, data: dict) -> Band:
812815
"""Construct band from metadata dict in STAC 1.1 + eo v2 style metadata"""
813816
# TODO: also support pystac wrapper when available (pystac v2?)
814817
return Band(
815-
name=data["name"],
818+
name=data.get("name"),
816819
common_name=data.get("eo:common_name"),
817820
wavelength_um=data.get("eo:center_wavelength"),
818821
)

tests/test_metadata.py

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,22 +1370,32 @@ def test_cube_metadata_repr_no_bands():
13701370

13711371

13721372
class TestStacMetadataParser:
1373-
def test_band_from_eo_bands_metadata(self):
1373+
def test_band_from_eo_bands_metadata_basic(self):
13741374
assert _StacMetadataParser()._band_from_eo_bands_metadata(
13751375
{"name": "B04"},
13761376
) == Band(name="B04")
1377+
1378+
def test_band_from_eo_bands_metadata_fields(self):
13771379
assert _StacMetadataParser()._band_from_eo_bands_metadata(
13781380
{"name": "B04", "common_name": "red", "center_wavelength": 0.665}
13791381
) == Band(name="B04", common_name="red", wavelength_um=0.665)
13801382

1381-
def test_band_from_common_bands_metadata(self):
1383+
def test_band_from_eo_bands_metadata_empty(self):
1384+
assert _StacMetadataParser()._band_from_eo_bands_metadata({}) == Band(name=None)
1385+
1386+
def test_band_from_common_bands_metadata_basic(self):
13821387
assert _StacMetadataParser()._band_from_common_bands_metadata(
13831388
{"name": "B04"},
13841389
) == Band(name="B04")
1390+
1391+
def test_band_from_common_bands_metadata_fields(self):
13851392
assert _StacMetadataParser()._band_from_common_bands_metadata(
13861393
{"name": "B04", "eo:common_name": "red", "eo:center_wavelength": 0.665}
13871394
) == Band(name="B04", common_name="red", wavelength_um=0.665)
13881395

1396+
def test_band_from_common_bands_metadata_emtpy(self):
1397+
assert _StacMetadataParser()._band_from_common_bands_metadata({}) == Band(name=None)
1398+
13891399
@pytest.mark.parametrize(
13901400
["data", "expected", "expected_warnings"],
13911401
[
@@ -1476,6 +1486,25 @@ def test_band_from_common_bands_metadata(self):
14761486
"bands_from_stac_catalog with summaries.keys()=dict_keys(['bands']) (which is non-standard)",
14771487
],
14781488
),
1489+
(
1490+
{
1491+
"type": "Catalog",
1492+
"id": "catalog123",
1493+
"description": "Catalog 123",
1494+
"stac_version": "1.1.0",
1495+
"summaries": {
1496+
"bands": [
1497+
{"eo:common_name": "blue"},
1498+
{"name": "B03"},
1499+
],
1500+
},
1501+
"links": [],
1502+
},
1503+
[Band(name=None, common_name="blue"), Band("B03")],
1504+
[
1505+
"bands_from_stac_catalog with summaries.keys()=dict_keys(['bands']) (which is non-standard)",
1506+
],
1507+
),
14791508
],
14801509
)
14811510
def test_bands_from_stac_catalog(self, data, expected, expected_warnings, caplog):
@@ -1547,6 +1576,23 @@ def test_bands_from_stac_catalog(self, data, expected, expected_warnings, caplog
15471576
],
15481577
[],
15491578
),
1579+
(
1580+
StacDummyBuilder.collection(
1581+
stac_version="1.1.0",
1582+
stac_extensions=["https://stac-extensions.github.io/eo/v1.1.0/schema.json"],
1583+
summaries={
1584+
"bands": [
1585+
{"eo:common_name": "red"},
1586+
{"name": "B03", "eo:common_name": "green", "eo:center_wavelength": 0.560},
1587+
],
1588+
},
1589+
),
1590+
[
1591+
Band(name=None, common_name="red"),
1592+
Band("B03", common_name="green", wavelength_um=0.560),
1593+
],
1594+
[],
1595+
),
15501596
],
15511597
)
15521598
def test_bands_from_stac_collection(self, data, expected, caplog, expected_warnings):
@@ -1768,6 +1814,25 @@ def test_bands_from_stac_collection_consult_items(
17681814
Band("B03", common_name="green", wavelength_um=0.560),
17691815
],
17701816
),
1817+
(
1818+
StacDummyBuilder.item(
1819+
stac_version="1.0.0",
1820+
stac_extensions=["https://stac-extensions.github.io/eo/v1.1.0/schema.json"],
1821+
properties={
1822+
"eo:bands": [{"nonane": "nope"}, {"name": "B03"}],
1823+
},
1824+
),
1825+
[Band(name=None), Band("B03")],
1826+
),
1827+
(
1828+
StacDummyBuilder.item(
1829+
stac_version="1.1.0",
1830+
properties={
1831+
"bands": [{"eo:common_name": "blue"}, {"name": "B03"}],
1832+
},
1833+
),
1834+
[Band(name=None, common_name="blue"), Band("B03")],
1835+
),
17711836
],
17721837
)
17731838
def test_bands_from_stac_item(self, data, expected):
@@ -1800,6 +1865,15 @@ def test_bands_from_stac_item_no_bands(self):
18001865
),
18011866
["B04", "B03"],
18021867
),
1868+
(
1869+
StacDummyBuilder.item(
1870+
stac_version="1.1.0",
1871+
properties={
1872+
"bands": [{"eo:common_name": "blue"}, {"name": "B03"}],
1873+
},
1874+
),
1875+
[None, "B03"],
1876+
),
18031877
],
18041878
)
18051879
def test_bands_from_stac_item_band_names(self, data, expected):
@@ -2007,6 +2081,26 @@ def test_bands_from_stac_item_consult_assets(self, data, expected, kwargs):
20072081
},
20082082
["B04", "B03"],
20092083
),
2084+
(
2085+
{
2086+
"href": "https://stac.test/asset.tif",
2087+
"bands": [
2088+
{"raster:scale": 3.14},
2089+
{"name": "B03"},
2090+
],
2091+
},
2092+
[None, "B03"],
2093+
),
2094+
(
2095+
{
2096+
"href": "https://stac.test/asset.tif",
2097+
"eo:bands": [
2098+
{"center_wavelength": 0.5},
2099+
{"name": "B03"},
2100+
],
2101+
},
2102+
[None, "B03"],
2103+
),
20102104
],
20112105
)
20122106
def test_bands_from_stac_asset(self, data, expected):
@@ -2077,6 +2171,21 @@ def test_bands_from_stac_asset(self, data, expected):
20772171
["B03", "B02", "B04"],
20782172
["Deriving band listing from unordered `item_assets`"],
20792173
),
2174+
(
2175+
# STAC 1.1 Collection with "eo" extension based band metadata
2176+
StacDummyBuilder.collection(
2177+
stac_version="1.1.0",
2178+
stac_extensions=[
2179+
"https://stac-extensions.github.io/eo/v1.1.0/schema.json",
2180+
],
2181+
item_assets={
2182+
"asset1": {"eo:bands": [{"noname": "noname"}, {"name": "B02"}]},
2183+
"asset2": {"eo:bands": [{"name": "B04"}]},
2184+
},
2185+
),
2186+
[None, "B02", "B04"],
2187+
["Deriving band listing from unordered `item_assets`"],
2188+
),
20802189
],
20812190
)
20822191
def test_bands_from_stac_collection_with_item_assets(

0 commit comments

Comments
 (0)