* add support for OpenAPI validation (#717) * update copyright years * fix ES ref * update CLI
This commit is contained in:
+1
-1
@@ -1,3 +1,3 @@
|
||||
include README.md LICENSE.md requirements.txt
|
||||
recursive-include pygeoapi *.html
|
||||
recursive-include pygeoapi *.html *.json
|
||||
recursive-include pygeoapi/static *
|
||||
|
||||
Vendored
+1
@@ -18,6 +18,7 @@ Depends: ${python3:Depends},
|
||||
python3-click,
|
||||
python3-dateutil,
|
||||
python3-flask,
|
||||
python3-jsonschema,
|
||||
python3-tz,
|
||||
python3-unicodecsv,
|
||||
python3-yaml,
|
||||
|
||||
@@ -60,7 +60,7 @@ function error() {
|
||||
cd ${PYGEOAPI_HOME}
|
||||
|
||||
echo "Trying to generate openapi.yml"
|
||||
pygeoapi generate-openapi-document -c ${PYGEOAPI_CONFIG} > ${PYGEOAPI_OPENAPI}
|
||||
pygeoapi openapi generate -c ${PYGEOAPI_CONFIG} > ${PYGEOAPI_OPENAPI}
|
||||
|
||||
[[ $? -ne 0 ]] && error "openapi.yml could not be generated ERROR"
|
||||
|
||||
|
||||
@@ -7,31 +7,32 @@ Now that you have pygeoapi installed and a basic configuration setup, it's time
|
||||
the administrative steps required before starting up the server. The remaining steps are:
|
||||
|
||||
- create OpenAPI document
|
||||
- validate OpenAPI document
|
||||
- set system environment variables
|
||||
|
||||
Creating the OpenAPI document
|
||||
-----------------------------
|
||||
|
||||
The OpenAPI document ia a YAML configuration which is generated from the pygeoapi configuration,
|
||||
The OpenAPI document is a YAML configuration which is generated from the pygeoapi configuration,
|
||||
and describes the server information, endpoints, and parameters.
|
||||
|
||||
To generate the OpenAPI document, run the following:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pygeoapi generate-openapi-document -c /path/to/my-pygeoapi-config.yml
|
||||
pygeoapi openapi generate -c /path/to/my-pygeoapi-config.yml
|
||||
|
||||
This will dump the OpenAPI document as YAML to your system's ``stdout``. To save to a file on disk, run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pygeoapi generate-openapi-document -c /path/to/my-pygeoapi-config.yml > /path/to/my-pygeoapi-openapi.yml
|
||||
pygeoapi openapi generate -c /path/to/my-pygeoapi-config.yml > /path/to/my-pygeoapi-openapi.yml
|
||||
|
||||
To generate the OpenAPI document as JSON, run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pygeoapi generate-openapi-document -c /path/to/my-pygeoapi-config.yml -f json > /path/to/my-pygeoapi-openapi.json
|
||||
pygeoapi openapi generate -c /path/to/my-pygeoapi-config.yml -f json > /path/to/my-pygeoapi-openapi.json
|
||||
|
||||
.. note::
|
||||
Generate as YAML or JSON? If your OpenAPI YAML definition is slow to render as JSON,
|
||||
@@ -47,6 +48,17 @@ To generate the OpenAPI document as JSON, run:
|
||||
:ref:`openapi` for more information on pygeoapi's OpenAPI support
|
||||
|
||||
|
||||
Validating the OpenAPI document
|
||||
-------------------------------
|
||||
|
||||
To ensure your OpenAPI document is valid, pygeoapi provides a validation
|
||||
utility that can be run as follows:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pygeoapi validate-openapi-document -o /path/to/my-pygeoapi-openapi.yml
|
||||
|
||||
|
||||
Verifying configuration files
|
||||
-----------------------------
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ For developers and the truly impatient
|
||||
vi example-config.yml
|
||||
export PYGEOAPI_CONFIG=example-config.yml
|
||||
export PYGEOAPI_OPENAPI=example-openapi.yml
|
||||
pygeoapi generate-openapi-document -c $PYGEOAPI_CONFIG > $PYGEOAPI_OPENAPI
|
||||
pygeoapi openapi generate -c $PYGEOAPI_CONFIG > $PYGEOAPI_OPENAPI
|
||||
pygeoapi serve
|
||||
curl http://localhost:5000
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2018 Tom Kralidis
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -30,7 +30,7 @@
|
||||
__version__ = '0.11.dev0'
|
||||
|
||||
import click
|
||||
from pygeoapi.openapi import generate_openapi_document
|
||||
from pygeoapi.openapi import openapi
|
||||
|
||||
|
||||
@click.group()
|
||||
@@ -58,4 +58,4 @@ def serve(ctx, server):
|
||||
raise click.ClickException('--flask/--starlette is required')
|
||||
|
||||
|
||||
cli.add_command(generate_openapi_document)
|
||||
cli.add_command(openapi)
|
||||
|
||||
+58
-10
@@ -28,10 +28,12 @@
|
||||
# =================================================================
|
||||
|
||||
from copy import deepcopy
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
import click
|
||||
from jsonschema import validate as jsonschema_validate
|
||||
import yaml
|
||||
|
||||
from pygeoapi import __version__
|
||||
@@ -54,6 +56,8 @@ OPENAPI_YAML = {
|
||||
'oat': 'https://raw.githubusercontent.com/opengeospatial/ogcapi-tiles/master/openapi/swaggerHubUnresolved/ogc-api-tiles.yaml', # noqa
|
||||
}
|
||||
|
||||
THISDIR = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
|
||||
def get_ogc_schemas_location(server_config):
|
||||
|
||||
@@ -417,7 +421,7 @@ def get_oas_30(cfg):
|
||||
'get': {
|
||||
'summary': 'Get {} metadata'.format(title),
|
||||
'description': desc,
|
||||
'tags': name,
|
||||
'tags': [name],
|
||||
'operationId': 'describe{}Collection'.format(name.capitalize()), # noqa
|
||||
'parameters': [
|
||||
{'$ref': '#/components/parameters/f'},
|
||||
@@ -508,7 +512,7 @@ def get_oas_30(cfg):
|
||||
paths[items_path]['get']['parameters'].append(
|
||||
{'$ref': '{}#/components/parameters/datetime'.format(OPENAPI_YAML['oapif'])}) # noqa
|
||||
|
||||
for field, type in p.fields.items():
|
||||
for field, type_ in p.fields.items():
|
||||
|
||||
if p.properties and field not in p.properties:
|
||||
LOGGER.debug('Provider specified not to advertise property') # noqa
|
||||
@@ -518,25 +522,23 @@ def get_oas_30(cfg):
|
||||
LOGGER.debug('q parameter already declared, skipping')
|
||||
continue
|
||||
|
||||
if type == 'date':
|
||||
if type_ == 'date':
|
||||
schema = {
|
||||
'type': 'string',
|
||||
'format': 'date'
|
||||
}
|
||||
elif type == 'float':
|
||||
elif type_ == 'float':
|
||||
schema = {
|
||||
'type': 'number',
|
||||
'format': 'float'
|
||||
}
|
||||
elif type == 'long':
|
||||
elif type_ == 'long':
|
||||
schema = {
|
||||
'type': 'integer',
|
||||
'format': 'int64'
|
||||
}
|
||||
else:
|
||||
schema = {
|
||||
'type': type
|
||||
}
|
||||
schema = type_
|
||||
|
||||
path_ = '{}/items'.format(collection_name_path)
|
||||
paths['{}'.format(path_)]['get']['parameters'].append({
|
||||
@@ -756,6 +758,7 @@ def get_oas_30(cfg):
|
||||
}
|
||||
mimetype = tile_extension['format']['mimetype']
|
||||
paths[tiles_data_path]['get']['responses']['200'] = {
|
||||
'description': 'successful operation',
|
||||
'content': {
|
||||
mimetype: {
|
||||
'schema': {
|
||||
@@ -1027,12 +1030,37 @@ def get_oas(cfg, version='3.0'):
|
||||
raise RuntimeError('OpenAPI version not supported')
|
||||
|
||||
|
||||
@click.command('generate-openapi-document')
|
||||
def validate_openapi_document(instance_dict):
|
||||
"""
|
||||
Validate an OpenAPI document against the OpenAPI schema
|
||||
|
||||
:param instance_dict: dict of OpenAPI instance
|
||||
|
||||
:returns: `bool` of validation
|
||||
"""
|
||||
|
||||
schema_file = os.path.join(THISDIR, 'schemas', 'openapi',
|
||||
'openapi-3.0.x.json')
|
||||
|
||||
with open(schema_file) as fh2:
|
||||
schema_dict = json.load(fh2)
|
||||
jsonschema_validate(instance_dict, schema_dict)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@click.group()
|
||||
def openapi():
|
||||
"""OpenAPI management"""
|
||||
pass
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.pass_context
|
||||
@click.option('--config', '-c', 'config_file', help='configuration file')
|
||||
@click.option('--format', '-f', 'format_', type=click.Choice(['json', 'yaml']),
|
||||
default='yaml', help='output format (json|yaml)')
|
||||
def generate_openapi_document(ctx, config_file, format_='yaml'):
|
||||
def generate(ctx, config_file, format_='yaml'):
|
||||
"""Generate OpenAPI Document"""
|
||||
|
||||
if config_file is None:
|
||||
@@ -1044,3 +1072,23 @@ def generate_openapi_document(ctx, config_file, format_='yaml'):
|
||||
click.echo(yaml.safe_dump(get_oas(s), default_flow_style=False))
|
||||
else:
|
||||
click.echo(to_json(get_oas(s), pretty=pretty_print))
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.pass_context
|
||||
@click.option('--openapi', '-o', 'openapi_file', help='OpenAPI document')
|
||||
def validate(ctx, openapi_file):
|
||||
"""Validate OpenAPI Document"""
|
||||
|
||||
if openapi_file is None:
|
||||
raise click.ClickException('--openapi/-o required')
|
||||
|
||||
with open(openapi_file) as ff:
|
||||
click.echo('Validating {}'.format(openapi_file))
|
||||
instance = yaml_load(ff)
|
||||
validate_openapi_document(instance)
|
||||
click.echo('Valid OpenAPI document')
|
||||
|
||||
|
||||
openapi.add_command(generate)
|
||||
openapi.add_command(validate)
|
||||
|
||||
@@ -134,11 +134,11 @@ class ElasticsearchProvider(BaseProvider):
|
||||
for k, v in p['properties'].items():
|
||||
if 'type' in v:
|
||||
if v['type'] == 'text':
|
||||
type_ = 'string'
|
||||
fields_[k] = {'type': 'string'}
|
||||
elif v['type'] == 'date':
|
||||
fields_[k] = {'type': 'string', 'format': 'date'}
|
||||
else:
|
||||
type_ = v['type']
|
||||
|
||||
fields_[k] = {'type': type_}
|
||||
fields_[k] = {'type': v['type']}
|
||||
|
||||
return fields_
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
Babel
|
||||
click<8
|
||||
Flask
|
||||
jsonschema
|
||||
pyproj
|
||||
python-dateutil
|
||||
pytz
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
# files (the "Software"), to deal in the Software without
|
||||
# restriction, including without limitation the rights to use,
|
||||
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following
|
||||
# conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
# OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# =================================================================
|
||||
@@ -14,6 +14,6 @@ pip install gunicorn
|
||||
cd tests/cite/ogcapi-features
|
||||
. cite.env
|
||||
python ../../load_es_data.py ./canada-hydat-daily-mean-02hc003.geojson IDENTIFIER
|
||||
pygeoapi generate-openapi-document -c $PYGEOAPI_CONFIG > $PYGEOAPI_OPENAPI
|
||||
pygeoapi openapi generate -c $PYGEOAPI_CONFIG > $PYGEOAPI_OPENAPI
|
||||
gunicorn pygeoapi.flask_app:APP -b 0.0.0.0:5001 --access-logfile '-'
|
||||
```
|
||||
|
||||
@@ -102,11 +102,11 @@ paths:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/f'
|
||||
responses:
|
||||
200:
|
||||
'200':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/LandingPage
|
||||
400:
|
||||
'400':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/InvalidParameter
|
||||
500:
|
||||
'500':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/ServerError
|
||||
summary: Landing page
|
||||
tags:
|
||||
@@ -117,9 +117,9 @@ paths:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/f'
|
||||
responses:
|
||||
200:
|
||||
'200':
|
||||
$ref: '#/components/responses/200'
|
||||
400:
|
||||
'400':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/InvalidParameter
|
||||
default:
|
||||
$ref: '#/components/responses/default'
|
||||
@@ -132,11 +132,11 @@ paths:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/f'
|
||||
responses:
|
||||
200:
|
||||
'200':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/Collections
|
||||
400:
|
||||
'400':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/InvalidParameter
|
||||
500:
|
||||
'500':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/ServerError
|
||||
summary: Feature Collections
|
||||
tags:
|
||||
@@ -147,13 +147,13 @@ paths:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/f'
|
||||
responses:
|
||||
200:
|
||||
'200':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/Collection
|
||||
400:
|
||||
'400':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/InvalidParameter
|
||||
404:
|
||||
'404':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/NotFound
|
||||
500:
|
||||
'500':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/ServerError
|
||||
summary: Get feature collection metadata
|
||||
tags:
|
||||
@@ -182,13 +182,13 @@ paths:
|
||||
- $ref: '#/components/parameters/sortby'
|
||||
- $ref: '#/components/parameters/startindex'
|
||||
responses:
|
||||
200:
|
||||
'200':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/Features
|
||||
400:
|
||||
'400':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/InvalidParameter
|
||||
404:
|
||||
'404':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/NotFound
|
||||
500:
|
||||
'500':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/ServerError
|
||||
summary: Get Observations features
|
||||
tags:
|
||||
@@ -200,13 +200,13 @@ paths:
|
||||
- $ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/parameters/featureId
|
||||
- $ref: '#/components/parameters/f'
|
||||
responses:
|
||||
200:
|
||||
'200':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/Feature
|
||||
400:
|
||||
'400':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/InvalidParameter
|
||||
404:
|
||||
'404':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/NotFound
|
||||
500:
|
||||
'500':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/ServerError
|
||||
summary: Get Observations feature by id
|
||||
tags:
|
||||
@@ -217,11 +217,11 @@ paths:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/f'
|
||||
responses:
|
||||
200:
|
||||
'200':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/ConformanceDeclaration
|
||||
400:
|
||||
'400':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/InvalidParameter
|
||||
500:
|
||||
'500':
|
||||
$ref: http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml#/components/responses/ServerError
|
||||
summary: API conformance definition
|
||||
tags:
|
||||
@@ -232,7 +232,7 @@ paths:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/f'
|
||||
responses:
|
||||
200:
|
||||
'200':
|
||||
$ref: '#/components/responses/200'
|
||||
default:
|
||||
$ref: '#/components/responses/default'
|
||||
@@ -245,7 +245,7 @@ paths:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/f'
|
||||
responses:
|
||||
200:
|
||||
'200':
|
||||
$ref: '#/components/responses/200'
|
||||
default:
|
||||
$ref: '#/components/responses/default'
|
||||
@@ -256,7 +256,7 @@ paths:
|
||||
get:
|
||||
description: Hello World process
|
||||
responses:
|
||||
200:
|
||||
'200':
|
||||
$ref: '#/components/responses/200'
|
||||
default:
|
||||
$ref: '#/components/responses/default'
|
||||
@@ -279,7 +279,7 @@ paths:
|
||||
description: Mandatory execute request JSON
|
||||
required: true
|
||||
responses:
|
||||
200:
|
||||
'200':
|
||||
$ref: '#/components/responses/200'
|
||||
default:
|
||||
$ref: '#/components/responses/default'
|
||||
|
||||
+2
-38
@@ -28,58 +28,22 @@
|
||||
# =================================================================
|
||||
|
||||
import json
|
||||
import os
|
||||
import logging
|
||||
import time
|
||||
|
||||
from pyld import jsonld
|
||||
import pytest
|
||||
from werkzeug.test import create_environ
|
||||
from werkzeug.wrappers import Request
|
||||
from werkzeug.datastructures import ImmutableMultiDict
|
||||
from pygeoapi.api import (
|
||||
API, APIRequest, FORMAT_TYPES, validate_bbox, validate_datetime,
|
||||
F_HTML, F_JSON, F_JSONLD
|
||||
)
|
||||
from pygeoapi.util import yaml_load
|
||||
|
||||
from .util import get_test_file_path, mock_request
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_test_file_path(filename):
|
||||
"""helper function to open test file safely"""
|
||||
|
||||
if os.path.isfile(filename):
|
||||
return filename
|
||||
else:
|
||||
return 'tests/{}'.format(filename)
|
||||
|
||||
|
||||
def mock_request(params: dict = None, data=None, **headers) -> Request:
|
||||
"""
|
||||
Mocks a Request object so the @pre_process decorator can inject it
|
||||
as an APIRequest.
|
||||
|
||||
:param params: Optional query parameter dict for the request.
|
||||
Will be set to {} if omitted.
|
||||
:param data: Optional data/body to send with the request.
|
||||
Can be text/bytes or a JSON dictionary.
|
||||
:param headers: Optional request HTTP headers to set.
|
||||
:returns: A Werkzeug Request instance.
|
||||
"""
|
||||
params = params or {}
|
||||
# TODO: We are not setting a path in the create_environ() call.
|
||||
# This is fine as long as an API test does not need the URL path.
|
||||
if isinstance(data, dict):
|
||||
environ = create_environ(base_url='http://localhost:5000/', json=data)
|
||||
else:
|
||||
environ = create_environ(base_url='http://localhost:5000/', data=data)
|
||||
environ.update(headers)
|
||||
request = Request(environ)
|
||||
request.args = ImmutableMultiDict(params.items())
|
||||
return request
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def config():
|
||||
with open(get_test_file_path('pygeoapi-test-config.yml')) as fh:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2019 Tom Kralidis
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -33,14 +33,7 @@ import pytest
|
||||
|
||||
from pygeoapi.util import yaml_load
|
||||
|
||||
|
||||
def get_test_file_path(filename):
|
||||
"""helper function to open test file safely"""
|
||||
|
||||
if os.path.isfile(filename):
|
||||
return filename
|
||||
else:
|
||||
return 'tests/{}'.format(filename)
|
||||
from .util import get_test_file_path
|
||||
|
||||
|
||||
def test_config_envvars():
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2018 Tom Kralidis
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -27,22 +27,12 @@
|
||||
#
|
||||
# =================================================================
|
||||
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
from pygeoapi.provider.base import ProviderItemNotFoundError
|
||||
from pygeoapi.provider.csv_ import CSVProvider
|
||||
|
||||
|
||||
def get_test_file_path(filename):
|
||||
"""helper function to open test file safely"""
|
||||
|
||||
if os.path.isfile(filename):
|
||||
return filename
|
||||
else:
|
||||
return 'tests/{}'.format(filename)
|
||||
|
||||
from .util import get_test_file_path
|
||||
|
||||
path = get_test_file_path('data/obs.csv')
|
||||
|
||||
|
||||
+3
-11
@@ -26,13 +26,14 @@
|
||||
# OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# =================================================================
|
||||
import os
|
||||
|
||||
from babel import Locale
|
||||
import pytest
|
||||
|
||||
from pygeoapi import l10n
|
||||
from pygeoapi.util import yaml_load
|
||||
|
||||
import pytest
|
||||
from .util import get_test_file_path
|
||||
|
||||
|
||||
def test_str2locale():
|
||||
@@ -223,15 +224,6 @@ def test_setresponselanguage():
|
||||
assert headers['Content-Language'] == 'en'
|
||||
|
||||
|
||||
def get_test_file_path(filename):
|
||||
"""helper function to open test file safely"""
|
||||
|
||||
if os.path.isfile(filename):
|
||||
return filename
|
||||
else:
|
||||
return 'tests/{}'.format(filename)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def config():
|
||||
with open(get_test_file_path('pygeoapi-test-config.yml')) as fh:
|
||||
|
||||
+36
-2
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2020 Tom Kralidis
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -27,7 +27,25 @@
|
||||
#
|
||||
# =================================================================
|
||||
|
||||
from pygeoapi.openapi import get_ogc_schemas_location
|
||||
import pytest
|
||||
|
||||
from pygeoapi.openapi import (get_oas, get_ogc_schemas_location,
|
||||
validate_openapi_document)
|
||||
from pygeoapi.util import yaml_load
|
||||
|
||||
from .util import get_test_file_path
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def config():
|
||||
with open(get_test_file_path('pygeoapi-test-config.yml')) as fh:
|
||||
return yaml_load(fh)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def openapi():
|
||||
with open(get_test_file_path('pygeoapi-test-openapi.yml')) as fh:
|
||||
return yaml_load(fh)
|
||||
|
||||
|
||||
def test_str2bool():
|
||||
@@ -45,3 +63,19 @@ def test_str2bool():
|
||||
|
||||
default['ogc_schemas_location'] = '/opt/schemas.opengis.net'
|
||||
osl = get_ogc_schemas_location(default)
|
||||
|
||||
|
||||
def test_get_oas(config, openapi):
|
||||
openapi_doc = get_oas(config)
|
||||
|
||||
assert isinstance(openapi_doc, dict)
|
||||
|
||||
is_valid = validate_openapi_document(openapi_doc)
|
||||
|
||||
assert is_valid is True
|
||||
|
||||
|
||||
def test_validate_openapi_document(openapi):
|
||||
is_valid = validate_openapi_document(openapi)
|
||||
|
||||
assert is_valid is True
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2020 Tom Kralidis
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -27,20 +27,11 @@
|
||||
#
|
||||
# =================================================================
|
||||
|
||||
import os
|
||||
import pytest
|
||||
|
||||
from pygeoapi.provider.rasterio_ import RasterioProvider
|
||||
|
||||
|
||||
def get_test_file_path(filename):
|
||||
"""helper function to open test file safely"""
|
||||
|
||||
if os.path.isfile(filename):
|
||||
return filename
|
||||
else:
|
||||
return 'tests/{}'.format(filename)
|
||||
|
||||
from .util import get_test_file_path
|
||||
|
||||
path = get_test_file_path(
|
||||
'tests/data/CMC_glb_TMP_TGL_2_latlon.15x.15_2020081000_P000.grib2')
|
||||
|
||||
@@ -27,22 +27,12 @@
|
||||
#
|
||||
# =================================================================
|
||||
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
from pygeoapi.provider.base import ProviderItemNotFoundError
|
||||
from pygeoapi.provider.tinydb_ import TinyDBCatalogueProvider
|
||||
|
||||
|
||||
def get_test_file_path(filename):
|
||||
"""helper function to open test file safely"""
|
||||
|
||||
if os.path.isfile(filename):
|
||||
return filename
|
||||
else:
|
||||
return 'tests/{}'.format(filename)
|
||||
|
||||
from .util import get_test_file_path
|
||||
|
||||
path = get_test_file_path('tests/data/open.canada.ca/sample-records.tinydb')
|
||||
|
||||
|
||||
+2
-10
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2020 Tom Kralidis
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -29,21 +29,13 @@
|
||||
|
||||
from datetime import datetime, date, time
|
||||
from decimal import Decimal
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
from pygeoapi import util
|
||||
from pygeoapi.provider.base import ProviderTypeError
|
||||
|
||||
|
||||
def get_test_file_path(filename):
|
||||
"""helper function to open test file safely"""
|
||||
|
||||
if os.path.isfile(filename):
|
||||
return filename
|
||||
else:
|
||||
return 'tests/{}'.format(filename)
|
||||
from .util import get_test_file_path
|
||||
|
||||
|
||||
def test_get_typed_value():
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Gregory Petrochenkov <gpetrochenkov@usgs.gov>
|
||||
#
|
||||
# Copyright (c) 2020 Gregory Petrochenkov
|
||||
# Copyright (c) 2021 Gregory Petrochenkov
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -27,21 +27,12 @@
|
||||
#
|
||||
# =================================================================
|
||||
|
||||
import os
|
||||
import pytest
|
||||
|
||||
from pygeoapi.provider.base import ProviderQueryError
|
||||
from pygeoapi.provider.xarray_ import XarrayProvider
|
||||
|
||||
|
||||
def get_test_file_path(filename):
|
||||
"""helper function to open test file safely"""
|
||||
|
||||
if os.path.isfile(filename):
|
||||
return filename
|
||||
else:
|
||||
return 'tests/{}'.format(filename)
|
||||
|
||||
from .util import get_test_file_path
|
||||
|
||||
path = get_test_file_path('tests/data/coads_sst.nc')
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Authors: Gregory Petrochenkov <gpetrochenkov@usgs.gov>
|
||||
#
|
||||
# Copyright (c) 2020 Gregory Petrochenkov
|
||||
# Copyright (c) 2021 Gregory Petrochenkov
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
@@ -27,20 +27,11 @@
|
||||
#
|
||||
# =================================================================
|
||||
|
||||
import os
|
||||
import pytest
|
||||
|
||||
from pygeoapi.provider.xarray_ import XarrayProvider
|
||||
|
||||
|
||||
def get_test_file_path(filename):
|
||||
"""helper function to open test file safely"""
|
||||
|
||||
if os.path.isfile(filename):
|
||||
return filename
|
||||
else:
|
||||
return 'tests/{}'.format(filename)
|
||||
|
||||
from .util import get_test_file_path
|
||||
|
||||
path = get_test_file_path(
|
||||
'data/analysed_sst.zarr')
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2021 Tom Kralidis
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
# files (the "Software"), to deal in the Software without
|
||||
# restriction, including without limitation the rights to use,
|
||||
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following
|
||||
# conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
# OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# =================================================================
|
||||
|
||||
import os
|
||||
import logging
|
||||
|
||||
from werkzeug.test import create_environ
|
||||
from werkzeug.wrappers import Request
|
||||
from werkzeug.datastructures import ImmutableMultiDict
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_test_file_path(filename):
|
||||
"""helper function to open test file safely"""
|
||||
|
||||
if os.path.isfile(filename):
|
||||
return filename
|
||||
else:
|
||||
return 'tests/{}'.format(filename)
|
||||
|
||||
|
||||
def mock_request(params: dict = None, data=None, **headers) -> Request:
|
||||
"""
|
||||
Mocks a Request object so the @pre_process decorator can inject it
|
||||
as an APIRequest.
|
||||
|
||||
:param params: Optional query parameter dict for the request.
|
||||
Will be set to {} if omitted.
|
||||
:param data: Optional data/body to send with the request.
|
||||
Can be text/bytes or a JSON dictionary.
|
||||
:param headers: Optional request HTTP headers to set.
|
||||
:returns: A Werkzeug Request instance.
|
||||
"""
|
||||
params = params or {}
|
||||
# TODO: We are not setting a path in the create_environ() call.
|
||||
# This is fine as long as an API test does not need the URL path.
|
||||
if isinstance(data, dict):
|
||||
environ = create_environ(base_url='http://localhost:5000/', json=data)
|
||||
else:
|
||||
environ = create_environ(base_url='http://localhost:5000/', data=data)
|
||||
environ.update(headers)
|
||||
request = Request(environ)
|
||||
request.args = ImmutableMultiDict(params.items())
|
||||
return request
|
||||
Reference in New Issue
Block a user