Bases: DataObjectSupportingAggregation
Represents a Geo Feature Aggregation in HydroShare
Source code in hsclient\hydroshare.py
class GeoFeatureAggregation(DataObjectSupportingAggregation):
"""Represents a Geo Feature Aggregation in HydroShare"""
@classmethod
def create(cls, base_aggr):
return super().create(aggr_cls=cls, base_aggr=base_aggr)
def _validate_aggregation_path(self, agg_path: str, for_save_data: bool = False) -> str:
if for_save_data:
for aggr_file in self.files():
aggr_file = basename(aggr_file)
if aggr_file.endswith(".shp.xml") or aggr_file.endswith(".sbn") or aggr_file.endswith(".sbx"):
# these are optional files for geo feature aggregation
continue
if not os.path.exists(os.path.join(agg_path, aggr_file)):
raise Exception(f"Aggregation path '{agg_path}' is not a valid path. "
f"Missing file '{aggr_file}'")
file_path = self._get_file_path(agg_path)
return file_path
def as_data_object(self, agg_path: str) -> 'fiona.Collection':
"""
Loads the Geo Feature aggregation to a fiona Collection object
:param agg_path: the path to the Geo Feature aggregation
:return: the Geo Feature aggregation as a fiona Collection object
"""
if fiona is None:
raise Exception("fiona package was not found")
return self._get_data_object(agg_path=agg_path, func=fiona.open)
def save_data_object(self, resource: 'Resource', agg_path: str, as_new_aggr: bool = False,
destination_path: str = "") -> 'Aggregation':
"""
Saves the fiona Collection object to the Geo Feature aggregation
:param resource: the resource containing the aggregation
:param agg_path: the path to the Geo Feature aggregation
:param as_new_aggr: Defaults False, set to True to create a new Geo Feature aggregation
:param destination_path: the destination path in Hydroshare to save the new aggregation
:return: the updated or new Geo Feature aggregation
"""
def upload_shape_files(main_file_path, dst_path=""):
shp_file_dir_path = os.path.dirname(main_file_path)
filename_starts_with = f"{pathlib.Path(main_file_path).stem}."
shape_files = []
for item in os.listdir(shp_file_dir_path):
if item.startswith(filename_starts_with):
file_full_path = os.path.join(shp_file_dir_path, item)
shape_files.append(file_full_path)
if not dst_path:
self._update_aggregation(resource, *shape_files)
else:
resource.file_upload(*shape_files, destination_path=dst_path)
self._validate_aggregation_for_update(resource, AggregationType.GeographicFeatureAggregation)
file_path = self._validate_aggregation_path(agg_path, for_save_data=True)
aggr_main_file_path = self.main_file_path
data_object = self._data_object
# need to close the fiona.Collection object to free up access to all the original shape files
data_object.close()
if not as_new_aggr:
# cache some of the metadata fields of the original aggregation to update the metadata of the
# updated aggregation
keywords = self.metadata.subjects
additional_meta = self.metadata.additional_metadata
# copy the updated shape files to the original shape file location where the user downloaded the
# aggregation previously
src_shp_file_dir_path = os.path.dirname(file_path)
tgt_shp_file_dir_path = os.path.dirname(data_object.path)
filename_starts_with = f"{pathlib.Path(file_path).stem}."
for item in os.listdir(src_shp_file_dir_path):
if item.startswith(filename_starts_with):
src_file_full_path = os.path.join(src_shp_file_dir_path, item)
tgt_file_full_path = os.path.join(tgt_shp_file_dir_path, item)
shutil.copyfile(src_file_full_path, tgt_file_full_path)
# upload the updated shape files to replace this aggregation
upload_shape_files(main_file_path=data_object.path)
# retrieve the updated aggregation
aggr = resource.aggregation(file__path=aggr_main_file_path)
# update aggregation metadata
for kw in keywords:
if kw not in aggr.metadata.subjects:
aggr.metadata.subjects.append(kw)
aggr.metadata.additional_metadata = additional_meta
aggr.save()
else:
# upload the updated shape files to create a new geo feature aggregation
upload_shape_files(main_file_path=file_path, dst_path=destination_path)
# retrieve the new aggregation
agg_path = urljoin(destination_path, os.path.basename(aggr_main_file_path))
aggr = resource.aggregation(file__path=agg_path)
aggr._data_object = None
return aggr
as_data_object(agg_path)
Loads the Geo Feature aggregation to a fiona Collection object :param agg_path: the path to the Geo Feature aggregation :return: the Geo Feature aggregation as a fiona Collection object
Source code in hsclient\hydroshare.py
def as_data_object(self, agg_path: str) -> 'fiona.Collection':
"""
Loads the Geo Feature aggregation to a fiona Collection object
:param agg_path: the path to the Geo Feature aggregation
:return: the Geo Feature aggregation as a fiona Collection object
"""
if fiona is None:
raise Exception("fiona package was not found")
return self._get_data_object(agg_path=agg_path, func=fiona.open)
save_data_object(resource, agg_path, as_new_aggr=False, destination_path='')
Saves the fiona Collection object to the Geo Feature aggregation :param resource: the resource containing the aggregation :param agg_path: the path to the Geo Feature aggregation :param as_new_aggr: Defaults False, set to True to create a new Geo Feature aggregation :param destination_path: the destination path in Hydroshare to save the new aggregation :return: the updated or new Geo Feature aggregation
Source code in hsclient\hydroshare.py
def save_data_object(self, resource: 'Resource', agg_path: str, as_new_aggr: bool = False,
destination_path: str = "") -> 'Aggregation':
"""
Saves the fiona Collection object to the Geo Feature aggregation
:param resource: the resource containing the aggregation
:param agg_path: the path to the Geo Feature aggregation
:param as_new_aggr: Defaults False, set to True to create a new Geo Feature aggregation
:param destination_path: the destination path in Hydroshare to save the new aggregation
:return: the updated or new Geo Feature aggregation
"""
def upload_shape_files(main_file_path, dst_path=""):
shp_file_dir_path = os.path.dirname(main_file_path)
filename_starts_with = f"{pathlib.Path(main_file_path).stem}."
shape_files = []
for item in os.listdir(shp_file_dir_path):
if item.startswith(filename_starts_with):
file_full_path = os.path.join(shp_file_dir_path, item)
shape_files.append(file_full_path)
if not dst_path:
self._update_aggregation(resource, *shape_files)
else:
resource.file_upload(*shape_files, destination_path=dst_path)
self._validate_aggregation_for_update(resource, AggregationType.GeographicFeatureAggregation)
file_path = self._validate_aggregation_path(agg_path, for_save_data=True)
aggr_main_file_path = self.main_file_path
data_object = self._data_object
# need to close the fiona.Collection object to free up access to all the original shape files
data_object.close()
if not as_new_aggr:
# cache some of the metadata fields of the original aggregation to update the metadata of the
# updated aggregation
keywords = self.metadata.subjects
additional_meta = self.metadata.additional_metadata
# copy the updated shape files to the original shape file location where the user downloaded the
# aggregation previously
src_shp_file_dir_path = os.path.dirname(file_path)
tgt_shp_file_dir_path = os.path.dirname(data_object.path)
filename_starts_with = f"{pathlib.Path(file_path).stem}."
for item in os.listdir(src_shp_file_dir_path):
if item.startswith(filename_starts_with):
src_file_full_path = os.path.join(src_shp_file_dir_path, item)
tgt_file_full_path = os.path.join(tgt_shp_file_dir_path, item)
shutil.copyfile(src_file_full_path, tgt_file_full_path)
# upload the updated shape files to replace this aggregation
upload_shape_files(main_file_path=data_object.path)
# retrieve the updated aggregation
aggr = resource.aggregation(file__path=aggr_main_file_path)
# update aggregation metadata
for kw in keywords:
if kw not in aggr.metadata.subjects:
aggr.metadata.subjects.append(kw)
aggr.metadata.additional_metadata = additional_meta
aggr.save()
else:
# upload the updated shape files to create a new geo feature aggregation
upload_shape_files(main_file_path=file_path, dst_path=destination_path)
# retrieve the new aggregation
agg_path = urljoin(destination_path, os.path.basename(aggr_main_file_path))
aggr = resource.aggregation(file__path=agg_path)
aggr._data_object = None
return aggr