Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract method to correctly handle setting properties in Item/Asset for ItemExtensions #272

Merged
merged 3 commits into from
Mar 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions pystac/extensions/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,30 @@ def enable_extension(cls, stac_object):
"""
pass

def _set_property(self, key, value, asset):
'''
Set an Item or an Asset property.

If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.

If the passed value to set is None, the property key is removed from
the dictionary of properties.

It's recommended to use this method from extensions, instead of implementing
the logic for that in the corresponding subclasses.

Args:
key (str): The name of the property
value (Object): the value to set
asset: The Asset to modify. If None, the property will be set in the Item
'''
target = self.item.properties if asset is None else asset.properties
if value is None:
target.pop(key, None)
else:
target[key] = value


class RegisteredSTACExtensions:
def __init__(self, extension_definitions):
Expand Down
10 changes: 2 additions & 8 deletions pystac/extensions/eo.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,7 @@ def set_bands(self, bands, asset=None):
Otherwise sets the Item's value.
"""
band_dicts = [b.to_dict() for b in bands]
if asset is not None:
asset.properties['eo:bands'] = band_dicts
else:
self.item.properties['eo:bands'] = band_dicts
self._set_property('eo:bands', band_dicts, asset)

@property
def cloud_cover(self):
Expand Down Expand Up @@ -124,10 +121,7 @@ def set_cloud_cover(self, cloud_cover, asset=None):
If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
if asset is None:
self.item.properties['eo:cloud_cover'] = cloud_cover
else:
asset.properties['eo:cloud_cover'] = cloud_cover
self._set_property('eo:cloud_cover', cloud_cover, asset)

def __repr__(self):
return '<EOItemExt Item id={}>'.format(self.item.id)
Expand Down
30 changes: 6 additions & 24 deletions pystac/extensions/pointcloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,7 @@ def set_count(self, count, asset=None):
If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
if asset is None:
self.item.properties['pc:count'] = count
else:
asset.properties['pc:count'] = count
self._set_property('pc:count', count, asset)

@property
def type(self):
Expand Down Expand Up @@ -117,10 +114,7 @@ def set_type(self, type, asset=None):
If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
if asset is None:
self.item.properties['pc:type'] = type
else:
asset.properties['pc:type'] = type
self._set_property('pc:type', type, asset)

@property
def encoding(self):
Expand Down Expand Up @@ -158,10 +152,7 @@ def set_encoding(self, encoding, asset=None):
If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
if asset is None:
self.item.properties['pc:encoding'] = encoding
else:
asset.properties['pc:encoding'] = encoding
self._set_property('pc:encoding', encoding, asset)

@property
def schemas(self):
Expand Down Expand Up @@ -202,10 +193,7 @@ def set_schemas(self, schemas, asset=None):
Otherwise sets the Item's value.
"""
dicts = [s.to_dict() for s in schemas]
if asset is None:
self.item.properties['pc:schemas'] = dicts
else:
asset.properties['pc:schemas'] = dicts
self._set_property('pc:schemas', dicts, asset)

@property
def density(self):
Expand Down Expand Up @@ -242,10 +230,7 @@ def set_density(self, density, asset=None):
If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
if asset is None:
self.item.properties['pc:density'] = density
else:
asset.properties['pc:density'] = density
self._set_property('pc:density', density, asset)

@property
def statistics(self):
Expand Down Expand Up @@ -289,10 +274,7 @@ def set_statistics(self, statistics, asset=None):
"""
if statistics is not None:
statistics = [s.to_dict() for s in statistics]
if asset is None:
self.item.properties['pc:statistics'] = statistics
else:
asset.properties['pc:statistics'] = statistics
self._set_property('pc:statistics', statistics, asset)

@classmethod
def _object_links(cls):
Expand Down
68 changes: 15 additions & 53 deletions pystac/extensions/projection.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,7 @@ def set_epsg(self, epsg, asset=None):
If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
if asset is None:
self.item.properties['proj:epsg'] = epsg
else:
asset.properties['proj:epsg'] = epsg
self._set_property('proj:epsg', epsg, asset)

@property
def wkt2(self):
Expand Down Expand Up @@ -141,18 +138,13 @@ def get_wkt2(self, asset=None):
else:
return asset.properties.get('proj:wkt2')

def set_wkt2(self, value, asset=None):
def set_wkt2(self, wkt2, asset=None):
"""Set an Item or an Asset wkt2.

If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
key = 'proj:wkt2'
target = self.item.properties if asset is None else asset.properties
if value is None:
target.pop(key, None)
else:
target[key] = value
self._set_property('proj:wkt2', wkt2, asset)

@property
def projjson(self):
Expand Down Expand Up @@ -190,18 +182,13 @@ def get_projjson(self, asset=None):
else:
return asset.properties.get('proj:projjson')

def set_projjson(self, value, asset=None):
def set_projjson(self, projjson, asset=None):
"""Set an Item or an Asset projjson.

If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
key = 'proj:projjson'
target = self.item.properties if asset is None else asset.properties
if value is None:
target.pop(key, None)
else:
target[key] = value
self._set_property('proj:projjson', projjson, asset)

@property
def geometry(self):
Expand Down Expand Up @@ -237,18 +224,13 @@ def get_geometry(self, asset=None):
else:
return asset.properties.get('proj:geometry')

