From f17c6936a0c44147db6be7baaa0d280a2ccdeceb Mon Sep 17 00:00:00 2001 From: Tom Kralidis Date: Thu, 10 Mar 2022 16:23:49 -0500 Subject: [PATCH] OACov: change coverage range-subset to properties, update conformance classes (#870) * OACov: change coverage range-subset to properties, update conformance classes * fix conformance tests --- .../data-publishing/ogcapi-coverages.rst | 6 +++--- pygeoapi/api.py | 20 +++++++++++-------- pygeoapi/provider/rasterio_.py | 6 +++--- pygeoapi/provider/xarray_.py | 14 ++++++------- tests/test_api.py | 4 ++-- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/docs/source/data-publishing/ogcapi-coverages.rst b/docs/source/data-publishing/ogcapi-coverages.rst index 8e2a966..fbbe6dd 100644 --- a/docs/source/data-publishing/ogcapi-coverages.rst +++ b/docs/source/data-publishing/ogcapi-coverages.rst @@ -15,7 +15,7 @@ pygeoapi core feature providers are listed below, along with a matrix of support parameters. .. csv-table:: - :header: Provider, range-subset, subset, bbox, datetime + :header: Provider, properties, subset, bbox, datetime :align: left rasterio,✅,✅,✅, @@ -96,8 +96,8 @@ Data access examples * http://localhost:5000/collections/foo/coverage?f=json * coverage access via native format (as defined in ``provider.format.name``) * http://localhost:5000/collections/foo/coverage?f=GRIB -* coverage access with comma-separated range-subset - * http://localhost:5000/collections/foo/coverage?range-subset=1,3 +* coverage access with comma-separated properties + * http://localhost:5000/collections/foo/coverage?properties=1,3 * coverage access with subsetting * http://localhost:5000/collections/foo/coverage?subset=lat(10,20)&subset=long(10,20) diff --git a/pygeoapi/api.py b/pygeoapi/api.py index 8406764..1ba5246 100644 --- a/pygeoapi/api.py +++ b/pygeoapi/api.py @@ -105,10 +105,14 @@ CONFORMANCE = [ 'http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30', 'http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/html', 'http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson', - 'http://www.opengis.net/spec/ogcapi_coverages-1/1.0/conf/core', + 'http://www.opengis.net/spec/ogcapi-coverages-1/1.0/conf/core', 'http://www.opengis.net/spec/ogcapi-coverages-1/1.0/conf/oas30', 'http://www.opengis.net/spec/ogcapi-coverages-1/1.0/conf/html', 'http://www.opengis.net/spec/ogcapi-coverages-1/1.0/conf/geodata-coverage', + 'http://www.opengis.net/spec/ogcapi-coverages-1/1.0/conf/coverage-subset', + 'http://www.opengis.net/spec/ogcapi-coverages-1/1.0/conf/coverage-rangesubset', # noqa + 'http://www.opengis.net/spec/ogcapi-coverages-1/1.0/conf/coverage-bbox', + 'http://www.opengis.net/spec/ogcapi-coverages-1/1.0/conf/coverage-datetime', # noqa 'http://www.opengis.net/spec/ogcapi-tiles-1/1.0/conf/core', 'http://www.opengis.net/spec/ogcapi-records-1/1.0/conf/core', 'http://www.opengis.net/spec/ogcapi-records-1/1.0/conf/sorting', @@ -2028,14 +2032,14 @@ class API: # Format explicitly set using a query parameter query_args['format_'] = format_ = request.format - range_subset = request.params.get('range-subset') - if range_subset: - LOGGER.debug('Processing range-subset parameter') - query_args['range_subset'] = [rs for - rs in range_subset.split(',') if rs] - LOGGER.debug('Fields: {}'.format(query_args['range_subset'])) + properties = request.params.get('properties') + if properties: + LOGGER.debug('Processing properties parameter') + query_args['properties'] = [rs for + rs in properties.split(',') if rs] + LOGGER.debug('Fields: {}'.format(query_args['properties'])) - for a in query_args['range_subset']: + for a in query_args['properties']: if a not in p.fields: msg = 'Invalid field specified' return self.get_exception( diff --git a/pygeoapi/provider/rasterio_.py b/pygeoapi/provider/rasterio_.py index a903093..f12b7cd 100644 --- a/pygeoapi/provider/rasterio_.py +++ b/pygeoapi/provider/rasterio_.py @@ -162,11 +162,11 @@ class RasterioProvider(BaseProvider): return rangetype - def query(self, range_subset=[], subsets={}, bbox=[], datetime_=None, + def query(self, properties=[], subsets={}, bbox=[], datetime_=None, format_='json', **kwargs): """ Extract data from collection collection - :param range_subset: list of bands + :param properties: list of bands :param subsets: dict of subset names with lists of ranges :param bbox: bounding box [minx,miny,maxx,maxy] :param datetime_: temporal (datestamp or extent) @@ -175,7 +175,7 @@ class RasterioProvider(BaseProvider): :returns: coverage data as dict of CoverageJSON or native format """ - bands = range_subset + bands = properties LOGGER.debug('Bands: {}, subsets: {}'.format(bands, subsets)) args = { diff --git a/pygeoapi/provider/xarray_.py b/pygeoapi/provider/xarray_.py index 1f049f2..f27d4d2 100644 --- a/pygeoapi/provider/xarray_.py +++ b/pygeoapi/provider/xarray_.py @@ -183,12 +183,12 @@ class XarrayProvider(BaseProvider): return rangetype - def query(self, range_subset=[], subsets={}, bbox=[], datetime_=None, + def query(self, properties=[], subsets={}, bbox=[], datetime_=None, format_='json', **kwargs): """ Extract data from collection collection - :param range_subset: list of data variables to return (all if blank) + :param properties: list of data variables to return (all if blank) :param subsets: dict of subset names with lists of ranges :param bbox: bounding box [minx,miny,maxx,maxy] :param datetime_: temporal (datestamp or extent) @@ -197,17 +197,17 @@ class XarrayProvider(BaseProvider): :returns: coverage data as dict of CoverageJSON or native format """ - if not range_subset and not subsets and format_ != 'json': + if not properties and not subsets and format_ != 'json': LOGGER.debug('No parameters specified, returning native data') if format_ == 'zarr': return _get_zarr_data(self._data) else: return read_data(self.data) - if len(range_subset) < 1: - range_subset = self.fields + if len(properties) < 1: + properties = self.fields - data = self._data[[*range_subset]] + data = self._data[[*properties]] if any([self._coverage_properties['x_axis_label'] in subsets, self._coverage_properties['y_axis_label'] in subsets, @@ -290,7 +290,7 @@ class XarrayProvider(BaseProvider): LOGGER.debug('Serializing data in memory') if format_ == 'json': LOGGER.debug('Creating output in CoverageJSON') - return self.gen_covjson(out_meta, data, range_subset) + return self.gen_covjson(out_meta, data, properties) elif format_ == 'zarr': LOGGER.debug('Returning data in native zarr format') return _get_zarr_data(data) diff --git a/tests/test_api.py b/tests/test_api.py index 67a35a6..aac99b8 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -413,7 +413,7 @@ def test_conformance(config, api_): assert isinstance(root, dict) assert 'conformsTo' in root - assert len(root['conformsTo']) == 21 + assert len(root['conformsTo']) == 25 req = mock_request({'f': 'foo'}) rsp_headers, code, response = api_.conformance(req) @@ -990,7 +990,7 @@ def test_get_collection_coverage(config, api_): assert code == 400 - req = mock_request({'range-subset': '12'}) + req = mock_request({'properties': '12'}) rsp_headers, code, response = api_.get_collection_coverage( req, 'gdps-temperature')