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