def set_geometry(self, value, asset=None):
def set_geometry(self, geometry, asset=None):
"""Set an Item or an Asset projection geometry.

If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
key = 'proj:geometry'
target = self.item.properties if asset is None else asset.properties
if value is None:
target.pop(key, None)
else:
target[key] = value
self._set_property('proj:geometry', geometry, asset)

@property
def bbox(self):
Expand Down Expand Up @@ -285,18 +267,13 @@ def get_bbox(self, asset=None):
else:
return asset.properties.get('proj:bbox')

def set_bbox(self, value, asset=None):
def set_bbox(self, bbox, asset=None):
"""Set an Item or an Asset projection bbox.

If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
key = 'proj:bbox'
target = self.item.properties if asset is None else asset.properties
if value is None:
target.pop(key, None)
else:
target[key] = value
self._set_property('proj:bbox', bbox, asset)

@property
def centroid(self):
Expand Down Expand Up @@ -332,18 +309,13 @@ def get_centroid(self, asset=None):
else:
return asset.properties.get('proj:centroid')

def set_centroid(self, value, asset=None):
def set_centroid(self, centroid, asset=None):
"""Set an Item or an Asset centroid.

If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
key = 'proj:centroid'
target = self.item.properties if asset is None else asset.properties
if value is None:
target.pop(key, None)
else:
target[key] = value
self._set_property('proj:centroid', centroid, asset)

@property
def shape(self):
Expand Down Expand Up @@ -377,18 +349,13 @@ def get_shape(self, asset=None):
else:
return asset.properties.get('proj:shape')

def set_shape(self, value, asset=None):
def set_shape(self, shape, asset=None):
"""Set an Item or an Asset shape.

If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
key = 'proj:shape'
target = self.item.properties if asset is None else asset.properties
if value is None:
target.pop(key, None)
else:
target[key] = value
self._set_property('proj:shape', shape, asset)

@property
def transform(self):
Expand Down Expand Up @@ -425,18 +392,13 @@ def get_transform(self, asset=None):
else:
return asset.properties.get('proj:transform')

def set_transform(self, value, asset=None):
def set_transform(self, transform, asset=None):
"""Set an Item or an Asset transform.

If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
key = 'proj:transform'
target = self.item.properties if asset is None else asset.properties
if value is None:
target.pop(key, None)
else:
target[key] = value
self._set_property('proj:transform', transform, asset)

@classmethod
def _object_links(cls):
Expand Down
11 changes: 3 additions & 8 deletions pystac/extensions/timestamps.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,9 @@ def _timestamp_getter(self, key, asset=None):
return timestamp

def _timestamp_setter(self, timestamp, key, asset=None):
if timestamp is None:
self.item.properties[key] = timestamp
else:
timestamp_str = datetime_to_str(timestamp)
if asset is not None:
asset.properties[key] = timestamp_str
else:
self.item.properties[key] = timestamp_str
if timestamp is not None:
timestamp = datetime_to_str(timestamp)
self._set_property(key, timestamp, asset)

@property
def published(self):
Expand Down
25 changes: 5 additions & 20 deletions pystac/extensions/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,7 @@ def set_off_nadir(self, off_nadir, asset=None):
If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
if asset is None:
self.item.properties['view:off_nadir'] = off_nadir
else:
asset.properties['view:off_nadir'] = off_nadir
self._set_property('view:off_nadir', off_nadir, asset)

@property
def incidence_angle(self):
Expand Down Expand Up @@ -141,10 +138,7 @@ def set_incidence_angle(self, incidence_angle, asset=None):
If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
if asset is None:
self.item.properties['view:incidence_angle'] = incidence_angle
else:
asset.properties['view:incidence_angle'] = incidence_angle
self._set_property('view:incidence_angle', incidence_angle, asset)

@property
def azimuth(self):
Expand Down Expand Up @@ -181,10 +175,7 @@ def set_azimuth(self, azimuth, asset=None):
If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
if asset is None:
self.item.properties['view:azimuth'] = azimuth
else:
asset.properties['view:azimuth'] = azimuth
self._set_property('view:azimuth', azimuth, asset)

@property
def sun_azimuth(self):
Expand Down Expand Up @@ -220,10 +211,7 @@ def set_sun_azimuth(self, sun_azimuth, asset=None):
If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
if asset is None:
self.item.properties['view:sun_azimuth'] = sun_azimuth
else:
asset.properties['view:sun_azimuth'] = sun_azimuth
self._set_property('view:sun_azimuth', sun_azimuth, asset)

@property
def sun_elevation(self):
Expand Down Expand Up @@ -259,10 +247,7 @@ def set_sun_elevation(self, sun_elevation, asset=None):
If an Asset is supplied, sets the property on the Asset.
Otherwise sets the Item's value.
"""
if asset is None:
self.item.properties['view:sun_elevation'] = sun_elevation
else:
asset.properties['view:sun_elevation'] = sun_elevation
self._set_property('view:sun_elevation', sun_elevation, asset)

@classmethod
def _object_links(cls):
Expand Down
2 changes: 1 addition & 1 deletion tests/extensions/test_timestamps.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def test_apply(self):
self.assertIsNone(d)

for p in ('expires', 'unpublished'):
self.assertIsNone(item.properties[p])
self.assertNotIn(p, item.properties)

def test_validate_timestamps(self):
item = pystac.read_file(self.example_uri)
Expand Down