Skip to content

Commit 93e5bfc

Browse files
committed
Fix bugs, improve CSV parsing, cleanup, add join_util tests
1 parent ee9ff77 commit 93e5bfc

File tree

4 files changed

+1516
-166
lines changed

4 files changed

+1516
-166
lines changed

pygeoapi/api/joins.py

Lines changed: 12 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -194,74 +194,10 @@ def get_oas_30(cfg: dict, locale: str) -> tuple[list[dict[str, str]], dict[str,
194194
}
195195
}
196196

197-
# Key value endpoint
198-
# See https://github.com/opengeospatial/ogcapi-joins/blob/master/sources/core/openapi/schemas/collectionKeyField.yaml # noqa
199-
key_field_param = {
200-
'name': 'keyFieldId',
201-
'in': 'path',
202-
'description': 'identifier of a key field',
203-
'required': True,
204-
'schema': {
205-
'type': 'string'
206-
}
207-
}
208-
description = f'Return all available {title} join key values'
209-
paths[f'/collections/{k}/keys/{{keyFieldId}}'] = {
210-
'get': {
211-
'summary': f'Get {title} values for a given join key field id',
212-
'description': description,
213-
'tags': [k, API_NAME],
214-
'operationId': f'get{k.capitalize()}KeyValues',
215-
'parameters': [
216-
key_field_param,
217-
{'$ref': '#/components/parameters/f'},
218-
# {'$ref': '#/components/parameters/lang'},
219-
],
220-
'responses': {
221-
'200': {
222-
'description': 'Response',
223-
'content': {
224-
'application/json': {
225-
'schema': {
226-
'type': 'object',
227-
'required': [
228-
'keyField',
229-
'values',
230-
'links'
231-
],
232-
'properties': {
233-
'links': links_conf,
234-
'keyField': {
235-
'type': 'string'
236-
},
237-
'values': {
238-
'type': 'array',
239-
'items': {
240-
'oneOf': [
241-
{'type': 'integer'},
242-
{'type': 'string'}
243-
]
244-
}
245-
},
246-
'numberMatched': {
247-
'type': 'integer'
248-
},
249-
'numberReturned': {
250-
'type': 'integer'
251-
}
252-
}
253-
}
254-
}
255-
}
256-
}
257-
},
258-
}
259-
}
260-
261197
# Joins endpoints (list and create)
262198
paths[f'/collections/{k}/{API_NAME}'] = {
263199
'get': {
264-
'summary': 'Get all available joins',
200+
'summary': 'Get all available join sources',
265201
'description': 'Lists all available joins for this collection',
266202
'tags': [k, API_NAME],
267203
'operationId': f'get{k.capitalize()}Joins',
@@ -581,10 +517,10 @@ def get_oas_30(cfg: dict, locale: str) -> tuple[list[dict[str, str]], dict[str,
581517
}
582518
paths[f'/collections/{k}/{API_NAME}/{{joinId}}'] = {
583519
'get': {
584-
'summary': 'Get join status',
585-
'description': 'Returns the status of an executed join',
520+
'summary': 'Get join source details',
521+
'description': 'Returns the metadata for an uploaded CSV',
586522
'tags': [k, API_NAME],
587-
'operationId': f'get{k.capitalize()}JoinStatus',
523+
'operationId': f'get{k.capitalize()}JoinSourceDetails',
588524
'parameters': [
589525
join_id_param,
590526
{'$ref': '#/components/parameters/f'},
@@ -607,10 +543,10 @@ def get_oas_30(cfg: dict, locale: str) -> tuple[list[dict[str, str]], dict[str,
607543
'500': {'$ref': '#/components/responses/ServerError'}
608544
},
609545
'delete': {
610-
'summary': 'Delete a join with the given id',
611-
'description': 'Deletes a join with the given id',
546+
'summary': 'Delete a join source with the given id',
547+
'description': 'Deletes a join source with the given id',
612548
'tags': [k, API_NAME],
613-
'operationId': f'delete{k.capitalize()}Join',
549+
'operationId': f'delete{k.capitalize()}JoinSource',
614550
'parameters': [
615551
join_id_param,
616552
{'$ref': '#/components/parameters/f'},
@@ -634,32 +570,7 @@ def get_oas_30(cfg: dict, locale: str) -> tuple[list[dict[str, str]], dict[str,
634570
}
635571
}
636572

637-
# Join results endpoint
638-
paths[f'/collections/{k}/{API_NAME}/{{joinId}}/results'] = {
639-
'get': {
640-
'summary': 'Get results for a join with the given id',
641-
'description': 'Returns the output data of an established join', # noqa
642-
'tags': [k, API_NAME],
643-
'operationId': f'get{k.capitalize()}JoinResult',
644-
'parameters': [
645-
join_id_param,
646-
{'$ref': '#/components/parameters/f'},
647-
# {'$ref': '#/components/parameters/lang'},
648-
],
649-
'responses': {
650-
'200': {
651-
'description': 'Response',
652-
'content': {
653-
'application/json': {
654-
'schema': {
655-
'type': 'object'
656-
}
657-
} # TODO: paginated response
658-
}
659-
}
660-
}
661-
}
662-
}
573+
# TODO: inject joinId parameter for OGC API - Features /items?
663574

664575
return [{'name': API_NAME}], {'paths': paths}
665576

@@ -730,8 +641,8 @@ def list_joins(api: API, request: APIRequest,
730641
return _server_error(api, request, headers, str(e))
731642

732643
if not sources:
733-
return _server_error(api, request, headers,
734-
f'No joins found for collection: {dataset}')
644+
return _not_found(api, request, headers,
645+
f'No joins found for collection: {dataset}')
735646

736647
# Build the joins list with proper structure
737648
joins_list = []
@@ -850,11 +761,13 @@ def create_join(api: API, request: APIRequest,
850761
headers, collections, dataset = _prepare(api, request, dataset)
851762

852763
if not api.supports_joins:
764+
# TODO: perhaps a 406 Not Acceptable would be better?
853765
msg = 'OGC API - Joins is not available on this instance'
854766
return _server_error(api, request, headers, msg)
855767

856768
if not request.supports_formdata:
857769
# i.e. python-multipart library is not installed for Starlette
770+
# TODO: perhaps a 406 Not Acceptable would be better?
858771
msg = 'multipart/form-data requests are not supported on this instance'
859772
return _server_error(api, request, headers, msg)
860773

pygeoapi/flask_app.py

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -417,23 +417,6 @@ def get_collection_key_fields(collection_id):
417417
return execute_from_flask(joins_api.key_fields, request, collection_id)
418418

419419

420-
# TODO: Why is this needed?
421-
# @BLUEPRINT.route('/collections/<path:collection_id>/keys/<keyFieldId>')
422-
# def get_collection_key_values(collection_id, keyFieldId):
423-
# """
424-
# OGC API - Joins: collection key values endpoint
425-
#
426-
# :param collection_id: collection identifier
427-
# :param keyFieldId: key field identifier
428-
#
429-
# :returns: HTTP response
430-
# """
431-
#
432-
# return execute_from_flask(joins_api.key_values, request, collection_id,
433-
# keyFieldId)
434-
435-
436-
# TODO: add @BLUEPRINT.route('/joins', methods=['GET']) for convenience?
437420
@BLUEPRINT.route('/collections/<path:collection_id>/joins', methods=['GET', 'POST']) # noqa
438421
@BLUEPRINT.route('/collections/<path:collection_id>/joins/<joinId>', methods=['GET', 'DELETE']) # noqa
439422
def joins(collection_id, joinId=None):

0 commit comments

Comments
 (0)