move to f-strings for string interpolation (#1064)
* update from format() to f-strings * fix * fix * fix ref * update headers
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
"app_function": "pygeoapi.flask_app.APP",
|
||||
"profile_name": null,
|
||||
"project_name": "pygeoapi",
|
||||
"runtime": "python3.6",
|
||||
"runtime": "python3.8",
|
||||
"s3_bucket": "zappa-pwpqh2twb",
|
||||
"aws_region": "us-east-2",
|
||||
"environment_variables": {
|
||||
|
||||
+139
-191
@@ -86,7 +86,7 @@ LOGGER = logging.getLogger(__name__)
|
||||
#: Return headers for requests (e.g:X-Powered-By)
|
||||
HEADERS = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Powered-By': 'pygeoapi {}'.format(__version__)
|
||||
'X-Powered-By': f'pygeoapi {__version__}'
|
||||
}
|
||||
|
||||
CHARSET = ['utf-8']
|
||||
@@ -198,7 +198,7 @@ def gzip(func):
|
||||
content = compress(content.encode(charset))
|
||||
except TypeError as err:
|
||||
headers.pop('Content-Encoding')
|
||||
LOGGER.error('Error in compression: {}'.format(err))
|
||||
LOGGER.error(f'Error in compression: {err}')
|
||||
|
||||
return headers, status, content
|
||||
|
||||
@@ -648,7 +648,7 @@ class API:
|
||||
'output_dir': None
|
||||
}
|
||||
|
||||
LOGGER.debug('Loading process manager {}'.format(manager_def['name']))
|
||||
LOGGER.debug(f"Loading process manager {manager_def['name']}")
|
||||
self.manager = load_plugin('process_manager', manager_def)
|
||||
LOGGER.info('Process manager plugin loaded')
|
||||
|
||||
@@ -685,35 +685,34 @@ class API:
|
||||
'rel': request.get_linkrel(F_JSON),
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'title': 'This document as JSON',
|
||||
'href': '{}?f={}'.format(self.config['server']['url'], F_JSON)
|
||||
'href': f"{self.config['server']['url']}?f={F_JSON}"
|
||||
}, {
|
||||
'rel': request.get_linkrel(F_JSONLD),
|
||||
'type': FORMAT_TYPES[F_JSONLD],
|
||||
'title': 'This document as RDF (JSON-LD)',
|
||||
'href': '{}?f={}'.format(self.config['server']['url'], F_JSONLD)
|
||||
'href': f"{self.config['server']['url']}?f={F_JSONLD}"
|
||||
}, {
|
||||
'rel': request.get_linkrel(F_HTML),
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'title': 'This document as HTML',
|
||||
'href': '{}?f={}'.format(self.config['server']['url'], F_HTML),
|
||||
'href': f"{self.config['server']['url']}?f={F_HTML}",
|
||||
'hreflang': self.default_locale
|
||||
}, {
|
||||
'rel': 'service-desc',
|
||||
'type': 'application/vnd.oai.openapi+json;version=3.0',
|
||||
'title': 'The OpenAPI definition as JSON',
|
||||
'href': '{}/openapi'.format(self.config['server']['url'])
|
||||
'href': f"{self.config['server']['url']}/openapi"
|
||||
}, {
|
||||
'rel': 'service-doc',
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'title': 'The OpenAPI definition as HTML',
|
||||
'href': '{}/openapi?f={}'.format(self.config['server']['url'],
|
||||
F_HTML),
|
||||
'href': f"{self.config['server']['url']}/openapi?f={F_HTML}",
|
||||
'hreflang': self.default_locale
|
||||
}, {
|
||||
'rel': 'conformance',
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'title': 'Conformance',
|
||||
'href': '{}/conformance'.format(self.config['server']['url'])
|
||||
'href': f"{self.config['server']['url']}/conformance"
|
||||
}, {
|
||||
'rel': 'data',
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
@@ -723,12 +722,12 @@ class API:
|
||||
'rel': 'http://www.opengis.net/def/rel/ogc/1.0/processes',
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'title': 'Processes',
|
||||
'href': '{}/processes'.format(self.config['server']['url'])
|
||||
'href': f"{self.config['server']['url']}/processes"
|
||||
}, {
|
||||
'rel': 'http://www.opengis.net/def/rel/ogc/1.0/job-list',
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'title': 'Jobs',
|
||||
'href': '{}/jobs'.format(self.config['server']['url'])
|
||||
'href': f"{self.config['server']['url']}/jobs"
|
||||
}]
|
||||
|
||||
headers = request.get_response_headers()
|
||||
@@ -871,7 +870,7 @@ class API:
|
||||
LOGGER.debug('Creating collections')
|
||||
for k, v in collections_dict.items():
|
||||
if v.get('visibility', 'default') == 'hidden':
|
||||
LOGGER.debug('Skipping hidden layer: {}'.format(k))
|
||||
LOGGER.debug(f'Skipping hidden layer: {k}')
|
||||
continue
|
||||
collection_data = get_provider_default(v['providers'])
|
||||
collection_data_type = collection_data['type']
|
||||
@@ -932,34 +931,31 @@ class API:
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': 'root',
|
||||
'title': 'The landing page of this server as JSON',
|
||||
'href': '{}?f={}'.format(self.config['server']['url'], F_JSON)
|
||||
'href': f"{self.config['server']['url']}?f={F_JSON}"
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': 'root',
|
||||
'title': 'The landing page of this server as HTML',
|
||||
'href': '{}?f={}'.format(self.config['server']['url'], F_HTML)
|
||||
'href': f"{self.config['server']['url']}?f={F_HTML}"
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': request.get_linkrel(F_JSON),
|
||||
'title': 'This document as JSON',
|
||||
'href': '{}/{}?f={}'.format(
|
||||
self.get_collections_url(), k, F_JSON)
|
||||
'href': f'{self.get_collections_url()}/{k}?f={F_JSON}'
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_JSONLD],
|
||||
'rel': request.get_linkrel(F_JSONLD),
|
||||
'title': 'This document as RDF (JSON-LD)',
|
||||
'href': '{}/{}?f={}'.format(
|
||||
self.get_collections_url(), k, F_JSONLD)
|
||||
'href': f'{self.get_collections_url()}/{k}?f={F_JSONLD}'
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': request.get_linkrel(F_HTML),
|
||||
'title': 'This document as HTML',
|
||||
'href': '{}/{}?f={}'.format(
|
||||
self.get_collections_url(), k, F_HTML)
|
||||
'href': f'{self.get_collections_url()}/{k}?f={F_HTML}'
|
||||
})
|
||||
|
||||
if collection_data_type in ['feature', 'record', 'tile']:
|
||||
@@ -970,36 +966,31 @@ class API:
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': 'queryables',
|
||||
'title': 'Queryables for this collection as JSON',
|
||||
'href': '{}/{}/queryables?f={}'.format(
|
||||
self.get_collections_url(), k, F_JSON)
|
||||
'href': f'{self.get_collections_url()}/{k}/queryables?f={F_JSON}' # noqa
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': 'queryables',
|
||||
'title': 'Queryables for this collection as HTML',
|
||||
'href': '{}/{}queryables?f={}'.format(
|
||||
self.get_collections_url(), k, F_HTML)
|
||||
'href': f'{self.get_collections_url()}/{k}/queryables?f={F_HTML}' # noqa
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': 'application/geo+json',
|
||||
'rel': 'items',
|
||||
'title': 'items as GeoJSON',
|
||||
'href': '{}/{}/items?f={}'.format(
|
||||
self.get_collections_url(), k, F_JSON)
|
||||
'href': f'{self.get_collections_url()}/{k}/items?f={F_JSON}' # noqa
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_JSONLD],
|
||||
'rel': 'items',
|
||||
'title': 'items as RDF (GeoJSON-LD)',
|
||||
'href': '{}/{}/items?f={}'.format(
|
||||
self.get_collections_url(), k, F_JSONLD)
|
||||
'href': f'{self.get_collections_url()}/{k}/items?f={F_JSONLD}' # noqa
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': 'items',
|
||||
'title': 'Items as HTML',
|
||||
'href': '{}/{}/items?f={}'.format(
|
||||
self.get_collections_url(), k, F_HTML)
|
||||
'href': f'{self.get_collections_url()}/{k}/items?f={F_HTML}' # noqa
|
||||
})
|
||||
|
||||
elif collection_data_type == 'coverage':
|
||||
@@ -1009,59 +1000,52 @@ class API:
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': 'collection',
|
||||
'title': 'Detailed Coverage metadata in JSON',
|
||||
'href': '{}/{}?f={}'.format(
|
||||
self.get_collections_url(), k, F_JSON)
|
||||
'href': f'{self.get_collections_url()}/{k}?f={F_JSON}'
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': 'collection',
|
||||
'title': 'Detailed Coverage metadata in HTML',
|
||||
'href': '{}/{}?f={}'.format(
|
||||
self.get_collections_url(), k, F_HTML)
|
||||
'href': f'{self.get_collections_url()}/{k}?f={F_HTML}'
|
||||
})
|
||||
coverage_url = '{}/{}/coverage'.format(
|
||||
self.get_collections_url(), k)
|
||||
coverage_url = f'{self.get_collections_url()}/{k}/coverage'
|
||||
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': '{}/coverage-domainset'.format(OGC_RELTYPES_BASE),
|
||||
'rel': f'{OGC_RELTYPES_BASE}/coverage-domainset',
|
||||
'title': 'Coverage domain set of collection in JSON',
|
||||
'href': '{}/domainset?f={}'.format(coverage_url, F_JSON)
|
||||
'href': f'{coverage_url}/domainset?f={F_JSON}'
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': '{}/coverage-domainset'.format(OGC_RELTYPES_BASE),
|
||||
'rel': f'{OGC_RELTYPES_BASE}/coverage-domainset',
|
||||
'title': 'Coverage domain set of collection in HTML',
|
||||
'href': '{}/domainset?f={}'.format(coverage_url, F_HTML)
|
||||
'href': f'{coverage_url}/domainset?f={F_HTML}'
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': '{}/coverage-rangetype'.format(OGC_RELTYPES_BASE),
|
||||
'rel': f'{OGC_RELTYPES_BASE}/coverage-rangetype',
|
||||
'title': 'Coverage range type of collection in JSON',
|
||||
'href': '{}/rangetype?f={}'.format(coverage_url, F_JSON)
|
||||
'href': f'{coverage_url}/rangetype?f={F_JSON}'
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': '{}/coverage-rangetype'.format(OGC_RELTYPES_BASE),
|
||||
'rel': f'{OGC_RELTYPES_BASE}/coverage-rangetype',
|
||||
'title': 'Coverage range type of collection in HTML',
|
||||
'href': '{}/rangetype?f={}'.format(coverage_url, F_HTML)
|
||||
'href': f'{coverage_url}/rangetype?f={F_HTML}'
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': 'application/prs.coverage+json',
|
||||
'rel': '{}/coverage'.format(OGC_RELTYPES_BASE),
|
||||
'rel': f'{OGC_RELTYPES_BASE}/coverage',
|
||||
'title': 'Coverage data',
|
||||
'href': '{}/{}/coverage?f={}'.format(
|
||||
self.get_collections_url(), k, F_JSON)
|
||||
'href': f'{self.get_collections_url()}/{k}/coverage?f={F_JSON}' # noqa
|
||||
})
|
||||
if collection_data_format is not None:
|
||||
collection['links'].append({
|
||||
'type': collection_data_format['mimetype'],
|
||||
'rel': '{}/coverage'.format(OGC_RELTYPES_BASE),
|
||||
'title': 'Coverage data as {}'.format(
|
||||
collection_data_format['name']),
|
||||
'href': '{}/{}/coverage?f={}'.format(
|
||||
self.get_collections_url(), k,
|
||||
collection_data_format['name'])
|
||||
'rel': f'{OGC_RELTYPES_BASE}/coverage',
|
||||
'title': f"Coverage data as {collection_data_format['name']}", # noqa
|
||||
'href': f"{self.get_collections_url()}/{k}/coverage?f={collection_data_format['name']}" # noqa
|
||||
})
|
||||
if dataset is not None:
|
||||
LOGGER.debug('Creating extended coverage metadata')
|
||||
@@ -1093,15 +1077,13 @@ class API:
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': 'tiles',
|
||||
'title': 'Tiles as JSON',
|
||||
'href': '{}/{}/tiles?f={}'.format(
|
||||
self.get_collections_url(), k, F_JSON)
|
||||
'href': f'{self.get_collections_url()}/{k}/tiles?f={F_JSON}' # noqa
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': 'tiles',
|
||||
'title': 'Tiles as HTML',
|
||||
'href': '{}/{}/tiles?f={}'.format(
|
||||
self.get_collections_url(), k, F_HTML)
|
||||
'href': f'{self.get_collections_url()}/{k}/tiles?f={F_HTML}' # noqa
|
||||
})
|
||||
|
||||
try:
|
||||
@@ -1118,9 +1100,8 @@ class API:
|
||||
collection['links'].append({
|
||||
'type': map_mimetype,
|
||||
'rel': 'http://www.opengis.net/def/rel/ogc/1.0/map',
|
||||
'title': 'Map as {}'.format(map_format),
|
||||
'href': '{}/collections/{}/map?f={}'.format(
|
||||
self.config['server']['url'], k, map_format)
|
||||
'title': f'Map as {map_format}',
|
||||
'href': f"{self.config['server']['url']}/collections/{k}/map?f={map_format}" # noqa
|
||||
})
|
||||
|
||||
try:
|
||||
@@ -1144,16 +1125,14 @@ class API:
|
||||
collection['links'].append({
|
||||
'type': 'application/json',
|
||||
'rel': 'data',
|
||||
'title': '{} query for this collection as JSON'.format(qt), # noqa
|
||||
'href': '{}/{}/{}?f={}'.format(
|
||||
self.get_collections_url(), k, qt, F_JSON)
|
||||
'title': f'{qt} query for this collection as JSON',
|
||||
'href': f'{self.get_collections_url()}/{k}/{qt}?f={F_JSON}' # noqa
|
||||
})
|
||||
collection['links'].append({
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': 'data',
|
||||
'title': '{} query for this collection as HTML'.format(qt), # noqa
|
||||
'href': '{}/{}/{}?f={}'.format(
|
||||
self.get_collections_url(), k, qt, F_HTML)
|
||||
'title': f'{qt} query for this collection as HTML',
|
||||
'href': f'{self.get_collections_url()}/{k}/{qt}?f={F_HTML}' # noqa
|
||||
})
|
||||
except ProviderConnectionError:
|
||||
msg = 'connection error (check logs)'
|
||||
@@ -1174,19 +1153,19 @@ class API:
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': request.get_linkrel(F_JSON),
|
||||
'title': 'This document as JSON',
|
||||
'href': '{}?f={}'.format(self.get_collections_url(), F_JSON)
|
||||
'href': f'{self.get_collections_url()}?f={F_JSON}'
|
||||
})
|
||||
fcm['links'].append({
|
||||
'type': FORMAT_TYPES[F_JSONLD],
|
||||
'rel': request.get_linkrel(F_JSONLD),
|
||||
'title': 'This document as RDF (JSON-LD)',
|
||||
'href': '{}?f={}'.format(self.get_collections_url(), F_JSONLD)
|
||||
'href': f'{self.get_collections_url()}?f={F_JSONLD}'
|
||||
})
|
||||
fcm['links'].append({
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': request.get_linkrel(F_HTML),
|
||||
'title': 'This document as HTML',
|
||||
'href': '{}?f={}'.format(self.get_collections_url(), F_HTML)
|
||||
'href': f'{self.get_collections_url()}?f={F_HTML}'
|
||||
})
|
||||
|
||||
if request.format == F_HTML: # render
|
||||
@@ -1265,8 +1244,7 @@ class API:
|
||||
self.config['resources'][dataset]['title'], request.locale),
|
||||
'properties': {},
|
||||
'$schema': 'http://json-schema.org/draft/2019-09/schema',
|
||||
'$id': '{}/{}/queryables'.format(
|
||||
self.get_collections_url(), dataset)
|
||||
'$id': f'{self.get_collections_url()}/{dataset}/queryables'
|
||||
}
|
||||
|
||||
if p.fields:
|
||||
@@ -1431,7 +1409,7 @@ class API:
|
||||
LOGGER.debug('processing property parameters')
|
||||
for k, v in request.params.items():
|
||||
if k not in reserved_fieldnames and k in list(p.fields.keys()):
|
||||
LOGGER.debug('Adding property filter {}={}'.format(k, v))
|
||||
LOGGER.debug(f'Adding property filter {k}={v}')
|
||||
properties.append((k, v))
|
||||
|
||||
LOGGER.debug('processing sort parameter')
|
||||
@@ -1504,19 +1482,19 @@ class API:
|
||||
prv_locale = l10n.get_plugin_locale(provider_def, request.raw_locale)
|
||||
|
||||
LOGGER.debug('Querying provider')
|
||||
LOGGER.debug('offset: {}'.format(offset))
|
||||
LOGGER.debug('limit: {}'.format(limit))
|
||||
LOGGER.debug('resulttype: {}'.format(resulttype))
|
||||
LOGGER.debug('sortby: {}'.format(sortby))
|
||||
LOGGER.debug('bbox: {}'.format(bbox))
|
||||
LOGGER.debug('datetime: {}'.format(datetime_))
|
||||
LOGGER.debug('properties: {}'.format(properties))
|
||||
LOGGER.debug('select properties: {}'.format(select_properties))
|
||||
LOGGER.debug('skipGeometry: {}'.format(skip_geometry))
|
||||
LOGGER.debug('language: {}'.format(prv_locale))
|
||||
LOGGER.debug('q: {}'.format(q))
|
||||
LOGGER.debug('cql_text: {}'.format(cql_text))
|
||||
LOGGER.debug('filter-lang: {}'.format(filter_lang))
|
||||
LOGGER.debug(f'offset: {offset}')
|
||||
LOGGER.debug(f'limit: {limit}')
|
||||
LOGGER.debug(f'resulttype: {resulttype}')
|
||||
LOGGER.debug(f'sortby: {sortby}')
|
||||
LOGGER.debug(f'bbox: {bbox}')
|
||||
LOGGER.debug(f'datetime: {datetime_}')
|
||||
LOGGER.debug(f'properties: {properties}')
|
||||
LOGGER.debug(f'select properties: {select_properties}')
|
||||
LOGGER.debug(f'skipGeometry: {skip_geometry}')
|
||||
LOGGER.debug(f'language: {prv_locale}')
|
||||
LOGGER.debug(f'q: {q}')
|
||||
LOGGER.debug(f'cql_text: {cql_text}')
|
||||
LOGGER.debug(f'filter-lang: {filter_lang}')
|
||||
|
||||
try:
|
||||
content = p.query(offset=offset, limit=limit,
|
||||
@@ -1551,25 +1529,22 @@ class API:
|
||||
serialized_query_params += urllib.parse.quote(str(v), safe=',')
|
||||
|
||||
# TODO: translate titles
|
||||
uri = '{}/{}/items'.format(self.get_collections_url(), dataset)
|
||||
uri = f'{self.get_collections_url()}/{dataset}/items'
|
||||
content['links'] = [{
|
||||
'type': 'application/geo+json',
|
||||
'rel': request.get_linkrel(F_JSON),
|
||||
'title': 'This document as GeoJSON',
|
||||
'href': '{}?f={}{}'.format(
|
||||
uri, F_JSON, serialized_query_params)
|
||||
'href': f'{uri}?f={F_JSON}{serialized_query_params}'
|
||||
}, {
|
||||
'rel': request.get_linkrel(F_JSONLD),
|
||||
'type': FORMAT_TYPES[F_JSONLD],
|
||||
'title': 'This document as RDF (JSON-LD)',
|
||||
'href': '{}?f={}{}'.format(
|
||||
uri, F_JSONLD, serialized_query_params)
|
||||
'href': f'{uri}?f={F_JSONLD}{serialized_query_params}'
|
||||
}, {
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': request.get_linkrel(F_HTML),
|
||||
'title': 'This document as HTML',
|
||||
'href': '{}?f={}{}'.format(
|
||||
uri, F_HTML, serialized_query_params)
|
||||
'href': f'{uri}?f={F_HTML}{serialized_query_params}'
|
||||
}]
|
||||
|
||||
if offset > 0:
|
||||
@@ -1579,9 +1554,7 @@ class API:
|
||||
'type': 'application/geo+json',
|
||||
'rel': 'prev',
|
||||
'title': 'items (prev)',
|
||||
'href': '{}?offset={}{}'
|
||||
.format(
|
||||
uri, prev, serialized_query_params)
|
||||
'href': f'{uri}?offset={prev}{serialized_query_params}'
|
||||
})
|
||||
|
||||
if len(content['features']) == limit:
|
||||
@@ -1591,9 +1564,7 @@ class API:
|
||||
'type': 'application/geo+json',
|
||||
'rel': 'next',
|
||||
'title': 'items (next)',
|
||||
'href': '{}?offset={}{}'
|
||||
.format(
|
||||
uri, next_, serialized_query_params)
|
||||
'href': f'{uri}?offset={next_}{serialized_query_params}'
|
||||
})
|
||||
|
||||
content['links'].append(
|
||||
@@ -1653,15 +1624,14 @@ class API:
|
||||
return self.get_exception(
|
||||
500, headers, request.format, 'NoApplicableCode', msg)
|
||||
|
||||
headers['Content-Type'] = '{}; charset={}'.format(
|
||||
formatter.mimetype, self.config['server']['encoding'])
|
||||
headers['Content-Type'] = f"{formatter.mimetype}; charset={self.config['server']['encoding']}" # noqa
|
||||
|
||||
if p.filename is None:
|
||||
filename = '{}.csv'.format(dataset)
|
||||
filename = f'{dataset}.csv'
|
||||
else:
|
||||
filename = '{}'.format(p.filename)
|
||||
filename = f'{p.filename}'
|
||||
|
||||
cd = 'attachment; filename="{}"'.format(filename)
|
||||
cd = f'attachment; filename="{filename}"'
|
||||
headers['Content-Disposition'] = cd
|
||||
|
||||
return headers, 200, content
|
||||
@@ -1802,11 +1772,11 @@ class API:
|
||||
LOGGER.debug('processing property parameters')
|
||||
for k, v in request.params.items():
|
||||
if k not in reserved_fieldnames and k not in p.fields.keys():
|
||||
msg = 'unknown query parameter: {}'.format(k)
|
||||
msg = f'unknown query parameter: {k}'
|
||||
return self.get_exception(
|
||||
400, headers, request.format, 'InvalidParameterValue', msg)
|
||||
elif k not in reserved_fieldnames and k in p.fields.keys():
|
||||
LOGGER.debug('Add property filter {}={}'.format(k, v))
|
||||
LOGGER.debug(f'Add property filter {k}={v}')
|
||||
properties.append((k, v))
|
||||
|
||||
LOGGER.debug('processing sort parameter')
|
||||
@@ -1862,16 +1832,16 @@ class API:
|
||||
400, headers, request.format, 'InvalidParameterValue', msg)
|
||||
|
||||
LOGGER.debug('Querying provider')
|
||||
LOGGER.debug('offset: {}'.format(offset))
|
||||
LOGGER.debug('limit: {}'.format(limit))
|
||||
LOGGER.debug('resulttype: {}'.format(resulttype))
|
||||
LOGGER.debug('sortby: {}'.format(sortby))
|
||||
LOGGER.debug('bbox: {}'.format(bbox))
|
||||
LOGGER.debug('datetime: {}'.format(datetime_))
|
||||
LOGGER.debug('properties: {}'.format(select_properties))
|
||||
LOGGER.debug('skipGeometry: {}'.format(skip_geometry))
|
||||
LOGGER.debug('q: {}'.format(q))
|
||||
LOGGER.debug('filter-lang: {}'.format(filter_lang))
|
||||
LOGGER.debug(f'offset: {offset}')
|
||||
LOGGER.debug(f'limit: {limit}')
|
||||
LOGGER.debug(f'resulttype: {resulttype}')
|
||||
LOGGER.debug(f'sortby: {sortby}')
|
||||
LOGGER.debug(f'bbox: {bbox}')
|
||||
LOGGER.debug(f'datetime: {datetime_}')
|
||||
LOGGER.debug(f'properties: {select_properties}')
|
||||
LOGGER.debug(f'skipGeometry: {skip_geometry}')
|
||||
LOGGER.debug(f'q: {q}')
|
||||
LOGGER.debug(f'filter-lang: {filter_lang}')
|
||||
|
||||
LOGGER.debug('Processing headers')
|
||||
|
||||
@@ -2017,8 +1987,7 @@ class API:
|
||||
return self.get_exception(
|
||||
400, headers, request.format, 'InvalidParameterValue', msg)
|
||||
|
||||
headers['Location'] = '{}/{}/items/{}'.format(
|
||||
self.get_collections_url(), dataset, identifier)
|
||||
headers['Location'] = f'{self.get_collections_url()}/{dataset}/items/{identifier}' # noqa
|
||||
|
||||
return headers, 201, ''
|
||||
|
||||
@@ -2095,7 +2064,7 @@ class API:
|
||||
prv_locale = l10n.get_plugin_locale(provider_def, request.raw_locale)
|
||||
|
||||
try:
|
||||
LOGGER.debug('Fetching id {}'.format(identifier))
|
||||
LOGGER.debug(f'Fetching id {identifier}')
|
||||
content = p.get(identifier, language=prv_locale)
|
||||
except ProviderConnectionError as err:
|
||||
LOGGER.error(err)
|
||||
@@ -2123,8 +2092,7 @@ class API:
|
||||
'NotFound', msg)
|
||||
|
||||
uri = content['properties'].get(p.uri_field) if p.uri_field else \
|
||||
'{}/{}/items/{}'.format(
|
||||
self.get_collections_url(), dataset, identifier)
|
||||
f'{self.get_collections_url()}/{dataset}/items/{identifier}'
|
||||
|
||||
if 'links' not in content:
|
||||
content['links'] = []
|
||||
@@ -2133,51 +2101,46 @@ class API:
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': 'root',
|
||||
'title': 'The landing page of this server as JSON',
|
||||
'href': '{}?f={}'.format(self.config['server']['url'], F_JSON)
|
||||
'href': f"{self.config['server']['url']}?f={F_JSON}"
|
||||
}, {
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': 'root',
|
||||
'title': 'The landing page of this server as HTML',
|
||||
'href': '{}?f={}'.format(self.config['server']['url'], F_HTML)
|
||||
'href': f"{self.config['server']['url']}?f={F_HTML}"
|
||||
}, {
|
||||
'rel': request.get_linkrel(F_JSON),
|
||||
'type': 'application/geo+json',
|
||||
'title': 'This document as GeoJSON',
|
||||
'href': '{}?f={}'.format(uri, F_JSON)
|
||||
'href': f'{uri}?f={F_JSON}'
|
||||
}, {
|
||||
'rel': request.get_linkrel(F_JSONLD),
|
||||
'type': FORMAT_TYPES[F_JSONLD],
|
||||
'title': 'This document as RDF (JSON-LD)',
|
||||
'href': '{}?f={}'.format(uri, F_JSONLD)
|
||||
'href': f'{uri}?f={F_JSONLD}'
|
||||
}, {
|
||||
'rel': request.get_linkrel(F_HTML),
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'title': 'This document as HTML',
|
||||
'href': '{}?f={}'.format(uri, F_HTML)
|
||||
'href': f'{uri}?f={F_HTML}'
|
||||
}, {
|
||||
'rel': 'collection',
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'title': l10n.translate(collections[dataset]['title'],
|
||||
request.locale),
|
||||
'href': '{}/{}'.format(
|
||||
self.get_collections_url(), dataset)
|
||||
'href': f'{self.get_collections_url()}/{dataset}'
|
||||
}])
|
||||
|
||||
if 'prev' in content:
|
||||
content['links'].append({
|
||||
'rel': 'prev',
|
||||
'type': FORMAT_TYPES[request.format],
|
||||
'href': '{}/{}/items/{}?f={}'.format(
|
||||
self.get_collections_url(), dataset,
|
||||
content['prev'], request.format)
|
||||
'href': f"{self.get_collections_url()}/{dataset}/items/{content['prev']}?f={request.format}" # noqa
|
||||
})
|
||||
if 'next' in content:
|
||||
content['links'].append({
|
||||
'rel': 'next',
|
||||
'type': FORMAT_TYPES[request.format],
|
||||
'href': '{}/{}/items/{}?f={}'.format(
|
||||
self.get_collections_url(), dataset,
|
||||
content['next'], request.format)
|
||||
'href': f"{self.get_collections_url()}/{dataset}/items/{content['next']}?f={request.format}" # noqa
|
||||
})
|
||||
|
||||
# Set response language to requested provider locale
|
||||
@@ -2271,7 +2234,7 @@ class API:
|
||||
|
||||
LOGGER.debug('Processing datetime parameter')
|
||||
|
||||
datetime_ = request.params.get('datetime', None)
|
||||
datetime_ = request.params.get('datetime')
|
||||
|
||||
try:
|
||||
datetime_ = validate_datetime(
|
||||
@@ -2292,7 +2255,7 @@ class API:
|
||||
LOGGER.debug('Processing properties parameter')
|
||||
query_args['properties'] = [rs for
|
||||
rs in properties.split(',') if rs]
|
||||
LOGGER.debug('Fields: {}'.format(query_args['properties']))
|
||||
LOGGER.debug(f"Fields: {query_args['properties']}")
|
||||
|
||||
for a in query_args['properties']:
|
||||
if a not in p.fields:
|
||||
@@ -2305,7 +2268,7 @@ class API:
|
||||
try:
|
||||
subsets = validate_subset(request.params['subset'] or '')
|
||||
except (AttributeError, ValueError) as err:
|
||||
msg = 'Invalid subset: {}'.format(err)
|
||||
msg = f'Invalid subset: {err}'
|
||||
LOGGER.error(msg)
|
||||
return self.get_exception(
|
||||
400, headers, format_, 'InvalidParameterValue', msg)
|
||||
@@ -2317,13 +2280,13 @@ class API:
|
||||
400, headers, format_, 'InvalidParameterValue', msg)
|
||||
|
||||
query_args['subsets'] = subsets
|
||||
LOGGER.debug('Subsets: {}'.format(query_args['subsets']))
|
||||
LOGGER.debug(f"Subsets: {query_args['subsets']}")
|
||||
|
||||
LOGGER.debug('Querying coverage')
|
||||
try:
|
||||
data = p.query(**query_args)
|
||||
except ProviderInvalidQueryError as err:
|
||||
msg = 'query error: {}'.format(err)
|
||||
msg = f'query error: {err}'
|
||||
return self.get_exception(
|
||||
400, headers, format_, 'InvalidParameterValue', msg)
|
||||
except ProviderNoDataError:
|
||||
@@ -2338,7 +2301,7 @@ class API:
|
||||
mt = collection_def['format']['name']
|
||||
if format_ == mt: # native format
|
||||
if p.filename is not None:
|
||||
cd = 'attachment; filename="{}"'.format(p.filename)
|
||||
cd = f'attachment; filename="{p.filename}"'
|
||||
headers['Content-Disposition'] = cd
|
||||
|
||||
headers['Content-Type'] = collection_def['format']['mimetype']
|
||||
@@ -2511,29 +2474,25 @@ class API:
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': request.get_linkrel(F_JSON),
|
||||
'title': 'This document as JSON',
|
||||
'href': '{}/{}/tiles?f={}'.format(
|
||||
self.get_collections_url(), dataset, F_JSON)
|
||||
'href': f'{self.get_collections_url()}/{dataset}/tiles?f={F_JSON}'
|
||||
})
|
||||
tiles['links'].append({
|
||||
'type': FORMAT_TYPES[F_JSONLD],
|
||||
'rel': request.get_linkrel(F_JSONLD),
|
||||
'title': 'This document as RDF (JSON-LD)',
|
||||
'href': '{}/{}/tiles?f={}'.format(
|
||||
self.get_collections_url(), dataset, F_JSONLD)
|
||||
'href': f'{self.get_collections_url()}/{dataset}/tiles?f={F_JSONLD}' # noqa
|
||||
})
|
||||
tiles['links'].append({
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': request.get_linkrel(F_HTML),
|
||||
'title': 'This document as HTML',
|
||||
'href': '{}/{}/tiles?f={}'.format(
|
||||
self.get_collections_url(), dataset, F_HTML)
|
||||
'href': f'{self.get_collections_url()}/{dataset}/tiles?f={F_HTML}'
|
||||
})
|
||||
|
||||
tile_services = p.get_tiles_service(
|
||||
baseurl=self.config['server']['url'],
|
||||
servicepath='{}/{}/tiles/{{{}}}/{{{}}}/{{{}}}/{{{}}}?f=mvt'
|
||||
.format(self.get_collections_url(), dataset, 'tileMatrixSetId',
|
||||
'tileMatrix', 'tileRow', 'tileCol'))
|
||||
servicepath='{self.get_collections_url()}/{dataset}/tiles/{{tileMatrixSetId}}/{{tileMatrix}}/{{tileRow}}/{{tileCol}}?f=mvt' # noqa
|
||||
)
|
||||
|
||||
for service in tile_services['links']:
|
||||
tiles['links'].append(service)
|
||||
@@ -2551,20 +2510,14 @@ class API:
|
||||
tile_matrix['links'].append({
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': request.get_linkrel(F_JSON),
|
||||
'title': '{} - {} - {}'.format(
|
||||
dataset, matrix.tileMatrixSet, F_JSON),
|
||||
'href': '{}/{}/tiles/{}?f={}'.format(
|
||||
self.get_collections_url(), dataset,
|
||||
matrix.tileMatrixSet, F_JSON)
|
||||
'title': f'{dataset} - {matrix.tileMatrixSet} - {F_JSON}',
|
||||
'href': f'{self.get_collections_url()}/{dataset}/tiles/{matrix.tileMatrixSet}?f={F_JSON}' # noqa
|
||||
})
|
||||
tile_matrix['links'].append({
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': request.get_linkrel(F_HTML),
|
||||
'title': '{} - {} - {}'.format(
|
||||
dataset, matrix.tileMatrixSet, F_HTML),
|
||||
'href': '{}/{}/tiles/{}?f={}'.format(
|
||||
self.get_collections_url(), dataset,
|
||||
matrix.tileMatrixSet, F_HTML)
|
||||
'title': f'{dataset} - {matrix.tileMatrixSet} - {F_HTML}',
|
||||
'href': f'{self.get_collections_url()}/{dataset}/tiles/{matrix.tileMatrixSet}?f={F_HTML}' # noqa
|
||||
})
|
||||
tiles['tilesets'].append(tile_matrix)
|
||||
|
||||
@@ -2635,8 +2588,7 @@ class API:
|
||||
format_ = p.format_type
|
||||
headers['Content-Type'] = format_
|
||||
|
||||
LOGGER.debug('Fetching tileset id {} and tile {}/{}/{}'.format(
|
||||
matrix_id, z_idx, y_idx, x_idx))
|
||||
LOGGER.debug(f'Fetching tileset id {matrix_id} and tile {z_idx}/{y_idx}/{x_idx}') # noqa
|
||||
content = p.get_tiles(layer=p.get_layer(), tileset=matrix_id,
|
||||
z=z_idx, y=y_idx, x=x_idx, format_=format_)
|
||||
if content is None:
|
||||
@@ -2886,7 +2838,7 @@ class API:
|
||||
except ProviderInvalidQueryError as err:
|
||||
exception = {
|
||||
'code': 'NoApplicableCode',
|
||||
'description': 'query error: {}'.format(err),
|
||||
'description': f'query error: {err}'
|
||||
}
|
||||
LOGGER.error(exception)
|
||||
headers['Content-type'] = 'application/json'
|
||||
@@ -2977,7 +2929,7 @@ class API:
|
||||
except ProviderInvalidQueryError as err:
|
||||
exception = {
|
||||
'code': 'NoApplicableCode',
|
||||
'description': 'query error: {}'.format(err),
|
||||
'description': f'query error: {err}'
|
||||
}
|
||||
LOGGER.error(exception)
|
||||
return headers, 400, to_json(exception, self.pretty_print)
|
||||
@@ -3064,15 +3016,14 @@ class API:
|
||||
p2['outputTransmission'] = ['value']
|
||||
p2['links'] = p2.get('links', [])
|
||||
|
||||
jobs_url = '{}/jobs'.format(self.config['server']['url'])
|
||||
process_url = '{}/processes/{}'.format(
|
||||
self.config['server']['url'], key)
|
||||
jobs_url = f"{self.config['server']['url']}/jobs"
|
||||
process_url = f"{self.config['server']['url']}/processes/{key}"
|
||||
|
||||
# TODO translation support
|
||||
link = {
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': request.get_linkrel(F_JSON),
|
||||
'href': '{}?f={}'.format(process_url, F_JSON),
|
||||
'href': f'{process_url}?f={F_JSON}',
|
||||
'title': 'Process description as JSON',
|
||||
'hreflang': self.default_locale
|
||||
}
|
||||
@@ -3081,7 +3032,7 @@ class API:
|
||||
link = {
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': request.get_linkrel(F_HTML),
|
||||
'href': '{}?f={}'.format(process_url, F_HTML),
|
||||
'href': f'{process_url}?f={F_HTML}',
|
||||
'title': 'Process description as HTML',
|
||||
'hreflang': self.default_locale
|
||||
}
|
||||
@@ -3090,7 +3041,7 @@ class API:
|
||||
link = {
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'rel': 'http://www.opengis.net/def/rel/ogc/1.0/job-list',
|
||||
'href': '{}?f={}'.format(jobs_url, F_HTML),
|
||||
'href': f'{jobs_url}?f={F_HTML}',
|
||||
'title': 'jobs for this process as HTML',
|
||||
'hreflang': self.default_locale
|
||||
}
|
||||
@@ -3099,7 +3050,7 @@ class API:
|
||||
link = {
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': 'http://www.opengis.net/def/rel/ogc/1.0/job-list',
|
||||
'href': '{}?f={}'.format(jobs_url, F_JSON),
|
||||
'href': f'{jobs_url}?f={F_JSON}',
|
||||
'title': 'jobs for this process as JSON',
|
||||
'hreflang': self.default_locale
|
||||
}
|
||||
@@ -3108,7 +3059,7 @@ class API:
|
||||
link = {
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'rel': 'http://www.opengis.net/def/rel/ogc/1.0/execute',
|
||||
'href': '{}/execution?f={}'.format(process_url, F_JSON),
|
||||
'href': f'{process_url}/execution?f={F_JSON}',
|
||||
'title': 'Execution for this process as JSON',
|
||||
'hreflang': self.default_locale
|
||||
}
|
||||
@@ -3168,12 +3119,12 @@ class API:
|
||||
serialized_jobs = {
|
||||
'jobs': [],
|
||||
'links': [{
|
||||
'href': '{}/jobs?f={}'.format(self.config['server']['url'], F_HTML), # noqa
|
||||
'href': f"{self.config['server']['url']}/jobs?f={F_HTML}",
|
||||
'rel': request.get_linkrel(F_HTML),
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'title': 'Jobs list as HTML'
|
||||
}, {
|
||||
'href': '{}/jobs?f={}'.format(self.config['server']['url'], F_JSON), # noqa
|
||||
'href': f"{self.config['server']['url']}/jobs?f={F_JSON}",
|
||||
'rel': request.get_linkrel(F_JSON),
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'title': 'Jobs list as JSON'
|
||||
@@ -3195,19 +3146,18 @@ class API:
|
||||
if JobStatus[job_['status']] in (
|
||||
JobStatus.successful, JobStatus.running, JobStatus.accepted):
|
||||
|
||||
job_result_url = '{}/jobs/{}/results'.format(
|
||||
self.config['server']['url'], job_['identifier'])
|
||||
job_result_url = f"{ self.config['server']['url']}/jobs/{job_['identifier']}/results" # noqa
|
||||
|
||||
job2['links'] = [{
|
||||
'href': '{}?f={}'.format(job_result_url, F_HTML),
|
||||
'href': f'{job_result_url}?f={F_HTML}',
|
||||
'rel': 'about',
|
||||
'type': FORMAT_TYPES[F_HTML],
|
||||
'title': 'results of job {} as HTML'.format(job_id)
|
||||
'title': f'results of job {job_id} as HTML'
|
||||
}, {
|
||||
'href': '{}?f={}'.format(job_result_url, F_JSON),
|
||||
'href': f'{job_result_url}?f={F_JSON}',
|
||||
'rel': 'about',
|
||||
'type': FORMAT_TYPES[F_JSON],
|
||||
'title': 'results of job {} as JSON'.format(job_id)
|
||||
'title': f'results of job {job_id} as JSON'
|
||||
}]
|
||||
|
||||
if job_['mimetype'] not in (FORMAT_TYPES[F_JSON],
|
||||
@@ -3216,8 +3166,7 @@ class API:
|
||||
'href': job_result_url,
|
||||
'rel': 'about',
|
||||
'type': job_['mimetype'],
|
||||
'title': 'results of job {} as {}'.format(
|
||||
job_id, job_['mimetype'])
|
||||
'title': f"results of job {job_id} as {job_['mimetype']}" # noqa
|
||||
})
|
||||
|
||||
serialized_jobs['jobs'].append(job2)
|
||||
@@ -3302,8 +3251,7 @@ class API:
|
||||
LOGGER.debug(data_dict)
|
||||
|
||||
job_id = data.get("job_id", str(uuid.uuid1()))
|
||||
url = '{}/jobs/{}'.format(
|
||||
self.config['server']['url'], job_id)
|
||||
url = f"{self.config['server']['url']}/jobs/{job_id}"
|
||||
|
||||
headers['Location'] = url
|
||||
|
||||
@@ -3430,7 +3378,7 @@ class API:
|
||||
}
|
||||
else:
|
||||
http_status = 200
|
||||
jobs_url = '{}/jobs'.format(self.config['server']['url'])
|
||||
jobs_url = f"{self.config['server']['url']}/jobs"
|
||||
|
||||
response = {
|
||||
'jobID': job_id,
|
||||
@@ -3495,7 +3443,7 @@ class API:
|
||||
parameternames = parameternames.split(',')
|
||||
|
||||
LOGGER.debug('Processing coords parameter')
|
||||
wkt = request.params.get('coords', None)
|
||||
wkt = request.params.get('coords')
|
||||
|
||||
if not wkt:
|
||||
msg = 'missing coords parameter'
|
||||
@@ -3615,12 +3563,12 @@ class API:
|
||||
for key, value in stac_collections.items():
|
||||
content['links'].append({
|
||||
'rel': 'child',
|
||||
'href': '{}/{}?f={}'.format(stac_url, key, F_JSON),
|
||||
'href': f'{stac_url}/{key}?f={F_JSON}',
|
||||
'type': FORMAT_TYPES[F_JSON]
|
||||
})
|
||||
content['links'].append({
|
||||
'rel': 'child',
|
||||
'href': '{}/{}'.format(stac_url, key),
|
||||
'href': f'{stac_url}/{key}',
|
||||
'type': FORMAT_TYPES[F_HTML]
|
||||
})
|
||||
|
||||
@@ -3649,7 +3597,7 @@ class API:
|
||||
headers = request.get_response_headers()
|
||||
|
||||
dataset = None
|
||||
LOGGER.debug('Path: {}'.format(path))
|
||||
LOGGER.debug(f'Path: {path}')
|
||||
dir_tokens = path.split('/')
|
||||
if dir_tokens:
|
||||
dataset = dir_tokens[0]
|
||||
@@ -3672,7 +3620,7 @@ class API:
|
||||
return self.get_exception(
|
||||
500, headers, request.format, 'NoApplicableCode', msg)
|
||||
|
||||
id_ = '{}-stac'.format(dataset)
|
||||
id_ = f'{dataset}-stac'
|
||||
stac_version = '1.0.0-rc.2'
|
||||
|
||||
content = {
|
||||
@@ -3768,7 +3716,7 @@ class API:
|
||||
400, headers, request.format, 'InvalidParameterValue', msg)
|
||||
|
||||
def get_collections_url(self):
|
||||
return '{}/collections'.format(self.config['server']['url'])
|
||||
return f"{self.config['server']['url']}/collections"
|
||||
|
||||
|
||||
def validate_bbox(value=None) -> list:
|
||||
@@ -3909,7 +3857,7 @@ def validate_subset(value: str) -> dict:
|
||||
subsets = {}
|
||||
|
||||
for s in value.split(','):
|
||||
LOGGER.debug('Processing subset {}'.format(s))
|
||||
LOGGER.debug(f'Processing subset {s}')
|
||||
m = re.search(r'(.*)\((.*)\)', s)
|
||||
subset_name, values = m.group(1, 2)
|
||||
|
||||
|
||||
+8
-8
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -31,15 +31,16 @@ import click
|
||||
import json
|
||||
from jsonschema import validate as jsonschema_validate
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from pygeoapi.util import to_json, yaml_load
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
THISDIR = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
THISDIR = Path(__file__).parent.resolve()
|
||||
|
||||
|
||||
def validate_config(instance_dict):
|
||||
def validate_config(instance_dict: dict) -> bool:
|
||||
"""
|
||||
Validate pygeoapi configuration against pygeoapi schema
|
||||
|
||||
@@ -48,10 +49,9 @@ def validate_config(instance_dict):
|
||||
:returns: `bool` of validation
|
||||
"""
|
||||
|
||||
schema_file = os.path.join(THISDIR, 'schemas', 'config',
|
||||
'pygeoapi-config-0.x.yml')
|
||||
schema_file = THISDIR / 'schemas' / 'config' / 'pygeoapi-config-0.x.yml'
|
||||
|
||||
with open(schema_file) as fh2:
|
||||
with schema_file.open() as fh2:
|
||||
schema_dict = yaml_load(fh2)
|
||||
jsonschema_validate(json.loads(to_json(instance_dict)), schema_dict)
|
||||
|
||||
@@ -74,7 +74,7 @@ def validate(ctx, config_file):
|
||||
raise click.ClickException('--config/-c required')
|
||||
|
||||
with open(config_file) as ff:
|
||||
click.echo('Validating {}'.format(config_file))
|
||||
click.echo(f'Validating {config_file}')
|
||||
instance = yaml_load(ff)
|
||||
validate_config(instance)
|
||||
click.echo('Valid configuration')
|
||||
|
||||
@@ -67,7 +67,7 @@ APP.config['JSONIFY_PRETTYPRINT_REGULAR'] = CONFIG['server'].get(
|
||||
|
||||
api_ = API(CONFIG)
|
||||
|
||||
OGC_SCHEMAS_LOCATION = CONFIG['server'].get('ogc_schemas_location', None)
|
||||
OGC_SCHEMAS_LOCATION = CONFIG['server'].get('ogc_schemas_location')
|
||||
|
||||
if (OGC_SCHEMAS_LOCATION is not None and
|
||||
not OGC_SCHEMAS_LOCATION.startswith('http')):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2019 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -35,7 +35,7 @@ LOGGER = logging.getLogger(__name__)
|
||||
class BaseFormatter:
|
||||
"""generic Formatter ABC"""
|
||||
|
||||
def __init__(self, formatter_def):
|
||||
def __init__(self, formatter_def: dict):
|
||||
"""
|
||||
Initialize object
|
||||
|
||||
@@ -51,7 +51,7 @@ class BaseFormatter:
|
||||
if 'geom' in formatter_def:
|
||||
self.geom = formatter_def['geom']
|
||||
|
||||
def write(self, options={}, data=None):
|
||||
def write(self, options: dict = {}, data: dict = None) -> str:
|
||||
"""
|
||||
Generate data in specified format
|
||||
|
||||
@@ -64,7 +64,7 @@ class BaseFormatter:
|
||||
raise NotImplementedError()
|
||||
|
||||
def __repr__(self):
|
||||
return '<BaseFormatter> {}'.format(self.name)
|
||||
return f'<BaseFormatter> {self.name}'
|
||||
|
||||
|
||||
class FormatterGenericError(Exception):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2018 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -40,7 +40,7 @@ LOGGER = logging.getLogger(__name__)
|
||||
class CSVFormatter(BaseFormatter):
|
||||
"""CSV formatter"""
|
||||
|
||||
def __init__(self, formatter_def):
|
||||
def __init__(self, formatter_def: dict):
|
||||
"""
|
||||
Initialize object
|
||||
|
||||
@@ -56,7 +56,7 @@ class CSVFormatter(BaseFormatter):
|
||||
super().__init__({'name': 'csv', 'geom': geom})
|
||||
self.mimetype = 'text/csv'
|
||||
|
||||
def write(self, options={}, data=None):
|
||||
def write(self, options: dict = {}, data: dict = None) -> str:
|
||||
"""
|
||||
Generate data in CSV format
|
||||
|
||||
@@ -83,7 +83,7 @@ class CSVFormatter(BaseFormatter):
|
||||
# TODO: implement wkt geometry serialization
|
||||
LOGGER.debug('not a point geometry, skipping')
|
||||
|
||||
LOGGER.debug('CSV fields: {}'.format(fields))
|
||||
LOGGER.debug(f'CSV fields: {fields}')
|
||||
|
||||
try:
|
||||
output = io.BytesIO()
|
||||
@@ -104,4 +104,4 @@ class CSVFormatter(BaseFormatter):
|
||||
return output.getvalue()
|
||||
|
||||
def __repr__(self):
|
||||
return '<CSVFormatter> {}'.format(self.mimetype)
|
||||
return f'<CSVFormatter> {self.name}'
|
||||
|
||||
+74
-76
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2019 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -26,11 +26,13 @@
|
||||
# OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# =================================================================
|
||||
|
||||
""" Linked data capabilities
|
||||
Returns content as linked data representations
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import Callable
|
||||
|
||||
from pygeoapi.util import is_url
|
||||
from pygeoapi import l10n
|
||||
@@ -40,23 +42,23 @@ from shapely.ops import unary_union
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def jsonldify(func):
|
||||
def jsonldify(func: Callable) -> Callable:
|
||||
"""
|
||||
Decorator that transforms app configuration\
|
||||
to include a JSON-LD representation
|
||||
Decorator that transforms app configuration\
|
||||
to include a JSON-LD representation
|
||||
|
||||
:param func: decorated function
|
||||
:param func: decorated function
|
||||
|
||||
:returns: `func`
|
||||
:returns: `func`
|
||||
"""
|
||||
|
||||
def inner(*args, **kwargs):
|
||||
apireq = args[1]
|
||||
format_ = getattr(apireq, 'format', None)
|
||||
format_ = getattr(apireq, 'format')
|
||||
if not format_ == 'jsonld':
|
||||
return func(*args, **kwargs)
|
||||
# Function args have been pre-processed, so get locale from APIRequest
|
||||
locale_ = getattr(apireq, 'locale', None)
|
||||
locale_ = getattr(apireq, 'locale')
|
||||
LOGGER.debug('Creating JSON-LD representation')
|
||||
cls = args[0]
|
||||
cfg = cls.config
|
||||
@@ -67,43 +69,43 @@ def jsonldify(func):
|
||||
fcmld = {
|
||||
"@context": "https://schema.org/docs/jsonldcontext.jsonld",
|
||||
"@type": "DataCatalog",
|
||||
"@id": cfg.get('server', {}).get('url', None),
|
||||
"url": cfg.get('server', {}).get('url', None),
|
||||
"name": l10n.translate(ident.get('title', None), locale_),
|
||||
"@id": cfg.get('server', {}).get('url'),
|
||||
"url": cfg.get('server', {}).get('url'),
|
||||
"name": l10n.translate(ident.get('title'), locale_),
|
||||
"description": l10n.translate(
|
||||
ident.get('description', None), locale_),
|
||||
ident.get('description'), locale_),
|
||||
"keywords": l10n.translate(
|
||||
ident.get('keywords', None), locale_),
|
||||
ident.get('keywords'), locale_),
|
||||
"termsOfService": l10n.translate(
|
||||
ident.get('terms_of_service', None), locale_),
|
||||
"license": meta.get('license', {}).get('url', None),
|
||||
ident.get('terms_of_service'), locale_),
|
||||
"license": meta.get('license', {}).get('url'),
|
||||
"provider": {
|
||||
"@type": "Organization",
|
||||
"name": l10n.translate(provider.get('name', None), locale_),
|
||||
"url": provider.get('url', None),
|
||||
"name": l10n.translate(provider.get('name'), locale_),
|
||||
"url": provider.get('url'),
|
||||
"address": {
|
||||
"@type": "PostalAddress",
|
||||
"streetAddress": contact.get('address', None),
|
||||
"postalCode": contact.get('postalcode', None),
|
||||
"addressLocality": contact.get('city', None),
|
||||
"addressRegion": contact.get('stateorprovince', None),
|
||||
"addressCountry": contact.get('country', None)
|
||||
"streetAddress": contact.get('address'),
|
||||
"postalCode": contact.get('postalcode'),
|
||||
"addressLocality": contact.get('city'),
|
||||
"addressRegion": contact.get('stateorprovince'),
|
||||
"addressCountry": contact.get('country')
|
||||
},
|
||||
"contactPoint": {
|
||||
"@type": "Contactpoint",
|
||||
"email": contact.get('email', None),
|
||||
"telephone": contact.get('phone', None),
|
||||
"faxNumber": contact.get('fax', None),
|
||||
"url": contact.get('url', None),
|
||||
"email": contact.get('email'),
|
||||
"telephone": contact.get('phone'),
|
||||
"faxNumber": contact.get('fax'),
|
||||
"url": contact.get('url'),
|
||||
"hoursAvailable": {
|
||||
"opens": contact.get('hours', None),
|
||||
"opens": contact.get('hours'),
|
||||
"description": l10n.translate(
|
||||
contact.get('instructions', None), locale_)
|
||||
contact.get('instructions'), locale_)
|
||||
},
|
||||
"contactType": l10n.translate(
|
||||
contact.get('role', None), locale_),
|
||||
contact.get('role'), locale_),
|
||||
"description": l10n.translate(
|
||||
contact.get('position', None), locale_)
|
||||
contact.get('position'), locale_)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,46 +114,43 @@ def jsonldify(func):
|
||||
return inner
|
||||
|
||||
|
||||
def jsonldify_collection(cls, collection, locale_):
|
||||
def jsonldify_collection(cls, collection: dict, locale_: str) -> dict:
|
||||
"""
|
||||
Transforms collection into a JSON-LD representation
|
||||
Transforms collection into a JSON-LD representation
|
||||
|
||||
:param cls: API object
|
||||
:param collection: `collection` as prepared for non-LD JSON
|
||||
representation
|
||||
:param locale_: The locale to use for translations (if supported)
|
||||
:param cls: API object
|
||||
:param collection: `collection` as prepared for non-LD JSON
|
||||
representation
|
||||
:param locale_: The locale to use for translations (if supported)
|
||||
|
||||
:returns: `collection` a dictionary, mapped into JSON-LD, of
|
||||
type schema:Dataset
|
||||
:returns: `collection` a dictionary, mapped into JSON-LD, of
|
||||
type schema:Dataset
|
||||
"""
|
||||
temporal_extent = collection.get('extent', {}).get('temporal', {})
|
||||
interval = temporal_extent.get('interval', [[None, None]])
|
||||
interval = temporal_extent.get('interval')
|
||||
if interval is not None:
|
||||
interval = f'{interval[0][0]}/{interval[0][1]}'
|
||||
|
||||
spatial_extent = collection.get('extent', {}).get('spatial', {})
|
||||
bbox = spatial_extent.get('bbox', None)
|
||||
crs = spatial_extent.get('crs', None)
|
||||
bbox = spatial_extent.get('bbox')
|
||||
crs = spatial_extent.get('crs')
|
||||
hascrs84 = crs.endswith('CRS84')
|
||||
|
||||
dataset = {
|
||||
"@type": "Dataset",
|
||||
"@id": "{}/collections/{}".format(
|
||||
cls.config['server']['url'],
|
||||
collection['id']
|
||||
),
|
||||
"@id": f"{cls.config['server']['url']}/collections/{collection['id']}",
|
||||
"name": l10n.translate(collection['title'], locale_),
|
||||
"description": l10n.translate(collection['description'], locale_),
|
||||
"license": cls.fcmld['license'],
|
||||
"keywords": l10n.translate(collection.get('keywords', None), locale_),
|
||||
"keywords": l10n.translate(collection.get('keywords'), locale_),
|
||||
"spatial": None if (not hascrs84 or not bbox) else [{
|
||||
"@type": "Place",
|
||||
"geo": {
|
||||
"@type": "GeoShape",
|
||||
"box": '{},{} {},{}'.format(*_bbox[0:2], *_bbox[2:4])
|
||||
"box": f'{_bbox[0]},{_bbox[1]} {_bbox[2]},{_bbox[3]}'
|
||||
}
|
||||
} for _bbox in bbox],
|
||||
"temporalCoverage": None if not interval else "{}/{}".format(
|
||||
*interval[0]
|
||||
)
|
||||
"temporalCoverage": interval
|
||||
}
|
||||
dataset['url'] = dataset['@id']
|
||||
|
||||
@@ -173,20 +172,22 @@ def jsonldify_collection(cls, collection, locale_):
|
||||
return dataset
|
||||
|
||||
|
||||
def geojson2jsonld(config, data, dataset, identifier=None, id_field='id'):
|
||||
def geojson2jsonld(config: dict, data: dict, dataset: str,
|
||||
identifier: str = None, id_field: str = 'id') -> str:
|
||||
"""
|
||||
Render GeoJSON-LD from a GeoJSON base. Inserts a @context that can be
|
||||
read from, and extended by, the pygeoapi configuration for a particular
|
||||
dataset.
|
||||
Render GeoJSON-LD from a GeoJSON base. Inserts a @context that can be
|
||||
read from, and extended by, the pygeoapi configuration for a particular
|
||||
dataset.
|
||||
|
||||
:param config: dict of configuration
|
||||
:param data: dict of data:
|
||||
:param dataset: dataset identifier
|
||||
:param identifier: item identifier (optional)
|
||||
:param id_field: item identifier_field (optional)
|
||||
:param config: dict of configuration
|
||||
:param data: dict of data:
|
||||
:param dataset: dataset identifier
|
||||
:param identifier: item identifier (optional)
|
||||
:param id_field: item identifier_field (optional)
|
||||
|
||||
:returns: string of rendered JSON (GeoJSON-LD)
|
||||
:returns: string of rendered JSON (GeoJSON-LD)
|
||||
"""
|
||||
|
||||
context = config['resources'][dataset].get('context', []).copy()
|
||||
defaultVocabulary = {
|
||||
'schema': 'https://schema.org/',
|
||||
@@ -215,17 +216,14 @@ def geojson2jsonld(config, data, dataset, identifier=None, id_field='id'):
|
||||
'FeatureCollection': 'schema:itemList'
|
||||
})
|
||||
|
||||
data['@id'] = '{}/collections/{}/items/'.format(
|
||||
config['server']['url'], dataset
|
||||
)
|
||||
data['@id'] = f"{config['server']['url']}/collections/{dataset}"
|
||||
|
||||
for i, feature in enumerate(data['features']):
|
||||
# Get URI for each feature
|
||||
identifier = feature.get(id_field,
|
||||
feature['properties'].get(id_field, ''))
|
||||
if not is_url(str(identifier)):
|
||||
identifier = '{}/collections/{}/items/{}'.format(
|
||||
config['server']['url'], dataset, feature['id'])
|
||||
identifier = f"config['server']['url']/collections/{dataset}/items/{feature['id']}" # noqa
|
||||
|
||||
data['features'][i] = {
|
||||
id_field: identifier,
|
||||
@@ -245,14 +243,14 @@ def geojson2jsonld(config, data, dataset, identifier=None, id_field='id'):
|
||||
return ldjsonData
|
||||
|
||||
|
||||
def jsonldify_geometry(feature):
|
||||
def jsonldify_geometry(feature: dict) -> None:
|
||||
"""
|
||||
Render JSON-LD for feature with GeoJSON, Geosparql/WKT, and
|
||||
schema geometry encodings.
|
||||
Render JSON-LD for feature with GeoJSON, Geosparql/WKT, and
|
||||
schema geometry encodings.
|
||||
|
||||
:param feature: feature body to with GeoJSON geometry
|
||||
:param feature: feature body to with GeoJSON geometry
|
||||
|
||||
:returns: None
|
||||
:returns: None
|
||||
"""
|
||||
|
||||
geo = feature.get('geometry')
|
||||
@@ -274,13 +272,13 @@ def jsonldify_geometry(feature):
|
||||
feature['schema:geo'] = geom2schemageo(geom)
|
||||
|
||||
|
||||
def geom2schemageo(geom):
|
||||
def geom2schemageo(geom: shape) -> dict:
|
||||
"""
|
||||
Render Schema Geometry from a GeoJSON base.
|
||||
Render Schema Geometry from a GeoJSON base.
|
||||
|
||||
:param geom: shapely geom of feature
|
||||
:param geom: shapely geom of feature
|
||||
|
||||
:returns: dict of rendered schema:geo geometry
|
||||
:returns: dict of rendered schema:geo geometry
|
||||
"""
|
||||
f = {'@type': 'schema:GeoShape'}
|
||||
if geom.geom_type == 'Point':
|
||||
@@ -313,9 +311,9 @@ def geom2schemageo(geom):
|
||||
# MultiPolygon to Polygon (buffer of 0 helps ensure manifold polygon)
|
||||
poly = unary_union(geom.buffer(0))
|
||||
if poly.geom_type.startswith('Multi') or not poly.is_valid:
|
||||
LOGGER.debug('Invalid Poly: {}'.format(poly.geom_type))
|
||||
LOGGER.debug(f'Invalid MultiPolygon: {poly.geom_type}')
|
||||
poly = poly.convex_hull
|
||||
LOGGER.debug('New Poly: {}'.format(poly.geom_type))
|
||||
LOGGER.debug(f'New MultiPolygon: {poly.geom_type}')
|
||||
poly_geom = poly.exterior.coords[:]
|
||||
|
||||
else:
|
||||
|
||||
+138
-143
@@ -61,7 +61,7 @@ THISDIR = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
def get_ogc_schemas_location(server_config):
|
||||
|
||||
osl = server_config.get('ogc_schemas_location', None)
|
||||
osl = server_config.get('ogc_schemas_location')
|
||||
|
||||
value = 'https://schemas.opengis.net'
|
||||
|
||||
@@ -86,7 +86,7 @@ def gen_media_type_object(media_type, api_type, path):
|
||||
:returns: `dict` of media type object
|
||||
"""
|
||||
|
||||
ref = '{}/{}'.format(OPENAPI_YAML[api_type], path)
|
||||
ref = f'{OPENAPI_YAML[api_type]}/{path}'
|
||||
|
||||
content = {
|
||||
media_type: {
|
||||
@@ -177,9 +177,9 @@ def get_oas_30(cfg):
|
||||
{'$ref': '#/components/parameters/lang'}
|
||||
],
|
||||
'responses': {
|
||||
'200': {'$ref': '{}#/components/responses/LandingPage'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'200': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/LandingPage"}, # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,7 +209,7 @@ def get_oas_30(cfg):
|
||||
],
|
||||
'responses': {
|
||||
'200': {'$ref': '#/components/responses/200'},
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'default': {'$ref': '#/components/responses/default'}
|
||||
}
|
||||
}
|
||||
@@ -226,9 +226,9 @@ def get_oas_30(cfg):
|
||||
{'$ref': '#/components/parameters/lang'}
|
||||
],
|
||||
'responses': {
|
||||
'200': {'$ref': '{}#/components/responses/ConformanceDeclaration'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'200': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/LandingPage"}, # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,9 +244,9 @@ def get_oas_30(cfg):
|
||||
{'$ref': '#/components/parameters/lang'}
|
||||
],
|
||||
'responses': {
|
||||
'200': {'$ref': '{}#/components/responses/Collections'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'200': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/LandingPage"}, # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -434,12 +434,12 @@ def get_oas_30(cfg):
|
||||
|
||||
for k, v in collections.items():
|
||||
if v.get('visibility', 'default') == 'hidden':
|
||||
LOGGER.debug('Skipping hidden layer: {}'.format(k))
|
||||
LOGGER.debug(f'Skipping hidden layer: {k}')
|
||||
continue
|
||||
name = l10n.translate(k, locale_)
|
||||
title = l10n.translate(v['title'], locale_)
|
||||
desc = l10n.translate(v['description'], locale_)
|
||||
collection_name_path = '/collections/{}'.format(k)
|
||||
collection_name_path = f'/collections/{k}'
|
||||
tag = {
|
||||
'name': name,
|
||||
'description': desc,
|
||||
@@ -457,19 +457,19 @@ def get_oas_30(cfg):
|
||||
|
||||
paths[collection_name_path] = {
|
||||
'get': {
|
||||
'summary': 'Get {} metadata'.format(title),
|
||||
'summary': f'Get {title} metadata',
|
||||
'description': desc,
|
||||
'tags': [name],
|
||||
'operationId': 'describe{}Collection'.format(name.capitalize()), # noqa
|
||||
'operationId': f'describe{name.capitalize()}Collection',
|
||||
'parameters': [
|
||||
{'$ref': '#/components/parameters/f'},
|
||||
{'$ref': '#/components/parameters/lang'}
|
||||
],
|
||||
'responses': {
|
||||
'200': {'$ref': '{}#/components/responses/Collection'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'404': {'$ref': '{}#/components/responses/NotFound'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'200': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/Collection"}, # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/NotFound"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -489,7 +489,7 @@ def get_oas_30(cfg):
|
||||
p = load_plugin('provider', get_provider_by_type(
|
||||
collections[k]['providers'], ptype))
|
||||
|
||||
items_path = '{}/items'.format(collection_name_path)
|
||||
items_path = f'{collection_name_path}/items'
|
||||
|
||||
coll_properties = deepcopy(oas['components']['parameters']['properties']) # noqa
|
||||
|
||||
@@ -497,26 +497,26 @@ def get_oas_30(cfg):
|
||||
|
||||
paths[items_path] = {
|
||||
'get': {
|
||||
'summary': 'Get {} items'.format(title), # noqa
|
||||
'summary': f'Get {title} items',
|
||||
'description': desc,
|
||||
'tags': [name],
|
||||
'operationId': 'get{}Features'.format(name.capitalize()),
|
||||
'operationId': f'get{name.capitalize()}Features',
|
||||
'parameters': [
|
||||
items_f,
|
||||
items_l,
|
||||
{'$ref': '{}#/components/parameters/bbox'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
{'$ref': '{}#/components/parameters/limit'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oapif']}#/components/parameters/bbox"}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oapif']}#/components/parameters/limit"}, # noqa
|
||||
coll_properties,
|
||||
{'$ref': '#/components/parameters/vendorSpecificParameters'}, # noqa
|
||||
{'$ref': '#/components/parameters/skipGeometry'},
|
||||
{'$ref': '{}/parameters/sortby.yaml'.format(OPENAPI_YAML['oapir'])}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oapir']}/parameters/sortby.yaml"}, # noqa
|
||||
{'$ref': '#/components/parameters/offset'},
|
||||
],
|
||||
'responses': {
|
||||
'200': {'$ref': '{}#/components/responses/Features'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'404': {'$ref': '{}#/components/responses/NotFound'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'200': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/Features"}, # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/NotFound"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -525,10 +525,10 @@ def get_oas_30(cfg):
|
||||
LOGGER.debug('Provider is editable; adding post')
|
||||
|
||||
paths[items_path]['post'] = {
|
||||
'summary': 'Add {} items'.format(title), # noqa
|
||||
'summary': f'Add {title} items',
|
||||
'description': desc,
|
||||
'tags': [name],
|
||||
'operationId': 'add{}Features'.format(name.capitalize()),
|
||||
'operationId': f'add{name.capitalize()}Features',
|
||||
'requestBody': {
|
||||
'description': 'Adds item to collection',
|
||||
'content': {
|
||||
@@ -540,8 +540,8 @@ def get_oas_30(cfg):
|
||||
},
|
||||
'responses': {
|
||||
'201': {'description': 'Successful creation'},
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,33 +555,32 @@ def get_oas_30(cfg):
|
||||
|
||||
if ptype == 'record':
|
||||
paths[items_path]['get']['parameters'].append(
|
||||
{'$ref': '{}/parameters/q.yaml'.format(OPENAPI_YAML['oapir'])}) # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oapir']}/parameters/q.yaml"})
|
||||
if p.fields:
|
||||
queryables_path = '{}/queryables'.format(collection_name_path)
|
||||
queryables_path = f'{collection_name_path}/queryables'
|
||||
|
||||
paths[queryables_path] = {
|
||||
'get': {
|
||||
'summary': 'Get {} queryables'.format(title),
|
||||
'summary': f'Get {title} queryables',
|
||||
'description': desc,
|
||||
'tags': [name],
|
||||
'operationId': 'get{}Queryables'.format(
|
||||
name.capitalize()),
|
||||
'operationId': f'get{name.capitalize()}Queryables',
|
||||
'parameters': [
|
||||
items_f,
|
||||
items_l
|
||||
],
|
||||
'responses': {
|
||||
'200': {'$ref': '#/components/responses/Queryables'}, # noqa
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'404': {'$ref': '{}#/components/responses/NotFound'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/NotFound"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"}, # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if p.time_field is not None:
|
||||
paths[items_path]['get']['parameters'].append(
|
||||
{'$ref': '{}#/components/parameters/datetime'.format(OPENAPI_YAML['oapif'])}) # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oapif']}#/components/parameters/datetime"}) # noqa
|
||||
|
||||
for field, type_ in p.fields.items():
|
||||
|
||||
@@ -611,8 +610,8 @@ def get_oas_30(cfg):
|
||||
else:
|
||||
schema = type_
|
||||
|
||||
path_ = '{}/items'.format(collection_name_path)
|
||||
paths['{}'.format(path_)]['get']['parameters'].append({
|
||||
path_ = f'{collection_name_path}/items'
|
||||
paths[path_]['get']['parameters'].append({
|
||||
'name': field,
|
||||
'in': 'query',
|
||||
'required': False,
|
||||
@@ -621,29 +620,29 @@ def get_oas_30(cfg):
|
||||
'explode': False
|
||||
})
|
||||
|
||||
paths['{}/items/{{featureId}}'.format(collection_name_path)] = {
|
||||
paths[f'{collection_name_path}/items/{{featureId}}'] = {
|
||||
'get': {
|
||||
'summary': 'Get {} item by id'.format(title),
|
||||
'summary': f'Get {title} item by id',
|
||||
'description': desc,
|
||||
'tags': [name],
|
||||
'operationId': 'get{}Feature'.format(name.capitalize()),
|
||||
'operationId': f'get{name.capitalize()}Feature',
|
||||
'parameters': [
|
||||
{'$ref': '{}#/components/parameters/featureId'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oapif']}#/components/parameters/featureId"}, # noqa
|
||||
{'$ref': '#/components/parameters/f'},
|
||||
{'$ref': '#/components/parameters/lang'}
|
||||
],
|
||||
'responses': {
|
||||
'200': {'$ref': '{}#/components/responses/Feature'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'404': {'$ref': '{}#/components/responses/NotFound'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'200': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/Feature"}, # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/NotFound"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try:
|
||||
schema_ref = p.get_schema()
|
||||
paths['{}/items/{{featureId}}'.format(collection_name_path)]['get']['responses']['200'] = { # noqa
|
||||
paths[f'{collection_name_path}/items/{{featureId}}']['get']['responses']['200'] = { # noqa
|
||||
'content': {
|
||||
schema_ref[0]: {
|
||||
'schema': schema_ref[1]
|
||||
@@ -655,14 +654,14 @@ def get_oas_30(cfg):
|
||||
|
||||
if p.editable:
|
||||
LOGGER.debug('Provider is editable; adding put/delete')
|
||||
put_path = '{}/items/{{featureId}}'.format(collection_name_path) # noqa
|
||||
put_path = f'{collection_name_path}/items/{{featureId}}' # noqa
|
||||
paths[put_path]['put'] = { # noqa
|
||||
'summary': 'Update {} items'.format(title),
|
||||
'summary': f'Update {title} items',
|
||||
'description': desc,
|
||||
'tags': [name],
|
||||
'operationId': 'update{}Features'.format(name.capitalize()), # noqa
|
||||
'operationId': f'update{name.capitalize()}Features',
|
||||
'parameters': [
|
||||
{'$ref': '{}#/components/parameters/featureId'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oapif']}#/components/parameters/featureId"} # noqa
|
||||
],
|
||||
'requestBody': {
|
||||
'description': 'Updates item in collection',
|
||||
@@ -675,8 +674,8 @@ def get_oas_30(cfg):
|
||||
},
|
||||
'responses': {
|
||||
'204': {'description': 'Successful update'},
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
|
||||
@@ -688,18 +687,18 @@ def get_oas_30(cfg):
|
||||
except Exception as err:
|
||||
LOGGER.debug(err)
|
||||
|
||||
paths['{}/items/{{featureId}}'.format(collection_name_path)]['delete'] = { # noqa
|
||||
'summary': 'Delete {} items'.format(title),
|
||||
paths[f'{collection_name_path}/items/{{featureId}}']['delete'] = { # noqa
|
||||
'summary': f'Delete {title} items',
|
||||
'description': desc,
|
||||
'tags': [name],
|
||||
'operationId': 'delete{}Features'.format(name.capitalize()), # noqa
|
||||
'operationId': f'delete{name.capitalize()}Features',
|
||||
'parameters': [
|
||||
{'$ref': '{}#/components/parameters/featureId'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oapif']}#/components/parameters/featureId"}, # noqa
|
||||
],
|
||||
'responses': {
|
||||
'200': {'description': 'Successful delete'},
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,71 +710,67 @@ def get_oas_30(cfg):
|
||||
load_plugin('provider', get_provider_by_type(
|
||||
collections[k]['providers'], 'coverage'))
|
||||
|
||||
coverage_path = '{}/coverage'.format(collection_name_path)
|
||||
coverage_path = f'{collection_name_path}/coverage'
|
||||
|
||||
paths[coverage_path] = {
|
||||
'get': {
|
||||
'summary': 'Get {} coverage'.format(title),
|
||||
'summary': f'Get {title} coverage',
|
||||
'description': desc,
|
||||
'tags': [name],
|
||||
'operationId': 'get{}Coverage'.format(name.capitalize()),
|
||||
'operationId': f'get{name.capitalize()}Coverage',
|
||||
'parameters': [
|
||||
items_f,
|
||||
items_l,
|
||||
{'$ref': '{}#/components/parameters/bbox'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oapif']}#/components/parameters/bbox"}, # noqa
|
||||
{'$ref': '#/components/parameters/bbox-crs'}
|
||||
],
|
||||
'responses': {
|
||||
'200': {'$ref': '{}#/components/responses/Features'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'404': {'$ref': '{}#/components/responses/NotFound'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'200': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/Features"}, # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/NotFound"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
coverage_domainset_path = '{}/coverage/domainset'.format(
|
||||
collection_name_path)
|
||||
coverage_domainset_path = f'{collection_name_path}/coverage/domainset' # noqa
|
||||
|
||||
paths[coverage_domainset_path] = {
|
||||
'get': {
|
||||
'summary': 'Get {} coverage domain set'.format(title),
|
||||
'summary': f'Get {title} coverage domain set',
|
||||
'description': desc,
|
||||
'tags': [name],
|
||||
'operationId': 'get{}CoverageDomainSet'.format(
|
||||
name.capitalize()),
|
||||
'operationId': f'get{name.capitalize()}CoverageDomainSet',
|
||||
'parameters': [
|
||||
items_f,
|
||||
items_l
|
||||
],
|
||||
'responses': {
|
||||
'200': {'$ref': '{}/schemas/cis_1.1/domainSet.yaml'.format(OPENAPI_YAML['oacov'])}, # noqa
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'404': {'$ref': '{}#/components/responses/NotFound'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'200': {'$ref': f"{OPENAPI_YAML['oacov']}/schemas/cis_1.1/domainSet.yaml"}, # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/NotFound"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
coverage_rangetype_path = '{}/coverage/rangetype'.format(
|
||||
collection_name_path)
|
||||
coverage_rangetype_path = f'{collection_name_path}/coverage/rangetype' # noqa
|
||||
|
||||
paths[coverage_rangetype_path] = {
|
||||
'get': {
|
||||
'summary': 'Get {} coverage range type'.format(title),
|
||||
'summary': f'Get {title} coverage range type',
|
||||
'description': desc,
|
||||
'tags': [name],
|
||||
'operationId': 'get{}CoverageRangeType'.format(
|
||||
name.capitalize()),
|
||||
'operationId': f'get{name.capitalize()}CoverageRangeType',
|
||||
'parameters': [
|
||||
items_f,
|
||||
items_l
|
||||
],
|
||||
'responses': {
|
||||
'200': {'$ref': '{}/schemas/cis_1.1/rangeType.yaml'.format(OPENAPI_YAML['oacov'])}, # noqa
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'404': {'$ref': '{}#/components/responses/NotFound'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'200': {'$ref': f"{OPENAPI_YAML['oacov']}/schemas/cis_1.1/rangeType.yaml"}, # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/NotFound"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -830,47 +825,47 @@ def get_oas_30(cfg):
|
||||
},
|
||||
'links': {
|
||||
'type': 'array',
|
||||
'items': {'$ref': '{}#/components/schemas/link'.format(OPENAPI_YAML['oapit'])}, # noqa
|
||||
'items': {'$ref': f"{OPENAPI_YAML['oapit']}#/components/schemas/link"} # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
tiles_path = '{}/tiles'.format(collection_name_path)
|
||||
tiles_path = f'{collection_name_path}/tiles'
|
||||
|
||||
paths[tiles_path] = {
|
||||
'get': {
|
||||
'summary': 'Fetch a {} tiles description'.format(title), # noqa
|
||||
'summary': f'Fetch a {title} tiles description',
|
||||
'description': desc,
|
||||
'tags': [name],
|
||||
'operationId': 'describe{}Tiles'.format(name.capitalize()),
|
||||
'operationId': f'describe{name.capitalize()}Tiles',
|
||||
'parameters': [
|
||||
items_f,
|
||||
# items_l TODO: is this useful?
|
||||
],
|
||||
'responses': {
|
||||
'200': {'$ref': '#/components/responses/Tiles'},
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'404': {'$ref': '{}#/components/responses/NotFound'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/NotFound"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tiles_data_path = '{}/tiles/{{tileMatrixSetId}}/{{tileMatrix}}/{{tileRow}}/{{tileCol}}'.format(collection_name_path) # noqa
|
||||
tiles_data_path = f'{collection_name_path}/tiles/{{tileMatrixSetId}}/{{tileMatrix}}/{{tileRow}}/{{tileCol}}' # noqa
|
||||
|
||||
paths[tiles_data_path] = {
|
||||
'get': {
|
||||
'summary': 'Get a {} tile'.format(title),
|
||||
'summary': f'Get a {title} tile',
|
||||
'description': desc,
|
||||
'tags': [name],
|
||||
'operationId': 'get{}Tiles'.format(name.capitalize()),
|
||||
'operationId': f'get{name.capitalize()}Tiles',
|
||||
'parameters': [
|
||||
{'$ref': '{}#/components/parameters/tileMatrixSetId'.format(OPENAPI_YAML['oat'])}, # noqa
|
||||
{'$ref': '{}#/components/parameters/tileMatrix'.format(OPENAPI_YAML['oat'])}, # noqa
|
||||
{'$ref': '{}#/components/parameters/tileRow'.format(OPENAPI_YAML['oat'])}, # noqa
|
||||
{'$ref': '{}#/components/parameters/tileCol'.format(OPENAPI_YAML['oat'])}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oat']}#/components/parameters/tileMatrixSetId"}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oat']}#/components/parameters/tileMatrix"}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oat']}#/components/parameters/tileRow"}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oat']}#/components/parameters/tileCol"}, # noqa
|
||||
{
|
||||
'name': 'f',
|
||||
'in': 'query',
|
||||
@@ -886,9 +881,9 @@ def get_oas_30(cfg):
|
||||
}
|
||||
],
|
||||
'responses': {
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'404': {'$ref': '{}#/components/responses/NotFound'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/NotFound"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"} # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -916,29 +911,29 @@ def get_oas_30(cfg):
|
||||
|
||||
for qt in ep.get_query_types():
|
||||
edr_query_endpoints.append({
|
||||
'path': '{}/{}'.format(collection_name_path, qt),
|
||||
'path': f'{collection_name_path}/{qt}',
|
||||
'qt': qt,
|
||||
'op_id': 'query{}{}'.format(qt.capitalize(), k.capitalize()) # noqa
|
||||
'op_id': f'query{qt.capitalize()}{k.capitalize()}'
|
||||
})
|
||||
if ep.instances:
|
||||
edr_query_endpoints.append({
|
||||
'path': '{}/instances/{{instanceId}}/{}'.format(collection_name_path, qt), # noqa
|
||||
'path': f'{collection_name_path}/instances/{{instanceId}}/{qt}', # noqa
|
||||
'qt': qt,
|
||||
'op_id': 'query{}Instance{}'.format(qt.capitalize(), k.capitalize()) # noqa
|
||||
'op_id': f'query{qt.capitalize()}Instance{k.capitalize()}' # noqa
|
||||
})
|
||||
|
||||
for eqe in edr_query_endpoints:
|
||||
paths[eqe['path']] = {
|
||||
'get': {
|
||||
'summary': 'query {} by {}'.format(v['description'], eqe['qt']), # noqa
|
||||
'summary': f"query {v['description']} by {eqe['qt']}", # noqa
|
||||
'description': v['description'],
|
||||
'tags': [k],
|
||||
'operationId': eqe['op_id'],
|
||||
'parameters': [
|
||||
{'$ref': '{}/parameters/{}Coords.yaml'.format(OPENAPI_YAML['oaedr'], eqe['qt'])}, # noqa
|
||||
{'$ref': '{}#/components/parameters/datetime'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
{'$ref': '{}/parameters/parameter-name.yaml'.format(OPENAPI_YAML['oaedr'])}, # noqa
|
||||
{'$ref': '{}/parameters/z.yaml'.format(OPENAPI_YAML['oaedr'])}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oaedr']}/parameters/{eqe['qt']}Coords.yaml"}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oapif']}#/components/parameters/datetime"}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oaedr']}/parameters/parameter-name.yaml"}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oaedr']}/parameters/z.yaml"}, # noqa
|
||||
{'$ref': '#/components/parameters/f'}
|
||||
],
|
||||
'responses': {
|
||||
@@ -947,13 +942,14 @@ def get_oas_30(cfg):
|
||||
'content': {
|
||||
'application/prs.coverage+json': {
|
||||
'schema': {
|
||||
'$ref': '{}/schemas/coverageJSON.yaml'.format(OPENAPI_YAML['oaedr'])} # noqa
|
||||
'$ref': f"{OPENAPI_YAML['oaedr']}/schemas/coverageJSON.yaml" # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.debug('setting up maps endpoints')
|
||||
map_extension = filter_providers_by_type(
|
||||
@@ -966,15 +962,15 @@ def get_oas_30(cfg):
|
||||
map_f['schema']['enum'] = [map_extension['format']['name']]
|
||||
map_f['schema']['default'] = map_extension['format']['name']
|
||||
|
||||
pth = '/collections/{}/map'.format(k)
|
||||
pth = f'/collections/{k}/map'
|
||||
paths[pth] = {
|
||||
'get': {
|
||||
'summary': 'Get map',
|
||||
'description': '{} map'.format(v['description']),
|
||||
'description': f"{v['description']} map",
|
||||
'tags': [k],
|
||||
'operationId': 'getMap',
|
||||
'parameters': [
|
||||
{'$ref': '{}#/components/parameters/bbox'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oapif']}#/components/parameters/bbox"}, # noqa
|
||||
{
|
||||
'name': 'width',
|
||||
'in': 'query',
|
||||
@@ -1019,14 +1015,14 @@ def get_oas_30(cfg):
|
||||
'application/json': {}
|
||||
}
|
||||
},
|
||||
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
|
||||
'500': {'$ref': '{}#/components/responses/ServerError'.format(OPENAPI_YAML['oapif'])} # noqa
|
||||
'400': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/InvalidParameter"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapif']}#/components/responses/ServerError"}, # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
if mp.time_field is not None:
|
||||
paths[pth]['get']['parameters'].append(
|
||||
{'$ref': '{}#/components/parameters/datetime'.format(OPENAPI_YAML['oapif'])}) # noqa
|
||||
{'$ref': f"{OPENAPI_YAML['oapif']}#/components/parameters/datetime"}) # noqa
|
||||
|
||||
LOGGER.debug('setting up STAC')
|
||||
stac_collections = filter_dict_by_key_value(cfg['resources'],
|
||||
@@ -1061,7 +1057,7 @@ def get_oas_30(cfg):
|
||||
{'$ref': '#/components/parameters/f'}
|
||||
],
|
||||
'responses': {
|
||||
'200': {'$ref': '{}/responses/ProcessList.yaml'.format(OPENAPI_YAML['oapip'])}, # noqa
|
||||
'200': {'$ref': f"{OPENAPI_YAML['oapip']}/responses/ProcessList.yaml"}, # noqa
|
||||
'default': {'$ref': '#/components/responses/default'}
|
||||
}
|
||||
}
|
||||
@@ -1070,13 +1066,13 @@ def get_oas_30(cfg):
|
||||
|
||||
for k, v in processes.items():
|
||||
if k.startswith('_'):
|
||||
LOGGER.debug('Skipping hidden layer: {}'.format(k))
|
||||
LOGGER.debug(f'Skipping hidden layer: {k}')
|
||||
continue
|
||||
name = l10n.translate(k, locale_)
|
||||
p = load_plugin('process', v['processor'])
|
||||
|
||||
md_desc = l10n.translate(p.metadata['description'], locale_)
|
||||
process_name_path = '/processes/{}'.format(name)
|
||||
process_name_path = f'/processes/{name}'
|
||||
tag = {
|
||||
'name': name,
|
||||
'description': md_desc, # noqa
|
||||
@@ -1097,7 +1093,7 @@ def get_oas_30(cfg):
|
||||
'summary': 'Get process metadata',
|
||||
'description': md_desc,
|
||||
'tags': [name],
|
||||
'operationId': 'describe{}Process'.format(name.capitalize()), # noqa
|
||||
'operationId': f'describe{name.capitalize()}Process',
|
||||
'parameters': [
|
||||
{'$ref': '#/components/parameters/f'}
|
||||
],
|
||||
@@ -1108,18 +1104,17 @@ def get_oas_30(cfg):
|
||||
}
|
||||
}
|
||||
|
||||
paths['{}/execution'.format(process_name_path)] = {
|
||||
paths[f'{process_name_path}/execution'] = {
|
||||
'post': {
|
||||
'summary': 'Process {} execution'.format(
|
||||
l10n.translate(p.metadata['title'], locale_)),
|
||||
'summary': f"Process {l10n.translate(p.metadata['title'], locale_)} execution", # noqa
|
||||
'description': md_desc,
|
||||
'tags': [name],
|
||||
'operationId': 'execute{}Job'.format(name.capitalize()),
|
||||
'operationId': f'execute{name.capitalize()}Job',
|
||||
'responses': {
|
||||
'200': {'$ref': '#/components/responses/200'},
|
||||
'201': {'$ref': '{}/responses/ExecuteAsync.yaml'.format(OPENAPI_YAML['oapip'])}, # noqa
|
||||
'404': {'$ref': '{}/responses/NotFound.yaml'.format(OPENAPI_YAML['oapip'])}, # noqa
|
||||
'500': {'$ref': '{}/responses/ServerError.yaml'.format(OPENAPI_YAML['oapip'])}, # noqa
|
||||
'201': {'$ref': f"{OPENAPI_YAML['oapip']}/responses/ExecuteAsync.yaml"}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapip']}/responses/NotFound.yaml"}, # noqa
|
||||
'500': {'$ref': f"{OPENAPI_YAML['oapip']}/responses/ServerError.yaml"}, # noqa
|
||||
'default': {'$ref': '#/components/responses/default'}
|
||||
},
|
||||
'requestBody': {
|
||||
@@ -1128,7 +1123,7 @@ def get_oas_30(cfg):
|
||||
'content': {
|
||||
'application/json': {
|
||||
'schema': {
|
||||
'$ref': '{}/schemas/execute.yaml'.format(OPENAPI_YAML['oapip']) # noqa
|
||||
'$ref': f"{OPENAPI_YAML['oapip']}/schemas/execute.yaml" # noqa
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1136,7 +1131,7 @@ def get_oas_30(cfg):
|
||||
}
|
||||
}
|
||||
if 'example' in p.metadata:
|
||||
paths['{}/execution'.format(process_name_path)]['post']['requestBody']['content']['application/json']['example'] = p.metadata['example'] # noqa
|
||||
paths[f'{process_name_path}/execution']['post']['requestBody']['content']['application/json']['example'] = p.metadata['example'] # noqa
|
||||
|
||||
name_in_path = {
|
||||
'name': 'jobId',
|
||||
@@ -1157,7 +1152,7 @@ def get_oas_30(cfg):
|
||||
'operationId': 'getJobs',
|
||||
'responses': {
|
||||
'200': {'$ref': '#/components/responses/200'},
|
||||
'404': {'$ref': '{}/responses/NotFound.yaml'.format(OPENAPI_YAML['oapip'])}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapip']}/responses/NotFound.yaml"}, # noqa
|
||||
'default': {'$ref': '#/components/responses/default'}
|
||||
}
|
||||
}
|
||||
@@ -1175,7 +1170,7 @@ def get_oas_30(cfg):
|
||||
'operationId': 'getJob',
|
||||
'responses': {
|
||||
'200': {'$ref': '#/components/responses/200'},
|
||||
'404': {'$ref': '{}/responses/NotFound.yaml'.format(OPENAPI_YAML['oapip'])}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapip']}/responses/NotFound.yaml"}, # noqa
|
||||
'default': {'$ref': '#/components/responses/default'} # noqa
|
||||
}
|
||||
},
|
||||
@@ -1189,7 +1184,7 @@ def get_oas_30(cfg):
|
||||
'operationId': 'deleteJob',
|
||||
'responses': {
|
||||
'204': {'$ref': '#/components/responses/204'},
|
||||
'404': {'$ref': '{}/responses/NotFound.yaml'.format(OPENAPI_YAML['oapip'])}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapip']}/responses/NotFound.yaml"}, # noqa
|
||||
'default': {'$ref': '#/components/responses/default'} # noqa
|
||||
}
|
||||
},
|
||||
@@ -1207,7 +1202,7 @@ def get_oas_30(cfg):
|
||||
'operationId': 'getJobResults',
|
||||
'responses': {
|
||||
'200': {'$ref': '#/components/responses/200'},
|
||||
'404': {'$ref': '{}/responses/NotFound.yaml'.format(OPENAPI_YAML['oapip'])}, # noqa
|
||||
'404': {'$ref': f"{OPENAPI_YAML['oapip']}/responses/NotFound.yaml"}, # noqa
|
||||
'default': {'$ref': '#/components/responses/default'} # noqa
|
||||
}
|
||||
}
|
||||
@@ -1297,7 +1292,7 @@ def validate(ctx, openapi_file):
|
||||
if openapi_file is None:
|
||||
raise click.ClickException('--openapi/-o required')
|
||||
|
||||
click.echo('Validating {}'.format(openapi_file))
|
||||
click.echo(f'Validating {openapi_file}')
|
||||
instance = yaml_load(openapi_file)
|
||||
validate_openapi_document(instance)
|
||||
click.echo('Valid OpenAPI document')
|
||||
|
||||
+7
-6
@@ -30,6 +30,7 @@
|
||||
|
||||
import importlib
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -71,7 +72,7 @@ PLUGINS = {
|
||||
}
|
||||
|
||||
|
||||
def load_plugin(plugin_type, plugin_def):
|
||||
def load_plugin(plugin_type: str, plugin_def: dict) -> Any:
|
||||
"""
|
||||
loads plugin by name
|
||||
|
||||
@@ -84,16 +85,16 @@ def load_plugin(plugin_type, plugin_def):
|
||||
name = plugin_def['name']
|
||||
|
||||
if plugin_type not in PLUGINS.keys():
|
||||
msg = 'Plugin type {} not found'.format(plugin_type)
|
||||
msg = f'Plugin type {plugin_type} not found'
|
||||
LOGGER.exception(msg)
|
||||
raise InvalidPluginError(msg)
|
||||
|
||||
plugin_list = PLUGINS[plugin_type]
|
||||
|
||||
LOGGER.debug('Plugins: {}'.format(plugin_list))
|
||||
LOGGER.debug(f'Plugins: {plugin_list}')
|
||||
|
||||
if '.' not in name and name not in plugin_list.keys():
|
||||
msg = 'Plugin {} not found'.format(name)
|
||||
msg = f'Plugin {name} not found'
|
||||
LOGGER.exception(msg)
|
||||
raise InvalidPluginError(msg)
|
||||
|
||||
@@ -102,8 +103,8 @@ def load_plugin(plugin_type, plugin_def):
|
||||
else: # core formatter
|
||||
packagename, classname = plugin_list[name].rsplit('.', 1)
|
||||
|
||||
LOGGER.debug('package name: {}'.format(packagename))
|
||||
LOGGER.debug('class name: {}'.format(classname))
|
||||
LOGGER.debug(f'package name: {packagename}')
|
||||
LOGGER.debug(f'class name: {classname}')
|
||||
|
||||
module = importlib.import_module(packagename)
|
||||
class_ = getattr(module, classname)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2019 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -28,6 +28,7 @@
|
||||
# =================================================================
|
||||
|
||||
import logging
|
||||
from typing import Any, Tuple
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -35,7 +36,7 @@ LOGGER = logging.getLogger(__name__)
|
||||
class BaseProcessor:
|
||||
"""generic Processor ABC. Processes are inherited from this class"""
|
||||
|
||||
def __init__(self, processor_def, process_metadata):
|
||||
def __init__(self, processor_def: dict, process_metadata: dict):
|
||||
"""
|
||||
Initialize object
|
||||
|
||||
@@ -47,7 +48,7 @@ class BaseProcessor:
|
||||
self.name = processor_def['name']
|
||||
self.metadata = process_metadata
|
||||
|
||||
def execute(self):
|
||||
def execute(self) -> Tuple[str, Any]:
|
||||
"""
|
||||
execute the process
|
||||
|
||||
@@ -57,7 +58,7 @@ class BaseProcessor:
|
||||
raise NotImplementedError()
|
||||
|
||||
def __repr__(self):
|
||||
return '<BaseProcessor> {}'.format(self.name)
|
||||
return f'<BaseProcessor> {self.name}'
|
||||
|
||||
|
||||
class ProcessorGenericError(Exception):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2019 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -120,12 +120,13 @@ class HelloWorldProcessor(BaseProcessor):
|
||||
def execute(self, data):
|
||||
|
||||
mimetype = 'application/json'
|
||||
name = data.get('name', None)
|
||||
name = data.get('name')
|
||||
|
||||
if name is None:
|
||||
raise ProcessorExecuteError('Cannot process without a name')
|
||||
|
||||
value = 'Hello {}! {}'.format(name, data.get('message', '')).strip()
|
||||
message = data.get('message', '')
|
||||
value = f'Hello {name}! {message}'.strip()
|
||||
|
||||
outputs = {
|
||||
'id': 'echo',
|
||||
@@ -135,4 +136,4 @@ class HelloWorldProcessor(BaseProcessor):
|
||||
return mimetype, outputs
|
||||
|
||||
def __repr__(self):
|
||||
return '<HelloWorldProcessor> {}'.format(self.name)
|
||||
return f'<HelloWorldProcessor> {self.name}'
|
||||
|
||||
@@ -28,13 +28,14 @@
|
||||
# =================================================================
|
||||
|
||||
from datetime import datetime
|
||||
import io
|
||||
import json
|
||||
import logging
|
||||
from multiprocessing import dummy
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Any, Tuple
|
||||
|
||||
from pygeoapi.util import DATETIME_FORMAT, JobStatus
|
||||
from pygeoapi.process.base import BaseProcessor
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -42,7 +43,7 @@ LOGGER = logging.getLogger(__name__)
|
||||
class BaseManager:
|
||||
"""generic Manager ABC"""
|
||||
|
||||
def __init__(self, manager_def):
|
||||
def __init__(self, manager_def: dict):
|
||||
"""
|
||||
Initialize object
|
||||
|
||||
@@ -53,10 +54,13 @@ class BaseManager:
|
||||
|
||||
self.name = manager_def['name']
|
||||
self.is_async = False
|
||||
self.connection = manager_def.get('connection', None)
|
||||
self.output_dir = manager_def.get('output_dir', None)
|
||||
self.connection = manager_def.get('connection')
|
||||
self.output_dir = manager_def.get('output_dir')
|
||||
|
||||
def get_jobs(self, status=None):
|
||||
if self.output_dir is not None:
|
||||
self.output_dir = Path(self.output_dir)
|
||||
|
||||
def get_jobs(self, status: JobStatus = None) -> list:
|
||||
"""
|
||||
Get process jobs, optionally filtered by status
|
||||
|
||||
@@ -68,7 +72,7 @@ class BaseManager:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
def add_job(self, job_metadata):
|
||||
def add_job(self, job_metadata: dict) -> str:
|
||||
"""
|
||||
Add a job
|
||||
|
||||
@@ -79,7 +83,7 @@ class BaseManager:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
def update_job(self, job_id, update_dict):
|
||||
def update_job(self, job_id: str, update_dict: dict) -> bool:
|
||||
"""
|
||||
Updates a job
|
||||
|
||||
@@ -91,7 +95,7 @@ class BaseManager:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_job(self, job_id):
|
||||
def get_job(self, job_id: str) -> dict:
|
||||
"""
|
||||
Get a job (!)
|
||||
|
||||
@@ -102,7 +106,7 @@ class BaseManager:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_job_result(self, job_id):
|
||||
def get_job_result(self, job_id: str) -> Tuple[str, Any]:
|
||||
"""
|
||||
Returns the actual output from a completed process
|
||||
|
||||
@@ -113,7 +117,7 @@ class BaseManager:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_job(self, job_id):
|
||||
def delete_job(self, job_id: str) -> bool:
|
||||
"""
|
||||
Deletes a job and associated results/outputs
|
||||
|
||||
@@ -124,7 +128,8 @@ class BaseManager:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
def _execute_handler_async(self, p, job_id, data_dict):
|
||||
def _execute_handler_async(self, p: BaseProcessor, job_id: str,
|
||||
data_dict: dict) -> Tuple[None, JobStatus]:
|
||||
"""
|
||||
This private execution handler executes a process in a background
|
||||
thread using `multiprocessing.dummy`
|
||||
@@ -145,7 +150,8 @@ class BaseManager:
|
||||
_process.start()
|
||||
return 'application/json', None, JobStatus.accepted
|
||||
|
||||
def _execute_handler_sync(self, p, job_id, data_dict):
|
||||
def _execute_handler_sync(self, p: BaseProcessor, job_id: str,
|
||||
data_dict: dict) -> Tuple[str, Any, JobStatus]:
|
||||
"""
|
||||
Synchronous execution handler
|
||||
|
||||
@@ -180,8 +186,8 @@ class BaseManager:
|
||||
|
||||
try:
|
||||
if self.output_dir is not None:
|
||||
filename = '{}-{}'.format(p.metadata['id'], job_id)
|
||||
job_filename = os.path.join(self.output_dir, filename)
|
||||
filename = f"{p.metadata['id']}-{job_id}"
|
||||
job_filename = self.output_dir / filename
|
||||
else:
|
||||
job_filename = None
|
||||
|
||||
@@ -195,7 +201,7 @@ class BaseManager:
|
||||
})
|
||||
|
||||
if self.output_dir is not None:
|
||||
LOGGER.debug('writing output to {}'.format(job_filename))
|
||||
LOGGER.debug(f'writing output to {job_filename}')
|
||||
if isinstance(outputs, dict):
|
||||
mode = 'w'
|
||||
data = json.dumps(outputs, sort_keys=True, indent=4)
|
||||
@@ -204,7 +210,7 @@ class BaseManager:
|
||||
mode = 'wb'
|
||||
data = outputs
|
||||
encoding = None
|
||||
with io.open(job_filename, mode, encoding=encoding) as fh:
|
||||
with job_filename.open(mode=mode, encoding=encoding) as fh:
|
||||
fh.write(data)
|
||||
|
||||
current_status = JobStatus.successful
|
||||
@@ -213,7 +219,7 @@ class BaseManager:
|
||||
'job_end_datetime': datetime.utcnow().strftime(
|
||||
DATETIME_FORMAT),
|
||||
'status': current_status.value,
|
||||
'location': job_filename,
|
||||
'location': str(job_filename),
|
||||
'mimetype': jfmt,
|
||||
'message': 'Job complete',
|
||||
'progress': 100
|
||||
@@ -230,6 +236,7 @@ class BaseManager:
|
||||
# endpoint, even if the /result endpoint correctly returns the
|
||||
# failure information (i.e. what one might assume is a 200
|
||||
# response).
|
||||
|
||||
current_status = JobStatus.failed
|
||||
code = 'InvalidParameterValue'
|
||||
outputs = {
|
||||
@@ -272,4 +279,4 @@ class BaseManager:
|
||||
return self._execute_handler_async(p, job_id, data_dict)
|
||||
|
||||
def __repr__(self):
|
||||
return '<BaseManager> {}'.format(self.name)
|
||||
return f'<BaseManager> {self.name}'
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
# =================================================================
|
||||
|
||||
import logging
|
||||
from typing import Any, Tuple
|
||||
|
||||
from pygeoapi.process.base import BaseProcessor
|
||||
from pygeoapi.process.manager.base import BaseManager
|
||||
from pygeoapi.util import JobStatus
|
||||
|
||||
@@ -38,7 +40,7 @@ LOGGER = logging.getLogger(__name__)
|
||||
class DummyManager(BaseManager):
|
||||
"""generic Manager ABC"""
|
||||
|
||||
def __init__(self, manager_def):
|
||||
def __init__(self, manager_def: dict):
|
||||
"""
|
||||
Initialize object
|
||||
|
||||
@@ -49,7 +51,7 @@ class DummyManager(BaseManager):
|
||||
|
||||
super().__init__(manager_def)
|
||||
|
||||
def get_jobs(self, status=None):
|
||||
def get_jobs(self, status: JobStatus = None) -> list:
|
||||
"""
|
||||
Get process jobs, optionally filtered by status
|
||||
|
||||
@@ -61,7 +63,8 @@ class DummyManager(BaseManager):
|
||||
|
||||
return []
|
||||
|
||||
def execute_process(self, p, job_id, data_dict, is_async=False):
|
||||
def execute_process(self, p: BaseProcessor, job_id: str, data_dict: dict,
|
||||
is_async: bool = False) -> Tuple[str, Any, int]:
|
||||
"""
|
||||
Default process execution handler
|
||||
|
||||
@@ -93,4 +96,4 @@ class DummyManager(BaseManager):
|
||||
return jfmt, outputs, current_status
|
||||
|
||||
def __repr__(self):
|
||||
return '<DummyManager> {}'.format(self.name)
|
||||
return f'<DummyManager> {self.name}'
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
# =================================================================
|
||||
|
||||
import fcntl
|
||||
import io
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Any, Tuple
|
||||
|
||||
import tinydb
|
||||
|
||||
@@ -44,7 +44,7 @@ LOGGER = logging.getLogger(__name__)
|
||||
class TinyDBManager(BaseManager):
|
||||
"""TinyDB Manager"""
|
||||
|
||||
def __init__(self, manager_def):
|
||||
def __init__(self, manager_def: dict):
|
||||
"""
|
||||
Initialize object
|
||||
|
||||
@@ -56,7 +56,7 @@ class TinyDBManager(BaseManager):
|
||||
super().__init__(manager_def)
|
||||
self.is_async = True
|
||||
|
||||
def _connect(self, mode='r'):
|
||||
def _connect(self, mode: str = 'r') -> bool:
|
||||
"""
|
||||
connect to manager
|
||||
|
||||
@@ -70,7 +70,7 @@ class TinyDBManager(BaseManager):
|
||||
|
||||
return True
|
||||
|
||||
def destroy(self):
|
||||
def destroy(self) -> bool:
|
||||
"""
|
||||
Destroy manager
|
||||
|
||||
@@ -81,7 +81,7 @@ class TinyDBManager(BaseManager):
|
||||
self.db.close()
|
||||
return True
|
||||
|
||||
def get_jobs(self, status=None):
|
||||
def get_jobs(self, status: JobStatus = None) -> list:
|
||||
"""
|
||||
Get jobs
|
||||
|
||||
@@ -97,7 +97,7 @@ class TinyDBManager(BaseManager):
|
||||
|
||||
return jobs_list
|
||||
|
||||
def add_job(self, job_metadata):
|
||||
def add_job(self, job_metadata: dict) -> str:
|
||||
"""
|
||||
Add a job
|
||||
|
||||
@@ -112,7 +112,7 @@ class TinyDBManager(BaseManager):
|
||||
|
||||
return doc_id
|
||||
|
||||
def update_job(self, job_id, update_dict):
|
||||
def update_job(self, job_id: str, update_dict: dict) -> bool:
|
||||
"""
|
||||
Updates a job
|
||||
|
||||
@@ -128,7 +128,7 @@ class TinyDBManager(BaseManager):
|
||||
|
||||
return True
|
||||
|
||||
def delete_job(self, job_id):
|
||||
def delete_job(self, job_id: str) -> bool:
|
||||
"""
|
||||
Deletes a job
|
||||
|
||||
@@ -139,9 +139,9 @@ class TinyDBManager(BaseManager):
|
||||
# delete result file if present
|
||||
job_result = self.get_job(job_id)
|
||||
if job_result:
|
||||
location = job_result.get('location', None)
|
||||
location = job_result.get('location')
|
||||
if location and self.output_dir is not None:
|
||||
os.remove(location)
|
||||
Path(location).unlink()
|
||||
|
||||
self._connect(mode='w')
|
||||
removed = bool(self.db.remove(tinydb.where('identifier') == job_id))
|
||||
@@ -149,7 +149,7 @@ class TinyDBManager(BaseManager):
|
||||
|
||||
return removed
|
||||
|
||||
def get_job(self, job_id):
|
||||
def get_job(self, job_id: str) -> dict:
|
||||
"""
|
||||
Get a single job
|
||||
|
||||
@@ -166,7 +166,7 @@ class TinyDBManager(BaseManager):
|
||||
self.db.close()
|
||||
return result
|
||||
|
||||
def get_job_result(self, job_id):
|
||||
def get_job_result(self, job_id: str) -> Tuple[str, Any]:
|
||||
"""
|
||||
Get a job's status, and actual output of executing the process
|
||||
|
||||
@@ -180,8 +180,8 @@ class TinyDBManager(BaseManager):
|
||||
# job does not exist
|
||||
return None
|
||||
|
||||
location = job_result.get('location', None)
|
||||
mimetype = job_result.get('mimetype', None)
|
||||
location = job_result.get('location')
|
||||
mimetype = job_result.get('mimetype')
|
||||
job_status = JobStatus[job_result['status']]
|
||||
|
||||
if not job_status == JobStatus.successful:
|
||||
@@ -191,11 +191,13 @@ class TinyDBManager(BaseManager):
|
||||
# Job data was not written for some reason
|
||||
# TODO log/raise exception?
|
||||
return (None,)
|
||||
else:
|
||||
location = Path(location)
|
||||
|
||||
with io.open(location, 'r', encoding='utf-8') as filehandler:
|
||||
with location.open('r', encoding='utf-8') as filehandler:
|
||||
result = json.load(filehandler)
|
||||
|
||||
return mimetype, result
|
||||
|
||||
def __repr__(self):
|
||||
return '<TinyDBManager> {}'.format(self.name)
|
||||
return f'<TinyDBManager> {self.name}'
|
||||
|
||||
@@ -61,11 +61,11 @@ class BaseProvider:
|
||||
raise RuntimeError('name/type/data are required')
|
||||
|
||||
self.editable = provider_def.get('editable', False)
|
||||
self.options = provider_def.get('options', None)
|
||||
self.id_field = provider_def.get('id_field', None)
|
||||
self.uri_field = provider_def.get('uri_field', None)
|
||||
self.x_field = provider_def.get('x_field', None)
|
||||
self.y_field = provider_def.get('y_field', None)
|
||||
self.options = provider_def.get('options')
|
||||
self.id_field = provider_def.get('id_field')
|
||||
self.uri_field = provider_def.get('uri_field')
|
||||
self.x_field = provider_def.get('x_field')
|
||||
self.y_field = provider_def.get('y_field')
|
||||
self.time_field = provider_def.get('time_field')
|
||||
self.title_field = provider_def.get('title_field')
|
||||
self.properties = provider_def.get('properties', [])
|
||||
@@ -212,7 +212,7 @@ class BaseProvider:
|
||||
msg = None
|
||||
|
||||
LOGGER.debug('Loading data')
|
||||
LOGGER.debug('Data: {}'.format(item))
|
||||
LOGGER.debug(f'Data: {item}')
|
||||
try:
|
||||
json_data = json.loads(item)
|
||||
except TypeError as err:
|
||||
@@ -262,7 +262,7 @@ class BaseProvider:
|
||||
return identifier2, json_data
|
||||
|
||||
def __repr__(self):
|
||||
return '<BaseProvider> {}'.format(self.type)
|
||||
return f'<BaseProvider> {self.type}'
|
||||
|
||||
|
||||
class ProviderGenericError(Exception):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -193,9 +193,9 @@ class CSVProvider(BaseProvider):
|
||||
if item:
|
||||
return item
|
||||
else:
|
||||
err = 'item {} not found'.format(identifier)
|
||||
err = f'item {identifier} not found'
|
||||
LOGGER.error(err)
|
||||
raise ProviderItemNotFoundError(err)
|
||||
|
||||
def __repr__(self):
|
||||
return '<CSVProvider> {}'.format(self.data)
|
||||
return f'<CSVProvider> {self.data}'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
# Copyright (c) 2021 Francesco Bartoli
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
@@ -67,8 +67,8 @@ class ElasticsearchProvider(BaseProvider):
|
||||
LOGGER.debug('Setting Elasticsearch properties')
|
||||
self.is_gdal = False
|
||||
|
||||
LOGGER.debug('host: {}'.format(self.es_host))
|
||||
LOGGER.debug('index: {}'.format(self.index_name))
|
||||
LOGGER.debug(f'host: {self.es_host}')
|
||||
LOGGER.debug(f'index: {self.index_name}')
|
||||
|
||||
self.type_name = 'FeatureCollection'
|
||||
self.url_parsed = urlparse(self.es_host)
|
||||
@@ -94,7 +94,7 @@ class ElasticsearchProvider(BaseProvider):
|
||||
if self.url_parsed.path:
|
||||
url_settings['url_prefix'] = self.url_parsed.path
|
||||
|
||||
LOGGER.debug('URL settings: {}'.format(url_settings))
|
||||
LOGGER.debug(f'URL settings: {url_settings}')
|
||||
LOGGER.debug('Connecting to Elasticsearch')
|
||||
self.es = Elasticsearch([url_settings])
|
||||
if not self.es.ping():
|
||||
@@ -262,14 +262,14 @@ class ElasticsearchProvider(BaseProvider):
|
||||
LOGGER.debug('processing sortby')
|
||||
query['sort'] = []
|
||||
for sort in sortby:
|
||||
LOGGER.debug('processing sort object: {}'.format(sort))
|
||||
LOGGER.debug(f'processing sort object: {sort}')
|
||||
|
||||
sp = sort['property']
|
||||
|
||||
if (self.fields[sp]['type'] == 'string'
|
||||
and self.fields[sp].get('format') != 'date'):
|
||||
LOGGER.debug('setting ES .raw on property')
|
||||
sort_property = '{}.raw'.format(self.mask_prop(sp))
|
||||
sort_property = f'{self.mask_prop(sp)}.raw'
|
||||
else:
|
||||
sort_property = self.mask_prop(sp)
|
||||
|
||||
@@ -318,7 +318,7 @@ class ElasticsearchProvider(BaseProvider):
|
||||
try:
|
||||
LOGGER.debug('querying Elasticsearch')
|
||||
if filterq:
|
||||
LOGGER.debug('adding cql object: {}'.format(filterq.json()))
|
||||
LOGGER.debug(f'adding cql object: {filterq.json()}')
|
||||
query = update_query(input_query=query, cql=filterq)
|
||||
LOGGER.debug(json.dumps(query, indent=4))
|
||||
|
||||
@@ -378,12 +378,12 @@ class ElasticsearchProvider(BaseProvider):
|
||||
"""
|
||||
|
||||
try:
|
||||
LOGGER.debug('Fetching identifier {}'.format(identifier))
|
||||
LOGGER.debug(f'Fetching identifier {identifier}')
|
||||
result = self.es.get(index=self.index_name, id=identifier)
|
||||
LOGGER.debug('Serializing feature')
|
||||
feature_ = self.esdoc2geojson(result)
|
||||
except exceptions.NotFoundError as err:
|
||||
LOGGER.debug('Not found via ES id query: {}'.format(err))
|
||||
LOGGER.debug(f'Not found via ES id query: {err}')
|
||||
LOGGER.debug('Trying via a real query')
|
||||
|
||||
query = {
|
||||
@@ -425,7 +425,7 @@ class ElasticsearchProvider(BaseProvider):
|
||||
|
||||
identifier, json_data = self._load_and_prepare_item(item)
|
||||
|
||||
LOGGER.debug('Inserting data with identifier {}'.format(identifier))
|
||||
LOGGER.debug(f'Inserting data with identifier {identifier}')
|
||||
_ = self.es.index(index=self.index_name, id=identifier, body=json_data)
|
||||
LOGGER.debug('Item added')
|
||||
|
||||
@@ -441,7 +441,7 @@ class ElasticsearchProvider(BaseProvider):
|
||||
:returns: `bool` of update result
|
||||
"""
|
||||
|
||||
LOGGER.debug('Updating item {}'.format(identifier))
|
||||
LOGGER.debug(f'Updating item {identifier}')
|
||||
identifier, json_data = self._load_and_prepare_item(
|
||||
item, identifier, raise_if_exists=False)
|
||||
|
||||
@@ -458,7 +458,7 @@ class ElasticsearchProvider(BaseProvider):
|
||||
:returns: `bool` of deletion result
|
||||
"""
|
||||
|
||||
LOGGER.debug('Deleting item {}'.format(identifier))
|
||||
LOGGER.debug(f'Deleting item {identifier}')
|
||||
_ = self.es.delete(index=self.index_name, id=identifier)
|
||||
|
||||
return True
|
||||
@@ -528,13 +528,13 @@ class ElasticsearchProvider(BaseProvider):
|
||||
if self.is_gdal:
|
||||
return property_name
|
||||
else:
|
||||
return 'properties.{}'.format(property_name)
|
||||
return f'properties.{property_name}'
|
||||
|
||||
def get_properties(self):
|
||||
all_properties = []
|
||||
|
||||
LOGGER.debug('configured properties: {}'.format(self.properties))
|
||||
LOGGER.debug('selected properties: {}'.format(self.select_properties))
|
||||
LOGGER.debug(f'configured properties: {self.properties}')
|
||||
LOGGER.debug(f'selected properties: {self.select_properties}')
|
||||
|
||||
if not self.properties and not self.select_properties:
|
||||
all_properties = self.get_fields()
|
||||
@@ -543,11 +543,11 @@ class ElasticsearchProvider(BaseProvider):
|
||||
else:
|
||||
all_properties = set(self.properties) | set(self.select_properties)
|
||||
|
||||
LOGGER.debug('resulting properties: {}'.format(all_properties))
|
||||
LOGGER.debug(f'resulting properties: {all_properties}')
|
||||
return all_properties
|
||||
|
||||
def __repr__(self):
|
||||
return '<ElasticsearchProvider> {}'.format(self.data)
|
||||
return f'<ElasticsearchProvider> {self.data}'
|
||||
|
||||
|
||||
class ElasticsearchCatalogueProvider(ElasticsearchProvider):
|
||||
@@ -588,7 +588,7 @@ class ElasticsearchCatalogueProvider(ElasticsearchProvider):
|
||||
return records
|
||||
|
||||
def __repr__(self):
|
||||
return '<ElasticsearchCatalogueProvider> {}'.format(self.data)
|
||||
return f'<ElasticsearchCatalogueProvider> {self.data}'
|
||||
|
||||
|
||||
class ESQueryBuilder:
|
||||
@@ -769,7 +769,5 @@ def update_query(input_query: Dict, cql: CQLModel):
|
||||
output_query = _build_query(query, cql)
|
||||
s = s.query(output_query)
|
||||
|
||||
LOGGER.debug('Enhanced query: {}'.format(
|
||||
json.dumps(s.to_dict())
|
||||
))
|
||||
LOGGER.debug(f'Enhanced query: {json.dumps(s.to_dict())}')
|
||||
return s.to_dict()
|
||||
|
||||
@@ -82,7 +82,7 @@ class ESRIServiceProvider(BaseProvider):
|
||||
resp = self.get_response(self.data, params=params)
|
||||
|
||||
if resp.get('error') is not None:
|
||||
msg = 'Connection error: {}'.format(resp['error']['message'])
|
||||
msg = f"Connection error: {resp['error']['message']}"
|
||||
LOGGER.error(msg)
|
||||
raise ProviderConnectionError(msg)
|
||||
|
||||
@@ -283,9 +283,8 @@ class ESRIServiceProvider(BaseProvider):
|
||||
if datetime_ is not None:
|
||||
|
||||
def esri_dt(dt):
|
||||
return "TIMESTAMP '{}'".format(
|
||||
format_datetime(dt, '%Y-%m-%d %H:%M:%S')
|
||||
)
|
||||
dt_ = format_datetime(dt, '%Y-%m-%d %H:%M:%S')
|
||||
return f"TIMESTAMP '{dt_}'"
|
||||
|
||||
tf = self.time_field
|
||||
if '/' in datetime_:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2020 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -56,7 +56,7 @@ class FileSystemProvider(BaseProvider):
|
||||
super().__init__(provider_def)
|
||||
|
||||
if not os.path.exists(self.data):
|
||||
msg = 'Directory does not exist: {}'.format(self.data)
|
||||
msg = f'Directory does not exist: {self.data}'
|
||||
LOGGER.error(msg)
|
||||
raise ProviderConnectionError(msg)
|
||||
|
||||
@@ -86,7 +86,7 @@ class FileSystemProvider(BaseProvider):
|
||||
parentpath = urljoin(thispath, '.')
|
||||
child_links.append({
|
||||
'rel': 'parent',
|
||||
'href': '{}?f=json'.format(parentpath),
|
||||
'href': f'{parentpath}?f=json',
|
||||
'type': 'application/json'
|
||||
})
|
||||
child_links.append({
|
||||
@@ -102,7 +102,7 @@ class FileSystemProvider(BaseProvider):
|
||||
content = {
|
||||
'links': [{
|
||||
'rel': 'root',
|
||||
'href': '{}?f=json'.format(root_link),
|
||||
'href': f'{root_link}?f=json',
|
||||
'type': 'application/json'
|
||||
}, {
|
||||
'rel': 'root',
|
||||
@@ -110,7 +110,7 @@ class FileSystemProvider(BaseProvider):
|
||||
'type': 'text/html'
|
||||
}, {
|
||||
'rel': 'self',
|
||||
'href': '{}?f=json'.format(thispath),
|
||||
'href': f'{thispath}?f=json',
|
||||
'type': 'application/json',
|
||||
}, {
|
||||
'rel': 'self',
|
||||
@@ -128,14 +128,14 @@ class FileSystemProvider(BaseProvider):
|
||||
else:
|
||||
LOGGER.debug('Checking if path exists as file via file_types')
|
||||
for ft in self.file_types:
|
||||
tmp_path = '{}{}'.format(data_path, ft)
|
||||
tmp_path = f'{data_path}{ft}'
|
||||
if os.path.exists(tmp_path):
|
||||
resource_type = 'file'
|
||||
data_path = tmp_path
|
||||
break
|
||||
|
||||
if resource_type is None:
|
||||
msg = 'Resource does not exist: {}'.format(data_path)
|
||||
msg = f'Resource does not exist: {data_path}'
|
||||
LOGGER.error(msg)
|
||||
raise ProviderNotFoundError(msg)
|
||||
|
||||
@@ -158,11 +158,6 @@ class FileSystemProvider(BaseProvider):
|
||||
|
||||
if os.path.isdir(fullpath):
|
||||
newpath = os.path.join(baseurl, urlpath, dc)
|
||||
# child_links.append({
|
||||
# 'rel': 'child',
|
||||
# 'href': '{}?f=json'.format(newpath),
|
||||
# 'type': 'application/json'
|
||||
# })
|
||||
child_links.append({
|
||||
'rel': 'child',
|
||||
'href': newpath,
|
||||
@@ -173,7 +168,7 @@ class FileSystemProvider(BaseProvider):
|
||||
elif os.path.isfile(fullpath):
|
||||
basename, extension = os.path.splitext(dc)
|
||||
newpath = os.path.join(baseurl, urlpath, basename)
|
||||
newpath2 = '{}{}'.format(newpath, extension)
|
||||
newpath2 = f'{newpath}{extension}'
|
||||
if extension in self.file_types:
|
||||
fullpath = os.path.join(data_path, dc)
|
||||
child_links.append({
|
||||
@@ -184,14 +179,6 @@ class FileSystemProvider(BaseProvider):
|
||||
'file:size': filesize,
|
||||
'entry:type': 'Item'
|
||||
})
|
||||
# child_links.append({
|
||||
# 'rel': 'item',
|
||||
# 'title': get_path_basename(newpath2),
|
||||
# 'href': newpath,
|
||||
# 'type': 'text/html',
|
||||
# 'created': filectime,
|
||||
# 'file:size': filesize
|
||||
# })
|
||||
|
||||
elif resource_type == 'file':
|
||||
filename = os.path.basename(data_path)
|
||||
@@ -199,7 +186,7 @@ class FileSystemProvider(BaseProvider):
|
||||
id_ = os.path.splitext(filename)[0]
|
||||
if urlpath:
|
||||
filename = filename.replace(id_, '')
|
||||
url = '{}/{}{}'.format(baseurl, urlpath, filename)
|
||||
url = f'{baseurl}/{urlpath}{filename}'
|
||||
|
||||
filectime = file_modified_iso8601(data_path)
|
||||
filesize = os.path.getsize(data_path)
|
||||
@@ -225,7 +212,7 @@ class FileSystemProvider(BaseProvider):
|
||||
return content
|
||||
|
||||
def __repr__(self):
|
||||
return '<FileSystemProvider> {}'.format(self.data)
|
||||
return f'<FileSystemProvider> {self.data}'
|
||||
|
||||
|
||||
def _describe_file(filepath):
|
||||
@@ -245,7 +232,7 @@ def _describe_file(filepath):
|
||||
'properties': {}
|
||||
}
|
||||
|
||||
mcf_file = '{}.yml'.format(os.path.splitext(filepath)[0])
|
||||
mcf_file = f'{os.path.splitext(filepath)[0]}.yml'
|
||||
|
||||
if os.path.isfile(mcf_file):
|
||||
try:
|
||||
@@ -260,9 +247,9 @@ def _describe_file(filepath):
|
||||
except ImportError:
|
||||
LOGGER.debug('pygeometa not found')
|
||||
except MCFReadError as err:
|
||||
LOGGER.warning('MCF error: {}'.format(err))
|
||||
LOGGER.warning(f'MCF error: {err}')
|
||||
else:
|
||||
LOGGER.debug('No mcf found at: {}'.format(mcf_file))
|
||||
LOGGER.debug(f'No mcf found at: {mcf_file}')
|
||||
|
||||
if content['geometry'] is None and content['bbox'] is None:
|
||||
try:
|
||||
@@ -350,15 +337,14 @@ def _describe_file(filepath):
|
||||
id_ = os.path.splitext(os.path.basename(filepath))[0]
|
||||
content['assets'] = {}
|
||||
for suffix in ['shx', 'dbf', 'prj']:
|
||||
fullpath = '{}.{}'.format(
|
||||
os.path.splitext(filepath)[0], suffix)
|
||||
fullpath = f'{os.path.splitext(filepath)[0]}.{suffix}'
|
||||
|
||||
if os.path.exists(fullpath):
|
||||
filectime = file_modified_iso8601(fullpath)
|
||||
filesize = os.path.getsize(fullpath)
|
||||
|
||||
content['assets'][suffix] = {
|
||||
'href': './{}.{}'.format(id_, suffix),
|
||||
'href': f'./{id_}.{suffix}',
|
||||
'created': filectime,
|
||||
'file:size': filesize
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Authors: Matthew Perry <perrygeo@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2018 Matthew Perry
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -84,7 +84,7 @@ class GeoJSONProvider(BaseProvider):
|
||||
for f in data['features'][0]['properties'].keys():
|
||||
fields[f] = {'type': 'string'}
|
||||
else:
|
||||
LOGGER.warning('File {} does not exist.'.format(self.data))
|
||||
LOGGER.warning(f'File {self.data} does not exist.')
|
||||
return fields
|
||||
|
||||
def _load(self, skip_geometry=None, properties=[], select_properties=[]):
|
||||
@@ -99,7 +99,7 @@ class GeoJSONProvider(BaseProvider):
|
||||
with open(self.data) as src:
|
||||
data = json.loads(src.read())
|
||||
else:
|
||||
LOGGER.warning('File {} does not exist.'.format(self.data))
|
||||
LOGGER.warning(f'File {self.data} does not exist.')
|
||||
data = {
|
||||
'type': 'FeatureCollection',
|
||||
'features': []}
|
||||
@@ -171,7 +171,7 @@ class GeoJSONProvider(BaseProvider):
|
||||
if str(feature.get('id')) == identifier:
|
||||
return feature
|
||||
# default, no match
|
||||
err = 'item {} not found'.format(identifier)
|
||||
err = f'item {identifier} not found'
|
||||
LOGGER.error(err)
|
||||
raise ProviderItemNotFoundError(err)
|
||||
|
||||
@@ -230,4 +230,4 @@ class GeoJSONProvider(BaseProvider):
|
||||
dst.write(json.dumps(all_data))
|
||||
|
||||
def __repr__(self):
|
||||
return '<GeoJSONProvider> {}'.format(self.data)
|
||||
return f'<GeoJSONProvider> {self.data}'
|
||||
|
||||
@@ -77,7 +77,7 @@ class HateoasProvider(BaseProvider):
|
||||
parentpath = urljoin(thispath, '.')
|
||||
child_links.append({
|
||||
'rel': 'parent',
|
||||
'href': '{}?f=json'.format(parentpath),
|
||||
'href': f'{parentpath}?f=json',
|
||||
'type': 'application/json'
|
||||
})
|
||||
child_links.append({
|
||||
@@ -93,7 +93,7 @@ class HateoasProvider(BaseProvider):
|
||||
content = {
|
||||
'links': [{
|
||||
'rel': 'root',
|
||||
'href': '{}?f=json'.format(root_link),
|
||||
'href': f'{root_link}?f=json',
|
||||
'type': 'application/json'
|
||||
}, {
|
||||
'rel': 'root',
|
||||
@@ -101,7 +101,7 @@ class HateoasProvider(BaseProvider):
|
||||
'type': 'text/html'
|
||||
}, {
|
||||
'rel': 'self',
|
||||
'href': '{}?f=json'.format(thispath),
|
||||
'href': f'{thispath}?f=json',
|
||||
'type': 'application/json',
|
||||
}, {
|
||||
'rel': 'self',
|
||||
@@ -113,19 +113,19 @@ class HateoasProvider(BaseProvider):
|
||||
|
||||
LOGGER.debug('Checking if path exists as Catalog, Collection or Asset')
|
||||
try:
|
||||
jsondata = _get_json_data('{}/catalog.json'.format(data_path))
|
||||
jsondata = _get_json_data(f'{data_path}/catalog.json')
|
||||
resource_type = 'Catalog'
|
||||
except Exception:
|
||||
try:
|
||||
jsondata = _get_json_data('{}/collection.json'.format(data_path)) # noqa
|
||||
jsondata = _get_json_data(f'{data_path}/collection.json')
|
||||
resource_type = 'Collection'
|
||||
except Exception:
|
||||
try:
|
||||
filename = os.path.basename(data_path)
|
||||
jsondata = _get_json_data('{}/{}.json'.format(data_path, filename)) # noqa
|
||||
jsondata = _get_json_data(f'{data_path}/{filename}.json')
|
||||
resource_type = 'Assets'
|
||||
except Exception:
|
||||
msg = 'Resource does not exist: {}'.format(data_path)
|
||||
msg = f'Resource does not exist: {data_path}'
|
||||
LOGGER.error(msg)
|
||||
raise ProviderNotFoundError(msg)
|
||||
|
||||
@@ -183,7 +183,7 @@ class HateoasProvider(BaseProvider):
|
||||
return content
|
||||
|
||||
def __repr__(self):
|
||||
return '<HateoasProvider> {}'.format(self.data)
|
||||
return f'<HateoasProvider> {self.data}'
|
||||
|
||||
|
||||
def _get_json_data(jsonpath):
|
||||
|
||||
@@ -64,7 +64,7 @@ class MapScriptProvider(BaseProvider):
|
||||
self.styles = []
|
||||
self.default_format = 'png'
|
||||
|
||||
LOGGER.debug('MapScript version: {}'.format(mapscript.MS_VERSION))
|
||||
LOGGER.debug(f'MapScript version: {mapscript.MS_VERSION}')
|
||||
|
||||
try:
|
||||
LOGGER.debug('Creating new mapObj and layerObj')
|
||||
@@ -91,7 +91,7 @@ class MapScriptProvider(BaseProvider):
|
||||
|
||||
self._layer.setProjection(self._epsg2projstring(self.crs))
|
||||
|
||||
LOGGER.debug('Layer projection: {}'.format(self._layer.getProjection())) # noqa
|
||||
LOGGER.debug(f'Layer projection: {self._layer.getProjection()}')
|
||||
|
||||
if 'style' in self.options:
|
||||
if self.options['style'].endswith(('xml', 'sld')):
|
||||
@@ -135,7 +135,7 @@ class MapScriptProvider(BaseProvider):
|
||||
try:
|
||||
image_obj_format = IMAGE_FORMATS[format_]
|
||||
except KeyError:
|
||||
LOGGER.error('Bad output format: {}'.format(image_obj_format))
|
||||
LOGGER.error(f'Bad output format: {image_obj_format}')
|
||||
raise ProviderQueryError('Bad image format')
|
||||
|
||||
LOGGER.debug('Setting output map CRS')
|
||||
@@ -167,8 +167,8 @@ class MapScriptProvider(BaseProvider):
|
||||
if self.time_field is None:
|
||||
LOGGER.debug('collection is not time enabled')
|
||||
else:
|
||||
fe = '{} = "{}"'.format(self.time_field, datetime_)
|
||||
LOGGER.debug('Setting temporal filter: {}'.format(fe))
|
||||
fe = f'{self.time_field} = "{datetime_}"'
|
||||
LOGGER.debug(f'Setting temporal filter: {fe}')
|
||||
self._layer.setFilter(fe)
|
||||
|
||||
LOGGER.debug('Setting output image properties')
|
||||
@@ -185,7 +185,7 @@ class MapScriptProvider(BaseProvider):
|
||||
self._map.setProjection(map_crs)
|
||||
self._map.setConfigOption('MS_NONSQUARE', 'yes')
|
||||
|
||||
LOGGER.debug('Mapfile: {}'.format(self._map.convertToString()))
|
||||
LOGGER.debug(f'Mapfile: {self._map.convertToString()}')
|
||||
try:
|
||||
img = self._map.draw()
|
||||
except MapServerError as err:
|
||||
@@ -209,4 +209,4 @@ class MapScriptProvider(BaseProvider):
|
||||
return prj.ExportToProj4().strip()
|
||||
|
||||
def __repr__(self):
|
||||
return '<MapScriptProvider> {}'.format(self.data)
|
||||
return f'<MapScriptProvider> {self.data}'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Authors: Timo Tuunanen <timo.tuunanen@rdvelho.com>
|
||||
#
|
||||
# Copyright (c) 2019 Timo Tuunanen
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -60,7 +60,7 @@ class MongoProvider(BaseProvider):
|
||||
|
||||
super().__init__(provider_def)
|
||||
|
||||
LOGGER.info('Mongo source config: {}'.format(self.data))
|
||||
LOGGER.info(f'Mongo source config: {self.data}')
|
||||
|
||||
dbclient = MongoClient(self.data)
|
||||
self.featuredb = dbclient.get_default_database()
|
||||
@@ -167,7 +167,7 @@ class MongoProvider(BaseProvider):
|
||||
if featurelist:
|
||||
return featurelist[0]
|
||||
else:
|
||||
err = 'item {} not found'.format(identifier)
|
||||
err = f'item {identifier} not found'
|
||||
LOGGER.error(err)
|
||||
raise ProviderItemNotFoundError(err)
|
||||
|
||||
|
||||
+38
-63
@@ -1,8 +1,10 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Francesco Bartoli <xbartolone@gmail.com>
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2020 Francesco Bartoli
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -60,23 +62,15 @@ class MVTProvider(BaseTileProvider):
|
||||
super().__init__(provider_def)
|
||||
if is_url(self.data):
|
||||
url = urlparse(self.data)
|
||||
baseurl = '{}://{}'.format(url.scheme, url.netloc)
|
||||
baseurl = f'{url.scheme}://{url.netloc}'
|
||||
param_type = '?f=mvt'
|
||||
layer = '/{}'.format(self.get_layer())
|
||||
layer = f'/{self.get_layer()}'
|
||||
|
||||
LOGGER.debug('Extracting layer name from URL')
|
||||
LOGGER.debug('Layer: {}'.format(layer))
|
||||
LOGGER.debug(f'Layer: {layer}')
|
||||
|
||||
tilepath = '{}/tiles'.format(layer)
|
||||
servicepath = \
|
||||
'{}/{{{}}}/{{{}}}/{{{}}}/{{{}}}{}'.format(
|
||||
tilepath,
|
||||
'tileMatrixSetId',
|
||||
'tileMatrix',
|
||||
'tileRow',
|
||||
'tileCol',
|
||||
param_type
|
||||
)
|
||||
tilepath = f'{layer}/tiles'
|
||||
servicepath = f'{tilepath}/{{tileMatrixSetId}}/{{tileMatrix}}/{{tileRow}}/{{tileCol}}{param_type}' # noqa
|
||||
|
||||
self._service_url = url_join(baseurl, servicepath)
|
||||
|
||||
@@ -86,19 +80,19 @@ class MVTProvider(BaseTileProvider):
|
||||
else:
|
||||
data_path = Path(self.data)
|
||||
if not data_path.exists():
|
||||
msg = 'Service does not exist: {}'.format(self.data)
|
||||
msg = f'Service does not exist: {self.data}'
|
||||
LOGGER.error(msg)
|
||||
raise ProviderConnectionError(msg)
|
||||
self._service_url = data_path
|
||||
metadata_path = data_path.joinpath('metadata.json')
|
||||
if not metadata_path.exists():
|
||||
msg = 'Service metadata does not exist: {}'.format(
|
||||
metadata_path.name)
|
||||
msg = f'Service metadata does not exist: {metadata_path.name}'
|
||||
LOGGER.error(msg)
|
||||
LOGGER.warning(msg)
|
||||
self._service_metadata_url = metadata_path
|
||||
|
||||
def __repr__(self):
|
||||
return '<MVTProvider> {}'.format(self.data)
|
||||
return f'<MVTProvider> {self.data}'
|
||||
|
||||
@property
|
||||
def service_url(self):
|
||||
@@ -117,8 +111,7 @@ class MVTProvider(BaseTileProvider):
|
||||
|
||||
if ('/{z}/{x}/{y}' not in url.path and
|
||||
'/{z}/{y}/{x}' not in url.path):
|
||||
msg = 'This url template is not supported yet: {}'.format(
|
||||
url.path)
|
||||
msg = f'This url template is not supported yet: {url.path}'
|
||||
LOGGER.error(msg)
|
||||
raise ProviderConnectionError(msg)
|
||||
|
||||
@@ -158,18 +151,11 @@ class MVTProvider(BaseTileProvider):
|
||||
"""
|
||||
|
||||
url = urlparse(self.data)
|
||||
baseurl = baseurl or '{}://{}'.format(url.scheme, url.netloc)
|
||||
baseurl = baseurl or f'{url.scheme}://{url.netloc}'
|
||||
# @TODO: support multiple types
|
||||
tile_type = tile_type or self.format_type
|
||||
servicepath = \
|
||||
servicepath or \
|
||||
'{}/tiles/{{{}}}/{{{}}}/{{{}}}/{{{}}}{}'.format(
|
||||
url.path.split('/{z}/{x}/{y}')[0],
|
||||
'tileMatrixSetId',
|
||||
'tileMatrix',
|
||||
'tileRow',
|
||||
'tileCol',
|
||||
tile_type)
|
||||
basepath = url.path.split('/{z}/{x}/{y}')[0]
|
||||
servicepath = servicepath or f'{basepath}/tiles/{{tileMatrixSetId}}/{{tileMatrix}}/{{tileRow}}/{{tileCol}}{tile_type}' # noqa
|
||||
|
||||
if servicepath.startswith(baseurl):
|
||||
self._service_url = servicepath
|
||||
@@ -185,18 +171,18 @@ class MVTProvider(BaseTileProvider):
|
||||
'type': 'application/json',
|
||||
'rel': 'self',
|
||||
'title': 'This collection as multi vector tilesets',
|
||||
'href': '{}?f=json'.format(tile_matrix_set),
|
||||
'href': f'{tile_matrix_set}?f=json'
|
||||
},
|
||||
{
|
||||
'type': self.mimetype,
|
||||
'rel': 'item',
|
||||
'title': 'This collection as multi vector tiles',
|
||||
'href': self.service_url,
|
||||
'href': self.service_url
|
||||
}, {
|
||||
'type': 'application/json',
|
||||
'rel': 'describedby',
|
||||
'title': 'Collection metadata in TileJSON format',
|
||||
'href': '{}?f=json'.format(self.service_metadata_url),
|
||||
'href': f'{self.service_metadata_url}?f=json'
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -220,36 +206,32 @@ class MVTProvider(BaseTileProvider):
|
||||
format_ = self.format_type
|
||||
if is_url(self.data):
|
||||
url = urlparse(self.data)
|
||||
base_url = '{}://{}'.format(url.scheme, url.netloc)
|
||||
base_url = f'{url.scheme}://{url.netloc}'
|
||||
|
||||
if url.query:
|
||||
url_query = f'?{url.query}'
|
||||
else:
|
||||
url_query = ''
|
||||
|
||||
with requests.Session() as session:
|
||||
session.get(base_url)
|
||||
# There is a "." in the url path
|
||||
if '.' in url.path:
|
||||
resp = session.get(
|
||||
'{base_url}/{lyr}/{z}/{y}/{x}.{f}{q}'.format(
|
||||
base_url=base_url, lyr=layer,
|
||||
z=z, y=y, x=x, f=format_, q="?" + url.query
|
||||
if url.query else ''))
|
||||
resp = session.get(f'{base_url}/{layer}/{z}/{y}/{x}.{f}{url_query}') # noqa
|
||||
# There is no "." in the url )e.g. elasticsearch)
|
||||
else:
|
||||
resp = session.get(
|
||||
'{base_url}/{lyr}/{z}/{y}/{x}{q}'.format(
|
||||
base_url=base_url, lyr=layer,
|
||||
z=z, y=y, x=x, q="?" + url.query
|
||||
if url.query else ''))
|
||||
resp = session.get(f'{base_url}/{layer}/{z}/{y}/{x}{url_query}') # noqa
|
||||
resp.raise_for_status()
|
||||
return resp.content
|
||||
else:
|
||||
if not isinstance(self.service_url, Path):
|
||||
msg = 'Wrong data path configuration: {}'.format(
|
||||
self.service_url)
|
||||
msg = f'Wrong data path configuration: {self.service_url}'
|
||||
LOGGER.error(msg)
|
||||
raise ProviderConnectionError(msg)
|
||||
else:
|
||||
try:
|
||||
with open(self.service_url.joinpath(
|
||||
'{z}/{y}/{x}.{f}'.format(
|
||||
z=z, y=y, x=x, f=format_)), 'rb') as tile:
|
||||
service_url_path = self.service_url.joinpath(f'{z}/{y}/{x}.{format_}') # noqa
|
||||
with open(service_url_path) as tile:
|
||||
return tile.read()
|
||||
except FileNotFoundError as err:
|
||||
raise ProviderTileNotFoundError(err)
|
||||
@@ -272,28 +254,25 @@ class MVTProvider(BaseTileProvider):
|
||||
|
||||
if is_url(self.data):
|
||||
url = urlparse(self.data)
|
||||
base_url = '{}://{}'.format(url.scheme, url.netloc)
|
||||
base_url = f'{url.scheme}://{url.netloc}'
|
||||
with requests.Session() as session:
|
||||
session.get(base_url)
|
||||
resp = session.get('{base_url}/{lyr}/metadata.json'.format(
|
||||
base_url=base_url, lyr=layer))
|
||||
resp = session.get(f'{base_url}/{layer}/metadata.json')
|
||||
resp.raise_for_status()
|
||||
metadata_json_content = resp.json()
|
||||
else:
|
||||
if not isinstance(self.service_metadata_url, Path):
|
||||
msg = 'Wrong data path configuration: {}'.format(
|
||||
self.service_metadata_url)
|
||||
msg = f'Wrong data path configuration: {self.service_metadata_url}' # noqa
|
||||
LOGGER.error(msg)
|
||||
raise ProviderConnectionError(msg)
|
||||
|
||||
if self.service_metadata_url.exists():
|
||||
with open(self.service_metadata_url, 'r') as md_file:
|
||||
metadata_json_content = json.loads(md_file.read())
|
||||
|
||||
service_url = urljoin(
|
||||
server_url,
|
||||
'collections/{}/tiles/{}/{{{}}}/{{{}}}/{{{}}}{}'.format(
|
||||
dataset, tileset, 'tileMatrix',
|
||||
'tileRow', 'tileCol', '?f=mvt'))
|
||||
f'collections/{dataset}/tiles/{tileset}/{{tileMatrix}}/{{tileRow}}/{{tileCol}}?f=mvt') # noqa
|
||||
|
||||
content = {}
|
||||
if metadata_format == TilesMetadataFormat.TILEJSON:
|
||||
@@ -304,8 +283,7 @@ class MVTProvider(BaseTileProvider):
|
||||
metadata_json_content["json"])["vector_layers"]
|
||||
return content.dict()
|
||||
else:
|
||||
msg = 'No tiles metadata json available: {}'.format(
|
||||
self.service_metadata_url)
|
||||
msg = f'No tiles metadata json available: {self.service_metadata_url}' # noqa
|
||||
LOGGER.error(msg)
|
||||
raise ProviderConnectionError(msg)
|
||||
elif metadata_format == TilesMetadataFormat.CUSTOMJSON:
|
||||
@@ -315,8 +293,7 @@ class MVTProvider(BaseTileProvider):
|
||||
content['json'] = json.loads(metadata_json_content['json'])
|
||||
return content
|
||||
else:
|
||||
msg = 'No custom JSON for tiles metadata available: {}'.format(
|
||||
self.service_metadata_url)
|
||||
msg = f'No custom JSON for tiles metadata available: {self.service_metadata_url}' # noqa
|
||||
LOGGER.error(msg)
|
||||
raise ProviderConnectionError(msg)
|
||||
else:
|
||||
@@ -336,9 +313,7 @@ class MVTProvider(BaseTileProvider):
|
||||
|
||||
links = []
|
||||
service_url_link_type = "application/vnd.mapbox-vector-tile"
|
||||
service_url_link_title = "{} vector tiles for {}".format(
|
||||
tileset, layer
|
||||
)
|
||||
service_url_link_title = f'{tileset} vector tiles for {layer}'
|
||||
service_url_link = LinkType(href=service_url, rel="item",
|
||||
type=service_url_link_type,
|
||||
title=service_url_link_title)
|
||||
|
||||
+23
-46
@@ -5,7 +5,7 @@
|
||||
#
|
||||
# Copyright (c) 2019 Just van den Broecke
|
||||
# Copyright (c) 2020 Francesco Bartoli
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -172,7 +172,7 @@ class OGRProvider(BaseProvider):
|
||||
self._load_source_helper(self.data_def['source_type'])
|
||||
|
||||
# Layer name is required
|
||||
self.layer_name = provider_def.get('layer', None)
|
||||
self.layer_name = provider_def.get('layer')
|
||||
if not self.layer_name:
|
||||
msg = 'Need explicit \'layer\' attr in provider config'
|
||||
LOGGER.error(msg)
|
||||
@@ -193,7 +193,7 @@ class OGRProvider(BaseProvider):
|
||||
source_type = self.data_def['source_type']
|
||||
self.driver = self.ogr.GetDriverByName(source_type)
|
||||
if not self.driver:
|
||||
msg = 'No Driver for Source: {}'.format(source_type)
|
||||
msg = f'No Driver for Source: {source_type}'
|
||||
LOGGER.error(msg)
|
||||
raise Exception(msg)
|
||||
if self.open_options:
|
||||
@@ -206,8 +206,7 @@ class OGRProvider(BaseProvider):
|
||||
LOGGER.error(err)
|
||||
raise ProviderConnectionError(err)
|
||||
except Exception:
|
||||
msg = 'Ignore errors during the connection for Driver \
|
||||
{}'.format(source_type)
|
||||
msg = f'Ignore errors during the connection for Driver {source_type}' # noqa
|
||||
LOGGER.error(msg)
|
||||
self.conn = _ignore_gdal_error(
|
||||
self.gdal, 'OpenEx', self.data_def['source'],
|
||||
@@ -220,8 +219,7 @@ class OGRProvider(BaseProvider):
|
||||
LOGGER.error(err)
|
||||
raise ProviderConnectionError(err)
|
||||
except Exception:
|
||||
msg = 'Ignore errors during the connection for Driver \
|
||||
{}'.format(source_type)
|
||||
msg = f'Ignore errors during the connection for Driver {source_type}' # noqa
|
||||
LOGGER.error(msg)
|
||||
# ignore errors for ESRIJSON not having geometry member
|
||||
# see https://github.com/OSGeo/gdal/commit/38b0feed67f80ded32be6c508323d862e1a14474 # noqa
|
||||
@@ -323,12 +321,10 @@ class OGRProvider(BaseProvider):
|
||||
|
||||
if bbox:
|
||||
LOGGER.debug('processing bbox parameter')
|
||||
minx, miny, maxx, maxy = bbox
|
||||
minx, miny, maxx, maxy = [float(b) for b in bbox]
|
||||
|
||||
wkt = "POLYGON (({minx} {miny},{minx} {maxy},{maxx} {maxy}," \
|
||||
"{maxx} {miny},{minx} {miny}))".format(
|
||||
minx=float(minx), miny=float(miny),
|
||||
maxx=float(maxx), maxy=float(maxy))
|
||||
wkt = f"POLYGON (({minx} {miny},{minx} {maxy},{maxx} {maxy}," \
|
||||
"{maxx} {miny},{minx} {miny}))"
|
||||
|
||||
polygon = self.ogr.CreateGeometryFromWkt(wkt)
|
||||
if self.transform_in:
|
||||
@@ -343,10 +339,7 @@ class OGRProvider(BaseProvider):
|
||||
LOGGER.debug('processing properties')
|
||||
|
||||
attribute_filter = ' and '.join(
|
||||
map(
|
||||
lambda x: '{} = \'{}\''.format(x[0], x[1]),
|
||||
properties
|
||||
)
|
||||
map(lambda x: f'{x[0]} = \'{x[1]}\'', properties)
|
||||
)
|
||||
|
||||
LOGGER.debug(attribute_filter)
|
||||
@@ -389,11 +382,10 @@ class OGRProvider(BaseProvider):
|
||||
"""
|
||||
result = None
|
||||
try:
|
||||
LOGGER.debug('Fetching identifier {}'.format(identifier))
|
||||
LOGGER.debug(f'Fetching identifier {identifier}')
|
||||
layer = self._get_layer()
|
||||
|
||||
layer.SetAttributeFilter("{field} = '{id}'".format(
|
||||
field=self.id_field, id=identifier))
|
||||
layer.SetAttributeFilter(f"{self.id_field} = '{identifier}'")
|
||||
|
||||
ogr_feature = self._get_next_feature(layer, identifier)
|
||||
result = self._ogr_feature_to_json(ogr_feature)
|
||||
@@ -417,7 +409,7 @@ class OGRProvider(BaseProvider):
|
||||
return result
|
||||
|
||||
def __repr__(self):
|
||||
return '<OGRProvider> {}'.format(self.data)
|
||||
return f'<OGRProvider> {self.data}'
|
||||
|
||||
def _load_source_helper(self, source_type):
|
||||
"""
|
||||
@@ -442,9 +434,9 @@ class OGRProvider(BaseProvider):
|
||||
def _get_next_feature(self, layer, feature_id):
|
||||
try:
|
||||
if layer.GetFeatureCount() == 0:
|
||||
LOGGER.error("item {} is not found".format(feature_id))
|
||||
raise ProviderItemNotFoundError(
|
||||
"item {} not found".format(feature_id))
|
||||
msg = f"item {feature_id} is not found"
|
||||
LOGGER.error(msg)
|
||||
raise ProviderItemNotFoundError(msg)
|
||||
# Ignore gdal error
|
||||
next_feature = _ignore_gdal_error(layer, 'GetNextFeature')
|
||||
if next_feature:
|
||||
@@ -455,8 +447,7 @@ class OGRProvider(BaseProvider):
|
||||
)
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"GDAL has returned a null feature for item {}".format(
|
||||
feature_id))
|
||||
f"GDAL has returned a null feature for item {feature_id}")
|
||||
return next_feature
|
||||
except RuntimeError as gdalerr:
|
||||
LOGGER.error(self.gdal.GetLastErrorMsg())
|
||||
@@ -476,11 +467,7 @@ class OGRProvider(BaseProvider):
|
||||
self.id_field, json_feature['id']
|
||||
)
|
||||
except KeyError as err:
|
||||
LOGGER.error(
|
||||
"Cannot use configured id_field nor fid as id, err={}".format(
|
||||
err
|
||||
)
|
||||
)
|
||||
LOGGER.error(f"Cannot use configured id_field nor fid as id, err={err}") # noqa
|
||||
|
||||
return json_feature
|
||||
|
||||
@@ -578,8 +565,7 @@ class SourceHelper:
|
||||
layer = self.provider.conn.GetLayerByName(self.provider.layer_name)
|
||||
|
||||
if not layer:
|
||||
msg = 'Cannot get Layer {} from OGR Source'.\
|
||||
format(self.provider.layer_name)
|
||||
msg = f'Cannot get Layer {self.provider.layer_name} from OGR Source' # noqa
|
||||
LOGGER.error(msg)
|
||||
raise Exception(msg)
|
||||
|
||||
@@ -635,8 +621,7 @@ class CommonSourceHelper(SourceHelper):
|
||||
try:
|
||||
self.provider.conn.ReleaseResultSet(self.result_set)
|
||||
except Exception as err:
|
||||
msg = 'ReleaseResultSet exception for Layer {}'.format(
|
||||
self.provider.layer_name)
|
||||
msg = f'ReleaseResultSet exception for Layer {self.provider.layer_name}' # noqa
|
||||
LOGGER.error(msg, err)
|
||||
finally:
|
||||
self.result_set = None
|
||||
@@ -671,10 +656,7 @@ class CommonSourceHelper(SourceHelper):
|
||||
|
||||
self.close()
|
||||
|
||||
sql = 'SELECT * FROM "{ds_name}" LIMIT {limit} OFFSET {offset}'.format(
|
||||
ds_name=self.provider.layer_name,
|
||||
limit=self.limit,
|
||||
offset=self.offset)
|
||||
sql = f'SELECT * FROM "{self.provider.layer_name}" LIMIT {self.limit} OFFSET {self.offset}' # noqa
|
||||
self.result_set = self.provider.conn.ExecuteSQL(sql)
|
||||
|
||||
# Reset since needs to be set each time explicitly
|
||||
@@ -682,8 +664,7 @@ class CommonSourceHelper(SourceHelper):
|
||||
self.limit = -1
|
||||
|
||||
if not self.result_set:
|
||||
msg = 'Cannot get Layer {} via ExecuteSQL'.format(
|
||||
self.provider.layer_name)
|
||||
msg = f'Cannot get Layer {self.provider.layer_name} via ExecuteSQL'
|
||||
LOGGER.error(msg)
|
||||
raise Exception(msg)
|
||||
|
||||
@@ -735,10 +716,7 @@ class ESRIJSONHelper(CommonSourceHelper):
|
||||
|
||||
self.close()
|
||||
|
||||
sql = "SELECT * FROM {ds_name} LIMIT {limit} OFFSET {offset}".format(
|
||||
ds_name=self.provider.layer_name,
|
||||
limit=self.limit,
|
||||
offset=self.offset)
|
||||
sql = f"SELECT * FROM {self.provider.layer_name} LIMIT {self.limit} OFFSET {self.offset}" # noqa
|
||||
self.result_set = self.provider.conn.ExecuteSQL(sql)
|
||||
|
||||
# Reset since needs to be set each time explicitly
|
||||
@@ -746,8 +724,7 @@ class ESRIJSONHelper(CommonSourceHelper):
|
||||
self.limit = -1
|
||||
|
||||
if not self.result_set:
|
||||
msg = 'Cannot get Layer {} via ExecuteSQL'.format(
|
||||
self.provider.layer_name)
|
||||
msg = f'Cannot get Layer {self.provider.layer_name} via ExecuteSQL'
|
||||
LOGGER.error(msg)
|
||||
raise Exception(msg)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# Colin Blackburn <colb@bgs.ac.uk>
|
||||
#
|
||||
# Copyright (c) 2018 Jorge Samuel Mendes de Jesus
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
# Copyright (c) 2022 John A Stevenson and Colin Blackburn
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
@@ -90,15 +90,15 @@ class PostgreSQLProvider(BaseProvider):
|
||||
self.id_field = provider_def['id_field']
|
||||
self.geom = provider_def.get('geom_field', 'geom')
|
||||
|
||||
LOGGER.debug('Name: {}'.format(self.name))
|
||||
LOGGER.debug('Table: {}'.format(self.table))
|
||||
LOGGER.debug('ID field: {}'.format(self.id_field))
|
||||
LOGGER.debug('Geometry field: {}'.format(self.geom))
|
||||
LOGGER.debug(f'Name: {self.name}')
|
||||
LOGGER.debug(f'Table: {self.table}')
|
||||
LOGGER.debug(f'ID field: {self.id_field}')
|
||||
LOGGER.debug(f'Geometry field: {self.geom}')
|
||||
|
||||
# Read table information from database
|
||||
self._store_db_parameters(provider_def['data'])
|
||||
self._engine, self.table_model = self._get_engine_and_table_model()
|
||||
LOGGER.debug('DB connection: {}'.format(repr(self._engine.url)))
|
||||
LOGGER.debug(f'DB connection: {repr(self._engine.url)}')
|
||||
self.fields = self.get_fields()
|
||||
|
||||
def query(self, offset=0, limit=10, resulttype='results',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2020 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -132,7 +132,7 @@ class RasterioProvider(BaseProvider):
|
||||
|
||||
for i, dtype, nodataval in zip(self._data.indexes, self._data.dtypes,
|
||||
self._data.nodatavals):
|
||||
LOGGER.debug('Determing rangetype for band {}'.format(i))
|
||||
LOGGER.debug(f'Determing rangetype for band {i}')
|
||||
|
||||
name, units = None, None
|
||||
if self._data.units[i-1] is None:
|
||||
@@ -146,12 +146,11 @@ class RasterioProvider(BaseProvider):
|
||||
'type': 'Quantity',
|
||||
'name': name,
|
||||
'encodingInfo': {
|
||||
'dataType': 'http://www.opengis.net/def/dataType/OGC/0/{}'.format(dtype) # noqa
|
||||
'dataType': f'http://www.opengis.net/def/dataType/OGC/0/{dtype}' # noqa
|
||||
},
|
||||
'nodata': nodataval,
|
||||
'uom': {
|
||||
'id': 'http://www.opengis.net/def/uom/UCUM/{}'.format(
|
||||
units),
|
||||
'id': f'http://www.opengis.net/def/uom/UCUM/{units}',
|
||||
'type': 'UnitReference',
|
||||
'code': units
|
||||
},
|
||||
@@ -176,7 +175,7 @@ class RasterioProvider(BaseProvider):
|
||||
"""
|
||||
|
||||
bands = properties
|
||||
LOGGER.debug('Bands: {}, subsets: {}'.format(bands, subsets))
|
||||
LOGGER.debug(f'Bands: {bands}, subsets: {subsets}')
|
||||
|
||||
args = {
|
||||
'indexes': None
|
||||
@@ -227,10 +226,8 @@ class RasterioProvider(BaseProvider):
|
||||
minx2, miny2 = t.transform(minx, miny)
|
||||
maxx2, maxy2 = t.transform(maxx, maxy)
|
||||
|
||||
LOGGER.debug('Source coordinates: {}'.format(
|
||||
[minx, miny, maxx, maxy]))
|
||||
LOGGER.debug('Destination coordinates: {}'.format(
|
||||
[minx2, miny2, maxx2, maxy2]))
|
||||
LOGGER.debug(f'Source coordinates: {minx}, {miny}, {maxx}, {maxy}') # noqa
|
||||
LOGGER.debug(f'Destination: {minx2}, {miny2}, {maxx2}, {maxy2}') # noqa
|
||||
|
||||
shapes = [{
|
||||
'type': 'Polygon',
|
||||
@@ -371,7 +368,7 @@ class RasterioProvider(BaseProvider):
|
||||
else:
|
||||
bands_select = metadata['bands']
|
||||
|
||||
LOGGER.debug('bands selected: {}'.format(bands_select))
|
||||
LOGGER.debug(f'bands selected: {bands_select}')
|
||||
for bs in bands_select:
|
||||
pm = _get_parameter_metadata(
|
||||
self._data.profile['driver'], self._data.tags(bs))
|
||||
@@ -437,10 +434,7 @@ class RasterioProvider(BaseProvider):
|
||||
|
||||
if self._data.crs is not None:
|
||||
if self._data.crs.is_projected:
|
||||
properties['bbox_crs'] = '{}/{}'.format(
|
||||
'http://www.opengis.net/def/crs/OGC/1.3/',
|
||||
self._data.crs.to_epsg())
|
||||
|
||||
properties['bbox_crs'] = f'http://www.opengis.net/def/crs/OGC/1.3/{self._data.crs.to_epsg()}' # noqa
|
||||
properties['x_axis_label'] = 'x'
|
||||
properties['y_axis_label'] = 'y'
|
||||
properties['bbox_units'] = self._data.crs.linear_units
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Benjamin Webb <benjamin.miller.webb@gmail.com>
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2021 Benjamin Webb
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -119,8 +121,8 @@ class SensorThingsProvider(BaseProvider):
|
||||
try:
|
||||
results = r.json()['value'][0]
|
||||
except JSONDecodeError as err:
|
||||
LOGGER.error('Entity {} error: {}'.format(self.entity, err))
|
||||
LOGGER.error('Bad url response at {}'.format(r.url))
|
||||
LOGGER.error(f'Entity {self.entity} error: {err}')
|
||||
LOGGER.error(f'Bad url response at {r.url}')
|
||||
raise ProviderQueryError(err)
|
||||
|
||||
for (n, v) in results.items():
|
||||
@@ -262,7 +264,7 @@ class SensorThingsProvider(BaseProvider):
|
||||
hits_ = 1 if identifier else min(limit, response.get('@iot.count'))
|
||||
while len(v) < hits_:
|
||||
LOGGER.debug('Fetching next set of values')
|
||||
next_ = response.get('@iot.nextLink', None)
|
||||
next_ = response.get('@iot.nextLink')
|
||||
if next_ is None:
|
||||
break
|
||||
else:
|
||||
@@ -415,7 +417,6 @@ class SensorThingsProvider(BaseProvider):
|
||||
|
||||
for k, v in entity.items():
|
||||
# Create intra links
|
||||
path_ = 'collections/{}/items/{}'
|
||||
ks = f'{k}s'
|
||||
if self.uri_field is not None and k in ['properties']:
|
||||
uri = v.get(self.uri_field, '')
|
||||
@@ -426,14 +427,9 @@ class SensorThingsProvider(BaseProvider):
|
||||
v[i] = _v['properties'][self._linkables[k]['u']]
|
||||
continue
|
||||
for i, _v in enumerate(v):
|
||||
id = _v[self.id_field]
|
||||
id = f"'{id}'" if isinstance(id, str) else str(id)
|
||||
v[i] = url_join(
|
||||
self._rel_link,
|
||||
path_.format(
|
||||
self._linkables[k]['n'], id
|
||||
)
|
||||
)
|
||||
id_ = _v[self.id_field]
|
||||
id_ = f"'{id_}'" if isinstance(id_, str) else str(id_)
|
||||
v[i] = url_join(self._rel_link, f"collections/{self._linkables[k]['n']}/items/{id_}") # noqa
|
||||
|
||||
elif ks in self._linkables.keys():
|
||||
if self._linkables[ks]['u'] != '':
|
||||
@@ -443,13 +439,10 @@ class SensorThingsProvider(BaseProvider):
|
||||
id = f"'{id}'" if isinstance(id, str) else str(id)
|
||||
entity[k] = url_join(
|
||||
self._rel_link,
|
||||
path_.format(
|
||||
self._linkables[ks]['n'], id
|
||||
)
|
||||
)
|
||||
f"collections/{self._linkables[ks]['n']}/items/{id_}")
|
||||
|
||||
# Make properties block
|
||||
if entity.get('properties', None):
|
||||
if entity.get('properties'):
|
||||
entity.update(entity.pop('properties'))
|
||||
|
||||
if keys:
|
||||
@@ -465,4 +458,4 @@ class SensorThingsProvider(BaseProvider):
|
||||
return entity
|
||||
|
||||
def __repr__(self):
|
||||
return '<SensorThingsProvider> {}, {}'.format(self.data, self.entity)
|
||||
return f'<SensorThingsProvider> {self.data}, {self.entity}'
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Benjamin Webb <bwebb@lincolninst.edu>
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2022 Benjamin Webb
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -79,7 +81,7 @@ class SODAServiceProvider(BaseProvider):
|
||||
[dataset] = self.client.datasets(ids=[self.resource_id])
|
||||
resource = dataset['resource']
|
||||
except json.decoder.JSONDecodeError as err:
|
||||
LOGGER.error('Bad response at {}'.format(self.data))
|
||||
LOGGER.error(f'Bad response at {self.data}')
|
||||
raise ProviderConnectionError(err)
|
||||
|
||||
fields = self.properties or resource[FIELD_NAME]
|
||||
@@ -269,4 +271,4 @@ class SODAServiceProvider(BaseProvider):
|
||||
return int(response['count'])
|
||||
|
||||
def __repr__(self):
|
||||
return '<SODAServiceProvider> {}'.format(self.data)
|
||||
return f'<SODAServiceProvider> {self.data}'
|
||||
|
||||
+28
-34
@@ -5,7 +5,7 @@
|
||||
# Francesco Bartoli <xbartolone@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2018 Jorge Samuel Mendes de Jesus
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
# Copyright (c) 2020 Francesco Bartoli
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
@@ -68,10 +68,10 @@ class SQLiteGPKGProvider(BaseProvider):
|
||||
self.geom_col = None
|
||||
|
||||
LOGGER.debug('Setting SQLite properties:')
|
||||
LOGGER.debug('Data source: {}'.format(self.data))
|
||||
LOGGER.debug('Name: {}'.format(self.name))
|
||||
LOGGER.debug('ID_field: {}'.format(self.id_field))
|
||||
LOGGER.debug('Table: {}'.format(self.table))
|
||||
LOGGER.debug(f'Data source: {self.data}')
|
||||
LOGGER.debug(f'Name: {self.name}')
|
||||
LOGGER.debug(f'ID_field: {self.id_field}')
|
||||
LOGGER.debug(f'Table: {self.table}')
|
||||
|
||||
self.cursor = self.__load()
|
||||
|
||||
@@ -89,7 +89,7 @@ class SQLiteGPKGProvider(BaseProvider):
|
||||
|
||||
if not self.fields:
|
||||
results = self.cursor.execute(
|
||||
'PRAGMA table_info({})'.format(self.table)).fetchall()
|
||||
f'PRAGMA table_info({self.table})').fetchall()
|
||||
for item in results:
|
||||
self.fields[item['name']] = {'type': item['type']}
|
||||
|
||||
@@ -116,14 +116,13 @@ class SQLiteGPKGProvider(BaseProvider):
|
||||
|
||||
if properties:
|
||||
where_clause += " AND ".join(
|
||||
["{}=?".format(k) for k, v in properties])
|
||||
[f"{k}=?" for k, v in properties])
|
||||
where_values += where_values + tuple((v for k, v in properties))
|
||||
|
||||
if bbox:
|
||||
if properties:
|
||||
where_clause += " AND "
|
||||
where_clause += " Intersects({}, \
|
||||
BuildMbr(?,?,?,?)) ".format(self.geom_col)
|
||||
where_clause += f" Intersects({self.geom_col}, BuildMbr(?,?,?,?)) "
|
||||
where_values += tuple(bbox)
|
||||
# WHERE continent=? <class 'tuple'>: ('Europe',)
|
||||
return where_clause, where_values
|
||||
@@ -144,7 +143,7 @@ class SQLiteGPKGProvider(BaseProvider):
|
||||
'type': 'Feature'
|
||||
}
|
||||
feature["geometry"] = json.loads(
|
||||
rd.pop('AsGeoJSON({})'.format(self.geom_col))
|
||||
rd.pop(f'AsGeoJSON({self.geom_col})')
|
||||
)
|
||||
if skip_geometry:
|
||||
feature["geometry"] = None
|
||||
@@ -185,7 +184,7 @@ class SQLiteGPKGProvider(BaseProvider):
|
||||
try:
|
||||
conn.enable_load_extension(True)
|
||||
except AttributeError as err:
|
||||
LOGGER.error('Extension loading not enabled: {}'.format(err))
|
||||
LOGGER.error(f'Extension loading not enabled: {err}')
|
||||
raise ProviderConnectionError()
|
||||
|
||||
conn.row_factory = sqlite3.Row
|
||||
@@ -193,10 +192,9 @@ class SQLiteGPKGProvider(BaseProvider):
|
||||
# conn.set_trace_callback(LOGGER.debug)
|
||||
cursor = conn.cursor()
|
||||
try:
|
||||
cursor.execute("SELECT load_extension('{}')".format(
|
||||
SPATIALITE_EXTENSION))
|
||||
cursor.execute(f"SELECT load_extension('{SPATIALITE_EXTENSION}')")
|
||||
except sqlite3.OperationalError as err:
|
||||
LOGGER.error('Extension loading error: {}'.format(err))
|
||||
LOGGER.error(f'Extension loading error: {err}')
|
||||
raise ProviderConnectionError()
|
||||
result = cursor.fetchall()
|
||||
|
||||
@@ -229,10 +227,10 @@ class SQLiteGPKGProvider(BaseProvider):
|
||||
self.geom_col = "geometry"
|
||||
|
||||
try:
|
||||
cursor.execute('PRAGMA table_info({})'.format(self.table))
|
||||
cursor.execute(f'PRAGMA table_info({self.table})')
|
||||
result = cursor.fetchall()
|
||||
except sqlite3.OperationalError:
|
||||
LOGGER.error('Couldnt find table: {}'.format(self.table))
|
||||
LOGGER.error(f'Couldnt find table: {self.table}')
|
||||
raise ProviderConnectionError()
|
||||
|
||||
try:
|
||||
@@ -245,11 +243,10 @@ class SQLiteGPKGProvider(BaseProvider):
|
||||
|
||||
self.columns = [item[1] for item in result if item[1]
|
||||
not in [self.geom_col, self.geom_col.upper()]]
|
||||
self.columns = ','.join(self.columns)+',AsGeoJSON({})'.format(
|
||||
self.geom_col)
|
||||
self.columns = ','.join(self.columns)+f',AsGeoJSON({self.geom_col})'
|
||||
|
||||
if self.application_id:
|
||||
self.table = "vgpkg_{}".format(self.table)
|
||||
self.table = f"vgpkg_{self.table}"
|
||||
|
||||
return cursor
|
||||
|
||||
@@ -282,23 +279,21 @@ class SQLiteGPKGProvider(BaseProvider):
|
||||
|
||||
if resulttype == 'hits':
|
||||
|
||||
sql_query = "SELECT COUNT(*) as hits FROM {} {} ".format(
|
||||
self.table, where_clause)
|
||||
sql_query = f"SELECT COUNT(*) as hits FROM {self.table} {where_clause} " # noqa
|
||||
|
||||
res = self.cursor.execute(sql_query, where_values)
|
||||
|
||||
hits = res.fetchone()["hits"]
|
||||
return self.__response_feature_hits(hits)
|
||||
|
||||
sql_query = "SELECT DISTINCT {} from \
|
||||
{} {} limit ? offset ?".format(
|
||||
self.columns, self.table, where_clause)
|
||||
sql_query = f"SELECT DISTINCT {self.columns} from \
|
||||
{self.table} {where_clause} limit ? offset ?"
|
||||
|
||||
end_index = offset + limit
|
||||
|
||||
LOGGER.debug('SQL Query: {}'.format(sql_query))
|
||||
LOGGER.debug('Start Index: {}'.format(offset))
|
||||
LOGGER.debug('End Index: {}'.format(end_index))
|
||||
LOGGER.debug(f'SQL Query: {sql_query}')
|
||||
LOGGER.debug(f'Start Index: {offset}')
|
||||
LOGGER.debug(f'End Index: {end_index}')
|
||||
|
||||
row_data = self.cursor.execute(
|
||||
sql_query, where_values + (limit, offset))
|
||||
@@ -326,12 +321,11 @@ class SQLiteGPKGProvider(BaseProvider):
|
||||
|
||||
LOGGER.debug('Get item from SQLite/GPKG')
|
||||
|
||||
sql_query = 'SELECT {} FROM \
|
||||
{} WHERE {}==?;'.format(
|
||||
self.columns, self.table, self.id_field)
|
||||
sql_query = f'SELECT {self.columns} FROM \
|
||||
{self.table} WHERE {self.id_field}==?;'
|
||||
|
||||
LOGGER.debug('SQL Query: {}'.format(sql_query))
|
||||
LOGGER.debug('Identifier: {}'.format(identifier))
|
||||
LOGGER.debug(f'SQL Query: {sql_query}')
|
||||
LOGGER.debug(f'Identifier: {identifier}')
|
||||
|
||||
row_data = self.cursor.execute(sql_query, (identifier, )).fetchone()
|
||||
|
||||
@@ -339,9 +333,9 @@ class SQLiteGPKGProvider(BaseProvider):
|
||||
if feature:
|
||||
return feature
|
||||
else:
|
||||
err = 'item {} not found'.format(identifier)
|
||||
err = f'item {identifier} not found'
|
||||
LOGGER.error(err)
|
||||
raise ProviderItemNotFoundError(err)
|
||||
|
||||
def __repr__(self):
|
||||
return '<SQLiteGPKGProvider> {}, {}'.format(self.data, self.table)
|
||||
return f'<SQLiteGPKGProvider> {self.data}, {self.table}'
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Francesco Bartoli <xbartolone@gmail.com>
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2020 Francesco Bartoli
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -50,7 +52,7 @@ class BaseTileProvider:
|
||||
self.data = provider_def['data']
|
||||
self.format_type = provider_def['format']['name']
|
||||
self.mimetype = provider_def['format']['mimetype']
|
||||
self.options = provider_def.get('options', None)
|
||||
self.options = provider_def.get('options')
|
||||
self.fields = {}
|
||||
|
||||
def get_layer(self):
|
||||
|
||||
@@ -58,7 +58,7 @@ class TinyDBCatalogueProvider(BaseProvider):
|
||||
|
||||
super().__init__(provider_def)
|
||||
|
||||
LOGGER.debug('Connecting to TinyDB db at {}'.format(self.data))
|
||||
LOGGER.debug(f'Connecting to TinyDB db at {self.data}')
|
||||
|
||||
if not os.path.exists(self.data):
|
||||
msg = 'TinyDB does not exist'
|
||||
@@ -117,7 +117,7 @@ class TinyDBCatalogueProvider(BaseProvider):
|
||||
"""
|
||||
|
||||
Q = Query()
|
||||
LOGGER.debug('Query initiated: {}'.format(Q))
|
||||
LOGGER.debug(f'Query initiated: {Q}')
|
||||
|
||||
QUERY = []
|
||||
|
||||
@@ -133,7 +133,7 @@ class TinyDBCatalogueProvider(BaseProvider):
|
||||
if bbox:
|
||||
LOGGER.debug('processing bbox parameter')
|
||||
bbox_as_string = ','.join(str(s) for s in bbox)
|
||||
QUERY.append("Q.properties.extent.spatial.bbox.test(bbox_intersects, '{}')".format(bbox_as_string)) # noqa
|
||||
QUERY.append(f"Q.properties.extent.spatial.bbox.test(bbox_intersects, '{bbox_as_string}')") # noqa
|
||||
|
||||
if datetime_ is not None:
|
||||
LOGGER.debug('processing datetime parameter')
|
||||
@@ -146,31 +146,31 @@ class TinyDBCatalogueProvider(BaseProvider):
|
||||
time_begin, time_end = datetime_.split('/')
|
||||
|
||||
if time_begin != '..':
|
||||
QUERY.append("(Q.properties[self.time_field]>='{}')".format(time_begin)) # noqa
|
||||
QUERY.append(f"(Q.properties[self.time_field]>='{time_begin}')") # noqa
|
||||
if time_end != '..':
|
||||
QUERY.append("(Q.properties[self.time_field]<='{}')".format(time_end)) # noqa
|
||||
QUERY.append(f"(Q.properties[self.time_field]<='{time_end}')") # noqa
|
||||
|
||||
else: # time instant
|
||||
LOGGER.debug('detected time instant')
|
||||
QUERY.append("(Q.properties[self.time_field]=='{}')".format(datetime_)) # noqa
|
||||
QUERY.append(f"(Q.properties[self.time_field]=='{datetime_}')") # noqa
|
||||
|
||||
if properties:
|
||||
LOGGER.debug('processing properties')
|
||||
for prop in properties:
|
||||
QUERY.append("(Q.properties['{}']=='{}')".format(*prop))
|
||||
QUERY.append(f"(Q.properties['{prop[0]}']=='{prop[1]}')")
|
||||
|
||||
if q is not None:
|
||||
for t in q.split():
|
||||
QUERY.append("(Q.properties['_metadata-anytext'].search('{}', flags=re.IGNORECASE))".format(t)) # noqa
|
||||
QUERY.append(f"(Q.properties['_metadata-anytext'].search('{t}', flags=re.IGNORECASE))") # noqa
|
||||
|
||||
QUERY_STRING = '&'.join(QUERY)
|
||||
LOGGER.debug('QUERY_STRING: {}'.format(QUERY_STRING))
|
||||
SEARCH_STRING = 'self.db.search({})'.format(QUERY_STRING)
|
||||
LOGGER.debug('SEARCH_STRING: {}'.format(SEARCH_STRING))
|
||||
LOGGER.debug(f'QUERY_STRING: {QUERY_STRING}')
|
||||
SEARCH_STRING = f'self.db.search({QUERY_STRING})'
|
||||
LOGGER.debug(f'SEARCH_STRING: {SEARCH_STRING}')
|
||||
|
||||
LOGGER.debug('querying database')
|
||||
if len(QUERY) > 0:
|
||||
LOGGER.debug('running eval on {}'.format(SEARCH_STRING))
|
||||
LOGGER.debug(f'running eval on {SEARCH_STRING}')
|
||||
results = eval(SEARCH_STRING)
|
||||
else:
|
||||
results = self.db.all()
|
||||
@@ -185,11 +185,11 @@ class TinyDBCatalogueProvider(BaseProvider):
|
||||
try:
|
||||
del r['properties'][e]
|
||||
except KeyError:
|
||||
LOGGER.debug('Missing excluded property {}'.format(e))
|
||||
LOGGER.debug(f'Missing excluded property {e}')
|
||||
|
||||
len_results = len(results)
|
||||
|
||||
LOGGER.debug('Results found: {}'.format(len_results))
|
||||
LOGGER.debug(f'Results found: {len_results}')
|
||||
|
||||
if len_results > limit:
|
||||
returned = limit
|
||||
@@ -221,7 +221,7 @@ class TinyDBCatalogueProvider(BaseProvider):
|
||||
:returns: `dict` of single record
|
||||
"""
|
||||
|
||||
LOGGER.debug('Fetching identifier {}'.format(identifier))
|
||||
LOGGER.debug(f'Fetching identifier {identifier}')
|
||||
|
||||
record = self.db.get(Query().id == identifier)
|
||||
|
||||
@@ -232,7 +232,7 @@ class TinyDBCatalogueProvider(BaseProvider):
|
||||
try:
|
||||
del record['properties'][e]
|
||||
except KeyError:
|
||||
LOGGER.debug('Missing excluded property {}'.format(e))
|
||||
LOGGER.debug(f'Missing excluded property {e}')
|
||||
|
||||
return record
|
||||
|
||||
@@ -256,10 +256,10 @@ class TinyDBCatalogueProvider(BaseProvider):
|
||||
LOGGER.debug('Missing title and description')
|
||||
json_data['properties']['_metadata_anytext'] = ''
|
||||
|
||||
LOGGER.debug('Inserting data with identifier {}'.format(identifier))
|
||||
LOGGER.debug(f'Inserting data with identifier {identifier}')
|
||||
result = self.db.insert(json_data)
|
||||
|
||||
LOGGER.debug('Item added with internal id {}'.format(result))
|
||||
LOGGER.debug(f'Item added with internal id {result}')
|
||||
|
||||
return identifier
|
||||
|
||||
@@ -273,7 +273,7 @@ class TinyDBCatalogueProvider(BaseProvider):
|
||||
:returns: `bool` of update result
|
||||
"""
|
||||
|
||||
LOGGER.debug('Updating item {}'.format(identifier))
|
||||
LOGGER.debug(f'Updating item {identifier}')
|
||||
identifier, json_data = self._load_and_prepare_item(
|
||||
item, identifier, raise_if_exists=False)
|
||||
self.db.update(json_data, where('id') == identifier)
|
||||
@@ -289,7 +289,7 @@ class TinyDBCatalogueProvider(BaseProvider):
|
||||
:returns: `bool` of deletion result
|
||||
"""
|
||||
|
||||
LOGGER.debug('Deleting item {}'.format(identifier))
|
||||
LOGGER.debug(f'Deleting item {identifier}')
|
||||
self.db.remove(where('id') == identifier)
|
||||
|
||||
return True
|
||||
@@ -307,7 +307,7 @@ class TinyDBCatalogueProvider(BaseProvider):
|
||||
return True
|
||||
|
||||
def __repr__(self):
|
||||
return '<TinyDBCatalogueProvider> {}'.format(self.data)
|
||||
return f'<TinyDBCatalogueProvider> {self.data}'
|
||||
|
||||
|
||||
def bbox_intersects(record_bbox, input_bbox):
|
||||
@@ -323,8 +323,8 @@ def bbox_intersects(record_bbox, input_bbox):
|
||||
bbox1 = record_bbox[0]
|
||||
bbox2 = [float(c) for c in input_bbox.split(',')]
|
||||
|
||||
LOGGER.debug('Record bbox: {}'.format(bbox1))
|
||||
LOGGER.debug('Input bbox: {}'.format(bbox2))
|
||||
LOGGER.debug(f'Record bbox: {bbox1}')
|
||||
LOGGER.debug(f'Input bbox: {bbox2}')
|
||||
|
||||
# any point in bbox1 should be in bbox2
|
||||
bbox_tests = [
|
||||
|
||||
@@ -61,7 +61,7 @@ class WMSFacadeProvider(BaseProvider):
|
||||
|
||||
BaseProvider.__init__(self, provider_def)
|
||||
|
||||
LOGGER.debug('pyproj version: {}'.format(pyproj.__version__))
|
||||
LOGGER.debug(f'pyproj version: {pyproj.__version__}')
|
||||
|
||||
def query(self, style=None, bbox=[-180, -90, 180, 90], width=500,
|
||||
height=300, crs=4326, datetime_=None, transparent=True,
|
||||
@@ -90,7 +90,7 @@ class WMSFacadeProvider(BaseProvider):
|
||||
[bbox[1], bbox[0], bbox[3], bbox[2]])
|
||||
else:
|
||||
LOGGER.debug('Reprojecting coordinates')
|
||||
LOGGER.debug('Output CRS: {}'.format(CRS_CODES[crs]))
|
||||
LOGGER.debug(f'Output CRS: {CRS_CODES[crs]}')
|
||||
|
||||
src_crs = pyproj.CRS.from_string('epsg:4326')
|
||||
dest_crs = pyproj.CRS.from_string(CRS_CODES[crs])
|
||||
@@ -128,7 +128,7 @@ class WMSFacadeProvider(BaseProvider):
|
||||
else:
|
||||
request_url = '?'.join([self.data, urlencode(params)])
|
||||
|
||||
LOGGER.debug('WMS 1.3.0 request url: {}'.format(request_url))
|
||||
LOGGER.debug(f'WMS 1.3.0 request url: {request_url}')
|
||||
|
||||
response = requests.get(request_url)
|
||||
|
||||
@@ -140,4 +140,4 @@ class WMSFacadeProvider(BaseProvider):
|
||||
return response.content
|
||||
|
||||
def __repr__(self):
|
||||
return '<MapScriptProvider> {}'.format(self.data)
|
||||
return f'<MapScriptProvider> {self.data}'
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Gregory Petrochenkov <gpetrochenkov@usgs.gov>
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2020 Gregory Petrochenkov
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -153,7 +155,7 @@ class XarrayProvider(BaseProvider):
|
||||
}
|
||||
|
||||
for name, var in self._data.variables.items():
|
||||
LOGGER.debug('Determining rangetype for {}'.format(name))
|
||||
LOGGER.debug(f'Determining rangetype for {name}')
|
||||
|
||||
desc, units = None, None
|
||||
if len(var.shape) >= 3:
|
||||
@@ -167,12 +169,11 @@ class XarrayProvider(BaseProvider):
|
||||
'type': 'Quantity',
|
||||
'name': var.attrs.get('long_name') or desc,
|
||||
'encodingInfo': {
|
||||
'dataType': 'http://www.opengis.net/def/dataType/OGC/0/{}'.format(str(var.dtype)) # noqa
|
||||
'dataType': f'http://www.opengis.net/def/dataType/OGC/0/{var.dtype}' # noqa
|
||||
},
|
||||
'nodata': 'null',
|
||||
'uom': {
|
||||
'id': 'http://www.opengis.net/def/uom/UCUM/{}'.format(
|
||||
units),
|
||||
'id': f'http://www.opengis.net/def/uom/UCUM/{units}',
|
||||
'type': 'UnitReference',
|
||||
'code': units
|
||||
},
|
||||
@@ -219,7 +220,7 @@ class XarrayProvider(BaseProvider):
|
||||
|
||||
query_params = {}
|
||||
for key, val in subsets.items():
|
||||
LOGGER.debug('Processing subset: {}'.format(key))
|
||||
LOGGER.debug(f'Processing subset: {key}')
|
||||
if data.coords[key].values[0] > data.coords[key].values[-1]:
|
||||
LOGGER.debug('Reversing slicing from high to low')
|
||||
query_params[key] = slice(val[1], val[0])
|
||||
@@ -257,7 +258,7 @@ class XarrayProvider(BaseProvider):
|
||||
else:
|
||||
query_params[self.time_field] = datetime_
|
||||
|
||||
LOGGER.debug('Query parameters: {}'.format(query_params))
|
||||
LOGGER.debug(f'Query parameters: {query_params}')
|
||||
try:
|
||||
data = data.sel(query_params)
|
||||
except Exception as err:
|
||||
@@ -329,7 +330,7 @@ class XarrayProvider(BaseProvider):
|
||||
tmp_max = data.coords[self.y_field].values
|
||||
|
||||
if tmp_min > tmp_max:
|
||||
LOGGER.debug('Reversing direction of {}'.format(self.y_field))
|
||||
LOGGER.debug(f'Reversing direction of {self.y_field}')
|
||||
miny = tmp_max
|
||||
maxy = tmp_min
|
||||
|
||||
@@ -471,9 +472,7 @@ class XarrayProvider(BaseProvider):
|
||||
}
|
||||
|
||||
if 'crs' in self._data.variables.keys():
|
||||
properties['bbox_crs'] = '{}/{}'.format(
|
||||
'http://www.opengis.net/def/crs/OGC/1.3/',
|
||||
self._data.crs.epsg_code)
|
||||
properties['bbox_crs'] = f'http://www.opengis.net/def/crs/OGC/1.3/{self._data.crs.epsg_code}' # noqa
|
||||
|
||||
properties['inverse_flattening'] = self._data.crs.\
|
||||
inverse_flattening
|
||||
@@ -502,11 +501,11 @@ class XarrayProvider(BaseProvider):
|
||||
|
||||
return {
|
||||
'id': name,
|
||||
'description': attrs.get('long_name', None),
|
||||
'unit_label': attrs.get('units', None),
|
||||
'unit_symbol': attrs.get('units', None),
|
||||
'description': attrs.get('long_name'),
|
||||
'unit_label': attrs.get('units'),
|
||||
'unit_symbol': attrs.get('units'),
|
||||
'observed_property_id': name,
|
||||
'observed_property_name': attrs.get('long_name', None)
|
||||
'observed_property_name': attrs.get('long_name')
|
||||
}
|
||||
|
||||
def get_time_resolution(self):
|
||||
@@ -542,7 +541,7 @@ class XarrayProvider(BaseProvider):
|
||||
'seconds': int(ms_difference / 1000) % 60
|
||||
}
|
||||
|
||||
times = ['{} {}'.format(val, key) for key, val
|
||||
times = [f'{val} {key}' for key, val
|
||||
in time_dict.items() if val > 0]
|
||||
|
||||
return ', '.join(times)
|
||||
@@ -605,12 +604,17 @@ def _get_zarr_data(data):
|
||||
"""
|
||||
|
||||
tmp_dir = tempfile.TemporaryDirectory().name
|
||||
data.to_zarr('{}zarr.zarr'.format(tmp_dir), mode='w')
|
||||
with zipfile.ZipFile('{}zarr.zarr.zip'.format(tmp_dir),
|
||||
'w', zipfile.ZIP_DEFLATED) as zipf:
|
||||
_zip_dir('{}zarr.zarr'.format(tmp_dir), zipf, os.getcwd())
|
||||
zip_file = open('{}zarr.zarr.zip'.format(tmp_dir), 'rb')
|
||||
return zip_file.read()
|
||||
|
||||
zarr_data_filename = f'{tmp_dir}zarr.zarr'
|
||||
zarr_zip_filename = f'{tmp_dir}zarr.zarr.zip'
|
||||
|
||||
data.to_zarr(zarr_data_filename, mode='w')
|
||||
|
||||
with zipfile.ZipFile(zarr_zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf: # noqa
|
||||
_zip_dir(zarr_data_filename, zipf, os.getcwd())
|
||||
|
||||
with open(zarr_zip_filename, 'rb') as fh:
|
||||
return fh.read()
|
||||
|
||||
|
||||
def _convert_float32_to_float64(data):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2020 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -77,14 +77,14 @@ class XarrayEDRProvider(BaseEDRProvider, XarrayProvider):
|
||||
|
||||
query_params = {}
|
||||
|
||||
LOGGER.debug('Query parameters: {}'.format(kwargs))
|
||||
LOGGER.debug(f'Query parameters: {kwargs}')
|
||||
|
||||
LOGGER.debug('Query type: {}'.format(kwargs.get('query_type')))
|
||||
LOGGER.debug(f"Query type: {kwargs.get('query_type')}")
|
||||
|
||||
wkt = kwargs.get('wkt')
|
||||
if wkt is not None:
|
||||
LOGGER.debug('Processing WKT')
|
||||
LOGGER.debug('Geometry type: {}'.format(wkt.type))
|
||||
LOGGER.debug(f'Geometry type: {wkt.type}')
|
||||
if wkt.type == 'Point':
|
||||
query_params[self._coverage_properties['x_axis_label']] = wkt.x
|
||||
query_params[self._coverage_properties['y_axis_label']] = wkt.y
|
||||
@@ -102,13 +102,13 @@ class XarrayEDRProvider(BaseEDRProvider, XarrayProvider):
|
||||
# example of fetching instance passed
|
||||
# TODO: apply accordingly
|
||||
instance = kwargs.get('instance')
|
||||
LOGGER.debug('instance: {}'.format(instance))
|
||||
LOGGER.debug(f'instance: {instance}')
|
||||
|
||||
datetime_ = kwargs.get('datetime_')
|
||||
if datetime_ is not None:
|
||||
query_params[self._coverage_properties['time_axis_label']] = datetime_ # noqa
|
||||
|
||||
LOGGER.debug('query parameters: {}'.format(query_params))
|
||||
LOGGER.debug(f'query parameters: {query_params}')
|
||||
|
||||
try:
|
||||
if select_properties:
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
""" Starlette module providing the route paths to the api"""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import click
|
||||
|
||||
@@ -53,10 +54,14 @@ if 'PYGEOAPI_CONFIG' not in os.environ:
|
||||
with open(os.environ.get('PYGEOAPI_CONFIG'), encoding='utf8') as fh:
|
||||
CONFIG = yaml_load(fh)
|
||||
|
||||
STATIC_DIR = '{}{}static'.format(os.path.dirname(os.path.realpath(__file__)),
|
||||
os.sep)
|
||||
if 'templates' in CONFIG['server']:
|
||||
STATIC_DIR = CONFIG['server']['templates'].get('static', STATIC_DIR)
|
||||
p = Path(__file__)
|
||||
|
||||
STATIC_DIR = Path(p).parent.resolve() / 'static'
|
||||
|
||||
try:
|
||||
STATIC_DIR = Path(CONFIG['server']['templates']['static'])
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
app = Starlette()
|
||||
app.mount('/static', StaticFiles(directory=STATIC_DIR))
|
||||
@@ -66,11 +71,14 @@ if CONFIG['server'].get('cors', False):
|
||||
from starlette.middleware.cors import CORSMiddleware
|
||||
app.add_middleware(CORSMiddleware, allow_origins=['*'])
|
||||
|
||||
OGC_SCHEMAS_LOCATION = CONFIG['server'].get('ogc_schemas_location', None)
|
||||
try:
|
||||
OGC_SCHEMAS_LOCATION = Path(CONFIG['server']['ogc_schemas_location'])
|
||||
except KeyError:
|
||||
OGC_SCHEMAS_LOCATION = None
|
||||
|
||||
if (OGC_SCHEMAS_LOCATION is not None and
|
||||
not OGC_SCHEMAS_LOCATION.startswith('http')):
|
||||
if not os.path.exists(OGC_SCHEMAS_LOCATION):
|
||||
not OGC_SCHEMAS_LOCATION.name.startswith('http')):
|
||||
if not OGC_SCHEMAS_LOCATION.exists():
|
||||
raise RuntimeError('OGC schemas misconfigured')
|
||||
app.mount('/schemas', StaticFiles(directory=OGC_SCHEMAS_LOCATION))
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
|
||||
<![endif]-->
|
||||
<meta name="twitter:image:src" content="{% block thumb %}{% endblock %}{% if not self.thumb() %}{{'{}/static/img/logo.png'.format(config['server']['url']) }}{% endif %}" />
|
||||
<meta property="og:image" content="{{ self.thumb() }}{% if not self.thumb() %}{{'{}/static/img/logo.png'.format(config['server']['url']) }}{% endif %}" />
|
||||
<meta name="twitter:image:src" content="{% block thumb %}{% endblock %}{% if not self.thumb() %}{{ config['server']['url'] }}/static/img/logo.png{% endif %}" />
|
||||
<meta property="og:image" content="{{ self.thumb() }}{% if not self.thumb() %}{{ config['server']['url'] }}/static/img/logo.png{% endif %}" />
|
||||
<meta name="twitter:site" content="{{ config['metadata']['identification']['title'] }}" />
|
||||
<meta property="og:site_name" content="{{ config['metadata']['identification']['title'] }}" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "_base.html" %}
|
||||
{% set ptitle = data['properties'][data['title_field']] or ("Item {}".format(data['id'])) %}
|
||||
{% set ptitle = data['properties'][data['title_field']] or "Item " + data['id'] %}
|
||||
{% block desc %}{{ data.get('properties',{}).get('description', {}) | string | truncate(250) }}{% endblock %}
|
||||
{% block tags %}{{ data['properties'].get('themes', [{}])[0].get('concepts', []) | join(',') }}{% endblock %}
|
||||
{# Optionally renders an img element, otherwise standard value or link rendering #}
|
||||
|
||||
+47
-42
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2020 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -34,12 +34,13 @@ from typing import List
|
||||
from datetime import date, datetime, time
|
||||
from decimal import Decimal
|
||||
from enum import Enum
|
||||
import io
|
||||
import json
|
||||
import logging
|
||||
import mimetypes
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
from typing import Any, IO, Union
|
||||
from urllib.request import urlopen
|
||||
from urllib.parse import urlparse
|
||||
|
||||
@@ -59,14 +60,13 @@ LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
|
||||
|
||||
TEMPLATES = '{}{}templates'.format(os.path.dirname(
|
||||
os.path.realpath(__file__)), os.sep)
|
||||
TEMPLATES = Path(__file__).parent.resolve() / 'templates'
|
||||
|
||||
mimetypes.add_type('text/plain', '.yaml')
|
||||
mimetypes.add_type('text/plain', '.yml')
|
||||
|
||||
|
||||
def dategetter(date_property, collection):
|
||||
def dategetter(date_property: str, collection: dict) -> str:
|
||||
"""
|
||||
Attempts to obtain a date value from a collection.
|
||||
|
||||
@@ -77,7 +77,7 @@ def dategetter(date_property, collection):
|
||||
for an open interval using null)
|
||||
"""
|
||||
|
||||
value = collection.get(date_property, None)
|
||||
value = collection.get(date_property)
|
||||
|
||||
if value is None:
|
||||
return None
|
||||
@@ -85,7 +85,7 @@ def dategetter(date_property, collection):
|
||||
return value.isoformat()
|
||||
|
||||
|
||||
def get_typed_value(value):
|
||||
def get_typed_value(value: str) -> Union[float, int, str]:
|
||||
"""
|
||||
Derive true type from data value
|
||||
|
||||
@@ -107,7 +107,7 @@ def get_typed_value(value):
|
||||
return value2
|
||||
|
||||
|
||||
def yaml_load(fh):
|
||||
def yaml_load(fh: IO) -> dict:
|
||||
"""
|
||||
serializes a YAML files into a pyyaml object
|
||||
|
||||
@@ -123,7 +123,7 @@ def yaml_load(fh):
|
||||
def path_constructor(loader, node):
|
||||
env_var = path_matcher.match(node.value).group(1)
|
||||
if env_var not in os.environ:
|
||||
msg = 'Undefined environment variable {} in config'.format(env_var)
|
||||
msg = f'Undefined environment variable {env_var} in config'
|
||||
raise EnvironmentError(msg)
|
||||
return get_typed_value(os.path.expandvars(node.value))
|
||||
|
||||
@@ -136,7 +136,7 @@ def yaml_load(fh):
|
||||
return yaml.load(fh, Loader=EnvVarLoader)
|
||||
|
||||
|
||||
def str2bool(value):
|
||||
def str2bool(value: Union[bool, str]) -> bool:
|
||||
"""
|
||||
helper function to return Python boolean
|
||||
type (source: https://stackoverflow.com/a/715468)
|
||||
@@ -156,7 +156,7 @@ def str2bool(value):
|
||||
return value2
|
||||
|
||||
|
||||
def to_json(dict_, pretty=False):
|
||||
def to_json(dict_: dict, pretty: bool = False) -> str:
|
||||
"""
|
||||
Serialize dict to json
|
||||
|
||||
@@ -175,7 +175,7 @@ def to_json(dict_, pretty=False):
|
||||
indent=indent)
|
||||
|
||||
|
||||
def format_datetime(value, format_=DATETIME_FORMAT):
|
||||
def format_datetime(value: str, format_: str = DATETIME_FORMAT) -> str:
|
||||
"""
|
||||
Parse datetime as ISO 8601 string; re-present it in particular format
|
||||
for display in HTML
|
||||
@@ -192,7 +192,7 @@ def format_datetime(value, format_=DATETIME_FORMAT):
|
||||
return dateutil.parser.isoparse(value).strftime(format_)
|
||||
|
||||
|
||||
def file_modified_iso8601(filepath):
|
||||
def file_modified_iso8601(filepath: Path) -> str:
|
||||
"""
|
||||
Provide a file's ctime in ISO8601
|
||||
|
||||
@@ -205,7 +205,7 @@ def file_modified_iso8601(filepath):
|
||||
os.path.getctime(filepath)).strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
|
||||
|
||||
def human_size(nbytes):
|
||||
def human_size(nbytes: int) -> str:
|
||||
"""
|
||||
Provides human readable file size
|
||||
|
||||
@@ -230,12 +230,12 @@ def human_size(nbytes):
|
||||
elif suffixes[i] == 'B':
|
||||
return nbytes
|
||||
else:
|
||||
f = '{:.1f}'.format(nbytes).rstrip('0').rstrip('.')
|
||||
f = f'{nbytes:.1f}'.rstrip('0').rstrip('.')
|
||||
|
||||
return '{}{}'.format(f, suffixes[i])
|
||||
return f'{f}{suffixes[i]}'
|
||||
|
||||
|
||||
def format_duration(start, end=None):
|
||||
def format_duration(start: str, end: str = None) -> str:
|
||||
"""
|
||||
Parse a start and (optional) end datetime as ISO 8601 strings, calculate
|
||||
the difference, and return that duration as a string.
|
||||
@@ -245,6 +245,7 @@ def format_duration(start, end=None):
|
||||
|
||||
:returns: string
|
||||
"""
|
||||
|
||||
if not isinstance(start, str) or not start.strip():
|
||||
return ''
|
||||
end = end or start
|
||||
@@ -252,7 +253,7 @@ def format_duration(start, end=None):
|
||||
return str(duration)
|
||||
|
||||
|
||||
def get_path_basename(urlpath):
|
||||
def get_path_basename(urlpath: str) -> str:
|
||||
"""
|
||||
Helper function to derive file basename
|
||||
|
||||
@@ -261,14 +262,16 @@ def get_path_basename(urlpath):
|
||||
:returns: string of basename of URL path
|
||||
"""
|
||||
|
||||
return os.path.basename(urlpath)
|
||||
return Path(urlpath).name
|
||||
|
||||
|
||||
def json_serial(obj):
|
||||
def json_serial(obj: Any) -> str:
|
||||
"""
|
||||
helper function to convert to JSON non-default
|
||||
types (source: https://stackoverflow.com/a/22238613)
|
||||
|
||||
:param obj: `object` to be evaluated
|
||||
|
||||
:returns: JSON non-default type to `str`
|
||||
"""
|
||||
|
||||
@@ -290,17 +293,19 @@ def json_serial(obj):
|
||||
elif isinstance(obj, l10n.Locale):
|
||||
return l10n.locale2str(obj)
|
||||
|
||||
msg = '{} type {} not serializable'.format(obj, type(obj))
|
||||
msg = f'{obj} type {type(obj)} not serializable'
|
||||
LOGGER.error(msg)
|
||||
raise TypeError(msg)
|
||||
|
||||
|
||||
def is_url(urlstring):
|
||||
def is_url(urlstring: str) -> bool:
|
||||
"""
|
||||
Validation function that determines whether a candidate URL should be
|
||||
considered a URI. No remote resource is obtained; this does not check
|
||||
the existence of any remote resource.
|
||||
|
||||
:param urlstring: `str` to be evaluated as candidate URL.
|
||||
|
||||
:returns: `bool` of whether the URL looks like a URL.
|
||||
"""
|
||||
try:
|
||||
@@ -310,7 +315,8 @@ def is_url(urlstring):
|
||||
return False
|
||||
|
||||
|
||||
def render_j2_template(config, template, data, locale_=None):
|
||||
def render_j2_template(config: dict, template: Path,
|
||||
data: dict, locale_: str = None) -> str:
|
||||
"""
|
||||
render Jinja2 template
|
||||
|
||||
@@ -330,13 +336,13 @@ def render_j2_template(config, template, data, locale_=None):
|
||||
'jinja2.ext.autoescape'],
|
||||
autoescape=select_autoescape(['html', 'xml']))
|
||||
custom_templates = True
|
||||
LOGGER.debug('using custom templates: {}'.format(templates_path))
|
||||
LOGGER.debug(f'using custom templates: {templates_path}')
|
||||
except (KeyError, TypeError):
|
||||
env = Environment(loader=FileSystemLoader(TEMPLATES),
|
||||
extensions=['jinja2.ext.i18n',
|
||||
'jinja2.ext.autoescape'],
|
||||
autoescape=select_autoescape(['html', 'xml']))
|
||||
LOGGER.debug('using default templates: {}'.format(TEMPLATES))
|
||||
LOGGER.debug(f'using default templates: {TEMPLATES}')
|
||||
|
||||
env.filters['to_json'] = to_json
|
||||
env.filters['format_datetime'] = format_datetime
|
||||
@@ -373,7 +379,7 @@ def render_j2_template(config, template, data, locale_=None):
|
||||
data=data, locale=locale_, version=__version__)
|
||||
|
||||
|
||||
def get_mimetype(filename):
|
||||
def get_mimetype(filename: str) -> str:
|
||||
"""
|
||||
helper function to return MIME type of a given file
|
||||
|
||||
@@ -385,7 +391,7 @@ def get_mimetype(filename):
|
||||
return mimetypes.guess_type(filename)[0]
|
||||
|
||||
|
||||
def get_breadcrumbs(urlpath):
|
||||
def get_breadcrumbs(urlpath: str) -> list:
|
||||
"""
|
||||
helper function to make breadcrumbs from a URL path
|
||||
|
||||
@@ -412,7 +418,7 @@ def get_breadcrumbs(urlpath):
|
||||
return links
|
||||
|
||||
|
||||
def filter_dict_by_key_value(dict_, key, value):
|
||||
def filter_dict_by_key_value(dict_: dict, key: str, value: str) -> dict:
|
||||
"""
|
||||
helper function to filter a dict by a dict key
|
||||
|
||||
@@ -426,7 +432,7 @@ def filter_dict_by_key_value(dict_, key, value):
|
||||
return {k: v for (k, v) in dict_.items() if v[key] == value}
|
||||
|
||||
|
||||
def filter_providers_by_type(providers, type):
|
||||
def filter_providers_by_type(providers: list, type: str) -> dict:
|
||||
"""
|
||||
helper function to filter a list of providers by type
|
||||
|
||||
@@ -437,20 +443,20 @@ def filter_providers_by_type(providers, type):
|
||||
"""
|
||||
|
||||
providers_ = {provider['type']: provider for provider in providers}
|
||||
return providers_.get(type, None)
|
||||
return providers_.get(type)
|
||||
|
||||
|
||||
def get_provider_by_type(providers, provider_type):
|
||||
def get_provider_by_type(providers: list, provider_type: str) -> dict:
|
||||
"""
|
||||
helper function to load a provider by a provider type
|
||||
|
||||
:param providers: ``list`` of providers
|
||||
:param provider_type: type of provider (feature)
|
||||
:param provider_type: type of provider (e.g. feature)
|
||||
|
||||
:returns: provider based on type
|
||||
"""
|
||||
|
||||
LOGGER.debug('Searching for provider type {}'.format(provider_type))
|
||||
LOGGER.debug(f'Searching for provider type {provider_type}')
|
||||
try:
|
||||
p = (next(d for i, d in enumerate(providers)
|
||||
if d['type'] == provider_type))
|
||||
@@ -460,7 +466,7 @@ def get_provider_by_type(providers, provider_type):
|
||||
return p
|
||||
|
||||
|
||||
def get_provider_default(providers):
|
||||
def get_provider_default(providers: list) -> dict:
|
||||
"""
|
||||
helper function to get a resource's default provider
|
||||
|
||||
@@ -477,7 +483,7 @@ def get_provider_default(providers):
|
||||
LOGGER.debug('no default provider type. Returning first provider')
|
||||
default = providers[0]
|
||||
|
||||
LOGGER.debug('Default provider: {}'.format(default['type']))
|
||||
LOGGER.debug(f"Default provider: {default['type']}")
|
||||
return default
|
||||
|
||||
|
||||
@@ -494,17 +500,16 @@ class JobStatus(Enum):
|
||||
dismissed = 'dismissed'
|
||||
|
||||
|
||||
def read_data(path):
|
||||
def read_data(path: Union[Path, str]) -> Union[bytes, str]:
|
||||
"""
|
||||
helper function to read data (file or networrk)
|
||||
"""
|
||||
|
||||
LOGGER.debug('Attempting to read {}'.format(path))
|
||||
scheme = urlparse(path).scheme
|
||||
LOGGER.debug(f'Attempting to read {path}')
|
||||
|
||||
if scheme in ['', 'file']:
|
||||
if isinstance(path, Path) or not path.startswith(('http', 's3')):
|
||||
LOGGER.debug('local file on disk')
|
||||
with io.open(path, 'rb') as fh:
|
||||
with Path(path).open('rb') as fh:
|
||||
return fh.read()
|
||||
else:
|
||||
LOGGER.debug('network file')
|
||||
@@ -512,7 +517,7 @@ def read_data(path):
|
||||
return r.read()
|
||||
|
||||
|
||||
def url_join(*parts):
|
||||
def url_join(*parts: list) -> str:
|
||||
"""
|
||||
helper function to join a URL from a number of parts/fragments.
|
||||
Implemented because urllib.parse.urljoin strips subpaths from
|
||||
@@ -528,7 +533,7 @@ def url_join(*parts):
|
||||
return '/'.join([p.strip().strip('/') for p in parts])
|
||||
|
||||
|
||||
def get_envelope(coords_list: List[List[float]]):
|
||||
def get_envelope(coords_list: List[List[float]]) -> list:
|
||||
"""
|
||||
helper function to get the envelope for a given coordinates
|
||||
list through the Shapely API.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2018 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -27,8 +27,8 @@
|
||||
#
|
||||
# =================================================================
|
||||
|
||||
import io
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
from setuptools import Command, find_packages, setup
|
||||
import shutil
|
||||
@@ -58,7 +58,7 @@ class PyCleanBuild(Command):
|
||||
|
||||
for file_ in remove_files:
|
||||
try:
|
||||
os.remove(file_)
|
||||
Path(file_).unlink()
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
@@ -68,9 +68,9 @@ class PyCleanBuild(Command):
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
for file_ in os.listdir('..'):
|
||||
if file_.endswith(('.deb', '.build', '.changes')):
|
||||
os.remove('../{}'.format(file_))
|
||||
for file_ in [Path(p) for p in os.listdir('..')]:
|
||||
if file_.stem in ['.deb', '.build', '.changes']:
|
||||
os.unlink(Path('..', file_))
|
||||
|
||||
|
||||
class PyTest(Command):
|
||||
@@ -107,16 +107,20 @@ class PyCoverage(Command):
|
||||
raise SystemExit(errno)
|
||||
|
||||
|
||||
def read(filename, encoding='utf-8'):
|
||||
def read(filename):
|
||||
"""read file contents"""
|
||||
full_path = os.path.join(os.path.dirname(__file__), filename)
|
||||
with io.open(full_path, encoding=encoding) as fh:
|
||||
|
||||
fullpath = Path(__file__).resolve().parent / filename
|
||||
|
||||
with fullpath.open() as fh:
|
||||
contents = fh.read().strip()
|
||||
|
||||
return contents
|
||||
|
||||
|
||||
def get_package_version():
|
||||
"""get version from top-level package init"""
|
||||
|
||||
version_file = read('pygeoapi/__init__.py')
|
||||
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
|
||||
version_file, re.M)
|
||||
@@ -129,8 +133,9 @@ LONG_DESCRIPTION = read('README.md')
|
||||
|
||||
DESCRIPTION = 'pygeoapi provides an API to geospatial data'
|
||||
|
||||
if os.path.exists('MANIFEST'):
|
||||
os.unlink('MANIFEST')
|
||||
MANIFEST = Path('MANIFEST')
|
||||
if MANIFEST.exists():
|
||||
MANIFEST.unlink()
|
||||
|
||||
setup(
|
||||
name='pygeoapi',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2020 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -28,17 +28,17 @@
|
||||
# =================================================================
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
from elasticsearch import Elasticsearch, helpers
|
||||
es = Elasticsearch()
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print('Usage: {} <path/to/data.geojson> <id-field>'.format(sys.argv[0]))
|
||||
print(f'Usage: {sys.argv[0]} <path/to/data.geojson> <id-field>')
|
||||
sys.exit(1)
|
||||
|
||||
index_name = os.path.splitext(os.path.basename(sys.argv[1]))[0].lower()
|
||||
index_name = Path(sys.argv[1]).stem.lower()
|
||||
id_field = sys.argv[2]
|
||||
|
||||
if es.indices.exists(index_name):
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Timo Tuunanen <timo.tuunanen@rdvelho.com>
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2019 Timo Tuunanen
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -37,7 +39,7 @@ mongodb = 'testdb'
|
||||
mongocollection = 'testplaces'
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
print('Usage: {} <path/to/data.geojson>'.format(sys.argv[0]))
|
||||
print(f'Usage: {sys.argv[0]} <path/to/data.geojson>')
|
||||
sys.exit(1)
|
||||
|
||||
myclient = MongoClient(monogourl)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Benjamin Webb <benjamin.miller.webb@gmail.com>
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2021 Benjamin Webb
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -27,17 +29,17 @@
|
||||
#
|
||||
# =================================================================
|
||||
|
||||
from pathlib import Path
|
||||
import requests
|
||||
import sys
|
||||
import json
|
||||
import os.path
|
||||
|
||||
url = 'http://localhost:8080/FROST-Server/v1.1/Datastreams'
|
||||
data_url = 'https://raw.githubusercontent.com/webb-ben/data/main/'
|
||||
|
||||
|
||||
def main(path_):
|
||||
filename = os.path.basename(path_)
|
||||
def main(path_: Path):
|
||||
filename = path_.name
|
||||
r = requests.get(f'{data_url}{filename}')
|
||||
data = r.json().get('value')
|
||||
for v in data:
|
||||
@@ -65,7 +67,7 @@ def clean(dirty_dict):
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) == 1:
|
||||
print('Usage: {} <path/to/data.geojson>'.format(sys.argv[0]))
|
||||
print(f'Usage: {sys.argv[0]} <path/to/data.geojson>')
|
||||
sys.exit(1)
|
||||
|
||||
main(sys.argv[1])
|
||||
main(Path(sys.argv[1]))
|
||||
|
||||
@@ -28,8 +28,7 @@
|
||||
# =================================================================
|
||||
|
||||
from datetime import datetime
|
||||
from glob import glob
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from typing import Union
|
||||
|
||||
@@ -39,14 +38,14 @@ from tinydb import TinyDB
|
||||
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print('Usage: {} <path/to/xml-files> <output.db>'.format(sys.argv[0]))
|
||||
print(f'Usage: {sys.argv[0]} <path/to/xml-files> <output.db>')
|
||||
sys.exit(1)
|
||||
|
||||
xml_dir = sys.argv[1]
|
||||
index_name = sys.argv[2]
|
||||
xml_dir = Path(sys.argv[1])
|
||||
index_name = Path(sys.argv[2])
|
||||
|
||||
if os.path.exists(index_name):
|
||||
os.remove(index_name)
|
||||
if index_name.exists():
|
||||
index_name.unlink()
|
||||
|
||||
db = TinyDB(index_name)
|
||||
|
||||
@@ -124,7 +123,7 @@ def get_anytext(bag: Union[list, str]) -> str:
|
||||
return ' '.join(text_bag)
|
||||
|
||||
|
||||
for xml_file in glob('{}/*.xml'.format(xml_dir)):
|
||||
for xml_file in xml_dir.glob('*.xml'):
|
||||
m = MD_Metadata(etree.parse(xml_file))
|
||||
|
||||
_raw_metadata = m.xml.decode('utf-8')
|
||||
@@ -231,7 +230,6 @@ for xml_file in glob('{}/*.xml'.format(xml_dir)):
|
||||
|
||||
try:
|
||||
res = db.insert(json_record)
|
||||
print('Metadata record {} loaded with internal id {}'.format(
|
||||
xml_file, res))
|
||||
print(f'Metadata record {xml_file} loaded with internal id {res}')
|
||||
except Exception as err:
|
||||
print(err)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Francesco Bartoli <xbartolone@gmail.com>
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2020 Francesco Bartoli
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -103,10 +105,10 @@ def test_query_hits_vsicurl(config_vsicurl_csv):
|
||||
|
||||
p = OGRProvider(config_vsicurl_csv)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits > 100
|
||||
|
||||
@@ -118,10 +120,10 @@ def test_query_bbox_hits_vsicurl(config_vsicurl_csv):
|
||||
feature_collection = p.query(
|
||||
bbox=[10.497565, 41.520355, 15.111823, 43.308645],
|
||||
resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits > 1
|
||||
|
||||
@@ -131,15 +133,15 @@ def test_query_with_limit_vsicurl(config_vsicurl_csv):
|
||||
|
||||
p = OGRProvider(config_vsicurl_csv)
|
||||
feature_collection = p.query(limit=2, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 2
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -148,17 +150,17 @@ def test_query_with_offset_vsicurl(config_vsicurl_csv):
|
||||
|
||||
p = OGRProvider(config_vsicurl_csv)
|
||||
feature_collection = p.query(offset=20, limit=10, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 10
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
assert feature['id'] == 21
|
||||
assert 'Veneto' in properties['denominazione_regione']
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -169,8 +171,8 @@ def test_query_with_property_vsicurl(config_vsicurl_csv):
|
||||
feature_collection = p.query(
|
||||
offset=20, limit=10, resulttype='results',
|
||||
properties=[('denominazione_regione', 'Lazio')])
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 10
|
||||
for feature in features:
|
||||
assert 'Lazio' in feature['properties']['denominazione_regione']
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Francesco Bartoli <xbartolone@gmail.com>
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2020 Francesco Bartoli
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -75,7 +77,7 @@ def config_random_id(config_ArcGIS_ESRIJSON):
|
||||
p = OGRProvider(config_ArcGIS_ESRIJSON)
|
||||
# Get bunch of features to randomly have an id
|
||||
feature_collection = p.query(offset=0, limit=10, resulttype='results')
|
||||
features = feature_collection.get('features', None)
|
||||
features = feature_collection.get('features')
|
||||
features_list = []
|
||||
for feature in features:
|
||||
features_list.append(feature['id'])
|
||||
@@ -117,10 +119,10 @@ def test_query_hits_agol(config_ArcGIS_ESRIJSON):
|
||||
|
||||
p = OGRProvider(config_ArcGIS_ESRIJSON)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits > 100
|
||||
|
||||
@@ -133,10 +135,10 @@ def test_query_bbox_hits_agol(config_ArcGIS_ESRIJSON):
|
||||
bbox=[-9822165.181154, 5112669.004249,
|
||||
-9807305.104750, 5133712.297986],
|
||||
resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits > 1
|
||||
|
||||
@@ -146,15 +148,15 @@ def test_query_with_limit_agol(config_ArcGIS_ESRIJSON):
|
||||
|
||||
p = OGRProvider(config_ArcGIS_ESRIJSON)
|
||||
feature_collection = p.query(limit=2, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 2
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -163,14 +165,14 @@ def test_query_with_offset(config_ArcGIS_ESRIJSON):
|
||||
|
||||
p = OGRProvider(config_ArcGIS_ESRIJSON)
|
||||
feature_collection = p.query(offset=10, limit=10, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 10
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
assert properties['fulladdr'] is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Just van den Broecke <justb4@gmail.com>
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2019 Just van den Broecke
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -64,13 +66,13 @@ def test_query(config_poi_portugal):
|
||||
|
||||
p = OGRProvider(config_poi_portugal)
|
||||
feature_collection = p.query()
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert features is not None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -164,10 +166,10 @@ def test_query_hits_28992(config_gpkg_28992):
|
||||
|
||||
p = OGRProvider(config_gpkg_28992)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits == 2481
|
||||
|
||||
@@ -177,10 +179,10 @@ def test_query_hits_4326(config_gpkg_4326):
|
||||
|
||||
p = OGRProvider(config_gpkg_4326)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits == 2481
|
||||
|
||||
@@ -193,10 +195,10 @@ def test_query_bbox_hits_4326(config_gpkg_4326):
|
||||
# bbox=[120000, 480000, 124000, 487000], resulttype='hits')
|
||||
feature_collection = p.query(
|
||||
bbox=[5.763409, 52.060197, 5.769256, 52.061976], resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits == 1
|
||||
|
||||
@@ -210,10 +212,10 @@ def test_query_bbox_hits_28992(config_gpkg_28992):
|
||||
feature_collection = p.query(
|
||||
bbox=[5.763409, 52.060197, 5.769256, 52.061976], resulttype='hits')
|
||||
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits == 1
|
||||
|
||||
@@ -226,15 +228,15 @@ def test_query_bbox_28992(config_gpkg_28992):
|
||||
# bbox=[180800, 452500, 181200, 452700], resulttype='results')
|
||||
feature_collection = p.query(
|
||||
bbox=(5.763409, 52.060197, 5.769256, 52.061976), resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 1
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Planken Wambuisweg'
|
||||
|
||||
@@ -247,15 +249,15 @@ def test_query_bbox_4326(config_gpkg_4326):
|
||||
# bbox=[180800, 452500, 181200, 452700], resulttype='results')
|
||||
feature_collection = p.query(
|
||||
bbox=(5.763409, 52.060197, 5.769256, 52.061976), resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 1
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Planken Wambuisweg'
|
||||
|
||||
@@ -265,15 +267,15 @@ def test_query_with_limit_28992(config_gpkg_28992):
|
||||
|
||||
p = OGRProvider(config_gpkg_28992)
|
||||
feature_collection = p.query(limit=2, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 2
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -282,15 +284,15 @@ def test_query_with_limit_4326(config_gpkg_4326):
|
||||
|
||||
p = OGRProvider(config_gpkg_4326)
|
||||
feature_collection = p.query(limit=5, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -299,17 +301,17 @@ def test_query_with_offset_28992(config_gpkg_28992):
|
||||
|
||||
p = OGRProvider(config_gpkg_28992)
|
||||
feature_collection = p.query(offset=20, limit=5, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
assert feature['id'] == 'inspireadressen.1744969'
|
||||
assert 'Egypte' in properties['straatnaam']
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -318,17 +320,17 @@ def test_query_with_offset_4326(config_gpkg_4326):
|
||||
|
||||
p = OGRProvider(config_gpkg_4326)
|
||||
feature_collection = p.query(offset=20, limit=5, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
assert feature['id'] == 'inspireadressen.1744969'
|
||||
assert 'Egypte' in properties['straatnaam']
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -340,15 +342,15 @@ def test_query_bbox_with_offset_28992(config_gpkg_28992):
|
||||
offset=10, limit=5,
|
||||
bbox=(5.742, 52.053, 5.773, 52.098),
|
||||
resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Buurtweg'
|
||||
assert properties['huisnummer'] == '4'
|
||||
@@ -362,15 +364,15 @@ def test_query_bbox_with_offset_4326(config_gpkg_4326):
|
||||
offset=1, limit=5,
|
||||
bbox=(5.742, 52.053, 5.773, 52.098),
|
||||
resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Egypte'
|
||||
assert properties['huisnummer'] == '6'
|
||||
@@ -387,8 +389,8 @@ def test_query_with_property_filtering(config_gpkg_4326):
|
||||
]
|
||||
)
|
||||
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) > 1
|
||||
|
||||
for feature in features:
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Just van den Broecke <justb4@gmail.com>
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2019 Just van den Broecke
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -120,10 +122,10 @@ def test_query_hits_28992(config_shapefile_28992):
|
||||
|
||||
p = OGRProvider(config_shapefile_28992)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits == 2481
|
||||
|
||||
@@ -133,10 +135,10 @@ def test_query_hits_4326(config_shapefile_4326):
|
||||
|
||||
p = OGRProvider(config_shapefile_4326)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits == 2481
|
||||
|
||||
@@ -149,10 +151,10 @@ def test_query_bbox_hits_4326(config_shapefile_4326):
|
||||
# bbox=[120000, 480000, 124000, 487000], resulttype='hits')
|
||||
feature_collection = p.query(
|
||||
bbox=[5.763409, 52.060197, 5.769256, 52.061976], resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits == 1
|
||||
|
||||
@@ -166,10 +168,10 @@ def test_query_bbox_hits_28992(config_shapefile_28992):
|
||||
feature_collection = p.query(
|
||||
bbox=[5.763409, 52.060197, 5.769256, 52.061976], resulttype='hits')
|
||||
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits == 1
|
||||
|
||||
@@ -182,15 +184,15 @@ def test_query_bbox_28992(config_shapefile_28992):
|
||||
# bbox=[180800, 452500, 181200, 452700], resulttype='results')
|
||||
feature_collection = p.query(
|
||||
bbox=(5.763409, 52.060197, 5.769256, 52.061976), resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 1
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Planken Wambuisweg'
|
||||
|
||||
@@ -203,15 +205,15 @@ def test_query_bbox_4326(config_shapefile_4326):
|
||||
# bbox=[180800, 452500, 181200, 452700], resulttype='results')
|
||||
feature_collection = p.query(
|
||||
bbox=(5.763409, 52.060197, 5.769256, 52.061976), resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 1
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Planken Wambuisweg'
|
||||
|
||||
@@ -221,15 +223,15 @@ def test_query_with_limit_28992(config_shapefile_28992):
|
||||
|
||||
p = OGRProvider(config_shapefile_28992)
|
||||
feature_collection = p.query(limit=2, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 2
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -238,15 +240,15 @@ def test_query_with_limit_4326(config_shapefile_4326):
|
||||
|
||||
p = OGRProvider(config_shapefile_4326)
|
||||
feature_collection = p.query(limit=5, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -255,17 +257,17 @@ def test_query_with_offset_28992(config_shapefile_28992):
|
||||
|
||||
p = OGRProvider(config_shapefile_28992)
|
||||
feature_collection = p.query(offset=20, limit=5, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
assert feature['id'] == 'inspireadressen.1744969'
|
||||
assert 'Egypte' in properties['straatnaam']
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -274,17 +276,17 @@ def test_query_with_offset_4326(config_shapefile_4326):
|
||||
|
||||
p = OGRProvider(config_shapefile_4326)
|
||||
feature_collection = p.query(offset=20, limit=5, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
assert feature['id'] == 'inspireadressen.1744969'
|
||||
assert 'Egypte' in properties['straatnaam']
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -296,15 +298,15 @@ def test_query_bbox_with_offset_28992(config_shapefile_28992):
|
||||
offset=10, limit=5,
|
||||
bbox=(5.742, 52.053, 5.773, 52.098),
|
||||
resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Buurtweg'
|
||||
assert properties['huisnummer'] == '4'
|
||||
@@ -318,15 +320,15 @@ def test_query_bbox_with_offset_4326(config_shapefile_4326):
|
||||
offset=1, limit=5,
|
||||
bbox=(5.742, 52.053, 5.773, 52.098),
|
||||
resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Egypte'
|
||||
assert properties['huisnummer'] == '6'
|
||||
@@ -343,8 +345,8 @@ def test_query_with_property_filtering(config_shapefile_4326):
|
||||
]
|
||||
)
|
||||
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) > 1
|
||||
|
||||
for feature in features:
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Just van den Broecke <justb4@gmail.com>
|
||||
# Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2019 Just van den Broecke
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -92,10 +94,10 @@ def test_query_hits_4326(config_sqlite_4326):
|
||||
|
||||
p = OGRProvider(config_sqlite_4326)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits == 2481
|
||||
|
||||
@@ -108,10 +110,10 @@ def test_query_bbox_hits_4326(config_sqlite_4326):
|
||||
# bbox=[120000, 480000, 124000, 487000], resulttype='hits')
|
||||
feature_collection = p.query(
|
||||
bbox=[5.763409, 52.060197, 5.769256, 52.061976], resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits == 1
|
||||
|
||||
@@ -124,15 +126,15 @@ def test_query_bbox_4326(config_sqlite_4326):
|
||||
# bbox=[180800, 452500, 181200, 452700], resulttype='results')
|
||||
feature_collection = p.query(
|
||||
bbox=(5.763409, 52.060197, 5.769256, 52.061976), resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 1
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Planken Wambuisweg'
|
||||
|
||||
@@ -142,15 +144,15 @@ def test_query_with_limit_4326(config_sqlite_4326):
|
||||
|
||||
p = OGRProvider(config_sqlite_4326)
|
||||
feature_collection = p.query(limit=5, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -159,17 +161,17 @@ def test_query_with_offset_4326(config_sqlite_4326):
|
||||
|
||||
p = OGRProvider(config_sqlite_4326)
|
||||
feature_collection = p.query(offset=20, limit=5, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
assert feature['id'] == 'inspireadressen.1744969'
|
||||
assert 'Egypte' in properties['straatnaam']
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -181,15 +183,15 @@ def test_query_bbox_with_offset_4326(config_sqlite_4326):
|
||||
offset=1, limit=50,
|
||||
bbox=(5.742, 52.053, 5.773, 52.098),
|
||||
resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 3
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Egypte'
|
||||
assert properties['huisnummer'] == '4'
|
||||
@@ -206,8 +208,8 @@ def test_query_with_property_filtering(config_sqlite_4326):
|
||||
]
|
||||
)
|
||||
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) > 1
|
||||
|
||||
for feature in features:
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#
|
||||
# Copyright (c) 2019 Just van den Broecke
|
||||
# Copyright (c) 2020 Francesco Bartoli
|
||||
# Copyright (c) 2020 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -259,10 +259,10 @@ def test_query_hits_ms(config_MapServer_WFS_cities):
|
||||
|
||||
p = OGRProvider(config_MapServer_WFS_cities)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits > 5000
|
||||
|
||||
@@ -272,10 +272,10 @@ def test_query_hits_geosol_gs(config_geosol_gs_WFS):
|
||||
|
||||
p = OGRProvider(config_geosol_gs_WFS)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits == 186
|
||||
|
||||
@@ -286,10 +286,10 @@ def test_query_hits_geosol_gs(config_geosol_gs_WFS):
|
||||
#
|
||||
# p = OGRProvider(config_MapServer_WFS_continents)
|
||||
# feature_collection = p.query(resulttype='hits')
|
||||
# assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
# features = feature_collection.get('features', None)
|
||||
# assert feature_collection.get('type') == 'FeatureCollection'
|
||||
# features = feature_collection.get('features')
|
||||
# assert len(features) == 0
|
||||
# hits = feature_collection.get('numberMatched', None)
|
||||
# hits = feature_collection.get('numberMatched')
|
||||
# assert hits is not None
|
||||
# assert hits > 8000000
|
||||
|
||||
@@ -301,10 +301,10 @@ def test_query_bbox_hits_ms(config_MapServer_WFS_cities):
|
||||
feature_collection = p.query(
|
||||
bbox=[-47, -24, -45, -22], resulttype='hits')
|
||||
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits > 1
|
||||
|
||||
@@ -315,10 +315,10 @@ def test_query_bbox_hits_gs(config_MapServer_WFS_continents):
|
||||
p = OGRProvider(config_MapServer_WFS_continents)
|
||||
feature_collection = p.query(bbox=[-61, 46, -60, 47], resulttype='hits')
|
||||
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits == 3
|
||||
|
||||
@@ -332,10 +332,10 @@ def test_query_bbox_hits_geosol_gs(config_geosol_gs_WFS):
|
||||
# feature_collection = p.query(bbox=(
|
||||
# 5.763409, 52.060197, 5.769256, 52.061976), resulttype='hits')
|
||||
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is not None
|
||||
assert hits == 1
|
||||
|
||||
@@ -348,15 +348,15 @@ def test_query_bbox_ms(config_MapServer_WFS_cities):
|
||||
# bbox=[120000, 480000, 124000, 487000], resulttype='results')
|
||||
feature_collection = p.query(
|
||||
bbox=[4.874016, 52.306852, 4.932020, 52.370004], resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) > 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -365,15 +365,15 @@ def test_query_bbox_gs(config_MapServer_WFS_continents):
|
||||
|
||||
p = OGRProvider(config_MapServer_WFS_continents)
|
||||
feature_collection = p.query(bbox=(5, 52, 6, 53), resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 4
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
assert properties['NA2DESC'] == 'Netherlands'
|
||||
assert properties['NA3DESC'] == 'Europe'
|
||||
@@ -388,16 +388,16 @@ def test_query_bbox_geosol_gs(config_geosol_gs_WFS):
|
||||
feature_collection = p.query(
|
||||
bbox=(681417.0, 4849032.0, 681417.3, 4849032.3),
|
||||
resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 1
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
assert properties['sito'] == 'Centro storico di Firenze'
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -406,15 +406,15 @@ def test_query_with_limit_ms(config_MapServer_WFS_cities):
|
||||
|
||||
p = OGRProvider(config_MapServer_WFS_cities)
|
||||
feature_collection = p.query(limit=2, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 2
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -423,17 +423,17 @@ def test_query_with_offset(config_MapServer_WFS_cities):
|
||||
|
||||
p = OGRProvider(config_MapServer_WFS_cities)
|
||||
feature_collection = p.query(offset=20, limit=5, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
hits = feature_collection.get('numberMatched')
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
assert feature['id'] == 'cities.411'
|
||||
assert '6610764' in properties['POPULATION']
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# Colin Blackburn <colb@bgs.ac.uk>
|
||||
#
|
||||
# Copyright (c) 2019 Just van den Broecke
|
||||
# Copyright (c) 2019 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
# Copyright (c) 2022 John A Stevenson and Colin Blackburn
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
@@ -73,13 +73,13 @@ def test_query(config):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
p = PostgreSQLProvider(config)
|
||||
feature_collection = p.query()
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert features is not None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -97,14 +97,14 @@ def test_query_with_property_filter(config):
|
||||
"""Test query valid features when filtering by property"""
|
||||
p = PostgreSQLProvider(config)
|
||||
feature_collection = p.query(properties=[("waterway", "stream")])
|
||||
features = feature_collection.get('features', None)
|
||||
features = feature_collection.get('features')
|
||||
stream_features = list(
|
||||
filter(lambda feature: feature['properties']['waterway'] == 'stream',
|
||||
features))
|
||||
assert (len(features) == len(stream_features))
|
||||
|
||||
feature_collection = p.query(limit=50)
|
||||
features = feature_collection.get('features', None)
|
||||
features = feature_collection.get('features')
|
||||
stream_features = list(
|
||||
filter(lambda feature: feature['properties']['waterway'] == 'stream',
|
||||
features))
|
||||
@@ -127,7 +127,7 @@ def test_query_with_config_properties(config):
|
||||
assert provider.properties == properties_subset
|
||||
result = provider.query()
|
||||
feature = result.get('features')[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
for property_name in properties.keys():
|
||||
assert property_name in config["properties"]
|
||||
|
||||
@@ -240,9 +240,9 @@ def test_query_cql(config, cql, expected_ids):
|
||||
provider = PostgreSQLProvider(config)
|
||||
|
||||
feature_collection = provider.query(filterq=ast)
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
|
||||
features = feature_collection.get('features', None)
|
||||
features = feature_collection.get('features')
|
||||
ids = [feature["id"] for feature in features]
|
||||
assert ids == expected_ids
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2019 Just van den Broecke
|
||||
# Copyright (c) 2019 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -66,13 +66,13 @@ def test_query_sqlite(config_sqlite):
|
||||
|
||||
p = SQLiteGPKGProvider(config_sqlite)
|
||||
feature_collection = p.query()
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert features is not None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -81,13 +81,13 @@ def test_query_geopackage(config_geopackage):
|
||||
|
||||
p = SQLiteGPKGProvider(config_geopackage)
|
||||
feature_collection = p.query()
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert feature_collection.get('type') == 'FeatureCollection'
|
||||
features = feature_collection.get('features')
|
||||
assert features is not None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
properties = feature.get('properties')
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
geometry = feature.get('geometry')
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ def test_query_with_property_filter_sqlite_geopackage(config_sqlite):
|
||||
p = SQLiteGPKGProvider(config_sqlite)
|
||||
feature_collection = p.query(properties=[
|
||||
("continent", "Europe")], limit=100)
|
||||
features = feature_collection.get('features', None)
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 39
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ def test_query_with_property_filter_bbox_sqlite_geopackage(config_sqlite):
|
||||
p = SQLiteGPKGProvider(config_sqlite)
|
||||
feature_collection = p.query(properties=[("continent", "Europe")],
|
||||
bbox=[29.3373, -3.4099, 29.3761, -3.3924])
|
||||
features = feature_collection.get('features', None)
|
||||
features = feature_collection.get('features')
|
||||
assert len(features) == 0
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Martin Pontius <m.pontius@52north.org>
|
||||
# Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2022 52°North Spatial Information Research GmbH
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -27,7 +29,7 @@
|
||||
#
|
||||
# =================================================================
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from werkzeug.wrappers import Request
|
||||
from werkzeug.test import create_environ
|
||||
@@ -79,10 +81,10 @@ def _create_request(name, message, locales):
|
||||
|
||||
|
||||
def test_async_hello_world_process_parallel(api_, config):
|
||||
index_name = config['server']['manager']['connection']
|
||||
index_name = Path(config['server']['manager']['connection'])
|
||||
|
||||
if os.path.exists(index_name):
|
||||
os.remove(index_name)
|
||||
if index_name.exists():
|
||||
index_name.unlink()
|
||||
|
||||
NUM_PROCS = 4
|
||||
process_id = "hello-world"
|
||||
@@ -118,10 +120,8 @@ def test_async_hello_world_process_parallel(api_, config):
|
||||
assert job_dict["mimetype"] == process_out['headers'][
|
||||
'Content-Type']
|
||||
try:
|
||||
with open(
|
||||
"{}/hello-world-{}".format(os.path.dirname(index_name),
|
||||
job_id)) as json_file:
|
||||
out_json = json.load(json_file)
|
||||
with open(f'{index_name.parent()}/hello-world-{job_id}') as fh:
|
||||
out_json = json.load(fh)
|
||||
assert out_json["id"] == "echo"
|
||||
assert out_json["value"] == "Hello World! Hello"
|
||||
except FileNotFoundError as e:
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
# Copyright (c) 2022 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -27,8 +27,8 @@
|
||||
#
|
||||
# =================================================================
|
||||
|
||||
import os
|
||||
import logging
|
||||
import os.path
|
||||
|
||||
from werkzeug.test import create_environ
|
||||
from werkzeug.wrappers import Request
|
||||
@@ -37,7 +37,7 @@ from werkzeug.datastructures import ImmutableMultiDict
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_test_file_path(filename):
|
||||
def get_test_file_path(filename: str) -> str:
|
||||
"""helper function to open test file safely"""
|
||||
|
||||
if os.path.isfile(filename):
|
||||
|
||||
Reference in New Issue
Block a user