add support for provider plugin schemas (#1022)

This commit is contained in:
Tom Kralidis
2022-10-19 15:43:57 -04:00
committed by GitHub
parent ad3e224f62
commit 6447493a76
5 changed files with 81 additions and 25 deletions
+4
View File
@@ -94,6 +94,10 @@ The below template provides a minimal example (let's call the file ``mycoolvecto
}]
}
def get_schema():
# return a `dict` of a JSON schema (inline or reference)
return ('application/geo+json', {'$ref': 'https://geojson.org/schema/Feature.json'})
For brevity, the above code will always return the single feature of the dataset. In reality, the plugin
developer would connect to a data source with capabilities to run queries and return a relevant result set,
+2 -2
View File
@@ -1920,7 +1920,7 @@ class API:
LOGGER.debug('Creating item')
try:
identifier = p.create(request.data)
except ProviderInvalidDataError as err:
except (ProviderInvalidDataError, TypeError) as err:
msg = str(err)
return self.get_exception(
400, headers, request.format, 'InvalidParameterValue', msg)
@@ -1934,7 +1934,7 @@ class API:
LOGGER.debug('Updating item')
try:
_ = p.update(identifier, request.data)
except ProviderGenericError as err:
except (ProviderInvalidDataError, TypeError) as err:
msg = str(err)
return self.get_exception(
400, headers, request.format, 'InvalidParameterValue', msg)
+50 -18
View File
@@ -39,7 +39,7 @@ import yaml
from pygeoapi import __version__
from pygeoapi import l10n
from pygeoapi.plugin import load_plugin
from pygeoapi.provider.base import ProviderTypeError
from pygeoapi.provider.base import ProviderTypeError, SchemaType
from pygeoapi.util import (filter_dict_by_key_value, get_provider_by_type,
filter_providers_by_type, to_json, yaml_load)
@@ -523,19 +523,21 @@ def get_oas_30(cfg):
if p.editable:
LOGGER.debug('Provider is editable; adding post')
paths[items_path]['post'] = {
'summary': 'Add {} items'.format(title), # noqa
'description': desc,
'tags': [name],
'operationId': 'add{}Features'.format(name.capitalize()),
'consumes': ['application/json'],
'produces': ['application/json'],
'parameters': [{
'in': 'body',
'name': 'body',
'requestBody': {
'description': 'Adds item to collection',
'required': True,
}],
'content': {
'application/json': {
'schema': {}
}
},
'required': True
},
'responses': {
'201': {'description': 'Successful creation'},
'400': {'$ref': '{}#/components/responses/InvalidParameter'.format(OPENAPI_YAML['oapif'])}, # noqa
@@ -543,6 +545,14 @@ def get_oas_30(cfg):
}
}
try:
schema_ref = p.get_schema(SchemaType.create)
paths[items_path]['post']['requestBody']['content'][schema_ref[0]] = { # noqa
'schema': schema_ref[1]
}
except Exception as err:
LOGGER.debug(err)
if ptype == 'record':
paths[items_path]['get']['parameters'].append(
{'$ref': '{}/parameters/q.yaml'.format(OPENAPI_YAML['oapir'])}) # noqa
@@ -631,36 +641,58 @@ def get_oas_30(cfg):
}
}
try:
schema_ref = p.get_schema()
paths['{}/items/{{featureId}}'.format(collection_name_path)]['get']['responses']['200'] = { # noqa
'content': {
schema_ref[0]: {
'schema': schema_ref[1]
}
}
}
except Exception as err:
LOGGER.debug(err)
if p.editable:
LOGGER.debug('Provider is editable; adding put/delete')
paths['{}/items/{{featureId}}'.format(collection_name_path)]['put'] = { # noqa
put_path = '{}/items/{{featureId}}'.format(collection_name_path) # noqa
paths[put_path]['put'] = { # noqa
'summary': 'Update {} items'.format(title),
'description': desc,
'tags': [name],
'operationId': 'update{}Features'.format(name.capitalize()), # noqa
'consumes': ['application/json'],
'produces': ['application/json'],
'parameters': [
{'$ref': '{}#/components/parameters/featureId'.format(OPENAPI_YAML['oapif'])}, # noqa
{
'in': 'body',
'name': 'body',
'description': 'Updates item in collection',
'required': True,
}
],
'requestBody': {
'description': 'Updates item in collection',
'content': {
'application/json': {
'schema': {}
}
},
'required': True
},
'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
}
}
try:
schema_ref = p.get_schema(SchemaType.replace)
paths[put_path]['put']['requestBody']['content'][schema_ref[0]] = { # noqa
'schema': schema_ref[1]
}
except Exception as err:
LOGGER.debug(err)
paths['{}/items/{{featureId}}'.format(collection_name_path)]['delete'] = { # noqa
'summary': 'Delete {} items'.format(title),
'description': desc,
'tags': [name],
'operationId': 'delete{}Features'.format(name.capitalize()), # noqa
'produces': ['application/json'],
'parameters': [
{'$ref': '{}#/components/parameters/featureId'.format(OPENAPI_YAML['oapif'])}, # noqa
],
+20
View File
@@ -29,10 +29,18 @@
import json
import logging
from enum import Enum
LOGGER = logging.getLogger(__name__)
class SchemaType(Enum):
item = 'item'
create = 'create'
update = 'update'
replace = 'replace'
class BaseProvider:
"""generic Provider ABC"""
@@ -79,6 +87,18 @@ class BaseProvider:
raise NotImplementedError()
def get_schema(self, schema_type: SchemaType = SchemaType.item):
"""
Get provider schema model
:param schema_type: `SchemaType` of schema (default is 'item')
:returns: tuple pair of `str` of media type and `dict` of schema
(i.e. JSON Schema)
"""
raise NotImplementedError()
def get_data_path(self, baseurl, urlpath, dirpath):
"""
Gets directory listing or file description or raw file dump
+5 -5
View File
@@ -4,9 +4,9 @@
<head>
<meta charset="UTF-8">
<title>Swagger UI - {{ config['metadata']['identification']['title'] }}</title>
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3.28.0/swagger-ui.css" >
<link rel="icon" type="image/png" href="https://unpkg.com/swagger-ui-dist@3.28.0/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="https://unpkg.com/swagger-ui-dist@3.28.0/favicon-16x16.png" sizes="16x16" />
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist/swagger-ui.css" >
<link rel="icon" type="image/png" href="https://unpkg.com/swagger-ui-dist/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="https://unpkg.com/swagger-ui-dist/favicon-16x16.png" sizes="16x16" />
<style>
html
{
@@ -30,8 +30,8 @@
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@3.28.0/swagger-ui-bundle.js"> </script>
<script src="https://unpkg.com/swagger-ui-dist@3.28.0/swagger-ui-standalone-preset.js"> </script>
<script src="https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js"> </script>
<script src="https://unpkg.com/swagger-ui-dist/swagger-ui-standalone-preset.js"> </script>
<script>
window.onload = function() {
// Begin Swagger UI call region