Skip to content

Commit

Permalink
Merge pull request #795 from dcs4cop/forman-793-update_server_api_docs
Browse files Browse the repository at this point in the history
Complete server API docs
  • Loading branch information
forman authored Feb 4, 2023
2 parents abd6b9c + 1420211 commit 6a73c79
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 134 deletions.
7 changes: 6 additions & 1 deletion xcube/webapi/datasets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,10 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.

# noinspection PyUnresolvedReferences
from .routes import PATH_PARAM_DATASET_ID
from .routes import PATH_PARAM_VAR_NAME
from .routes import QUERY_PARAM_CBAR
from .routes import QUERY_PARAM_CRS
from .routes import QUERY_PARAM_VMAX
from .routes import QUERY_PARAM_VMIN
from .routes import api
1 change: 0 additions & 1 deletion xcube/webapi/datasets/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
_CRS84 = pyproj.CRS.from_string('CRS84')



def find_dataset_places(ctx: DatasetsContext,
place_group_id: str,
ds_id: str,
Expand Down
114 changes: 106 additions & 8 deletions xcube/webapi/datasets/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,75 @@
from .controllers import get_dataset_place_group
from .controllers import get_datasets
from .controllers import get_legend
from ..places import PATH_PARAM_PLACE_GROUP_ID
from ...util.assertions import assert_true

PATH_PARAM_DATASET_ID = {
"name": "datasetId",
"in": "path",
"description": "Dataset identifier",
"schema": {"type": "string"}
}

PATH_PARAM_VAR_NAME = {
"name": "varName",
"in": "path",
"description": "Variable name",
"schema": {"type": "string"}
}

QUERY_PARAM_CRS = {
"name": "crs",
"in": "query",
"description": "The tile grid's spatial CRS",
"schema": {
"type": "string",
"enum": ["EPSG:3857", "CRS84"],
"default": "CRS84"
}
}

QUERY_PARAM_VMIN = {
"name": "vmin",
"in": "query",
"description": "Minimum value of variable"
" for color mapping",
"schema": {
"type": "number",
"default": 0
}
}

QUERY_PARAM_VMAX = {
"name": "vmax",
"in": "query",
"description": "Maximum value of variable"
" for color mapping",
"schema": {
"type": "number",
"default": 1
}
}

QUERY_PARAM_CBAR = {
"name": "cbar",
"in": "query",
"description": "Name of the (matplotlib) color bar"
" for color mapping",
"schema": {
"type": "string",
"default": "bone"
}
}


@api.route('/datasets')
class DatasetsHandler(ApiHandler[DatasetsContext]):
"""List the published datasets."""

@api.operation(
operation_id="getDatasets",
summary="Get the published datasets",
summary="Get all datasets.",
parameters=[
{
"name": "details",
Expand Down Expand Up @@ -86,7 +145,8 @@ def get(self):
class DatasetHandler(ApiHandler[DatasetsContext]):
# noinspection PyPep8Naming
@api.operation(operation_id='getDataset',
summary='Get dataset details')
summary='Get the details of a dataset.',
parameters=[PATH_PARAM_DATASET_ID])
async def get(self, datasetId: str):
granted_scopes = self.ctx.auth_ctx.get_granted_scopes(
self.request.headers
Expand All @@ -104,7 +164,8 @@ class DatasetCoordsHandler(ApiHandler[DatasetsContext]):

# noinspection PyPep8Naming
@api.operation(operation_id='getDatasetCoordinates',
summary='Get dataset coordinates')
summary='Get the coordinates for a dimension of a dataset.',
parameters=[PATH_PARAM_DATASET_ID])
async def get(self, datasetId: str, dimName: str):
result = get_dataset_coordinates(self.ctx, datasetId, dimName)
self.response.set_header('Content-Type', 'application/json')
Expand All @@ -117,7 +178,11 @@ class DatasetPlaceGroupHandler(ApiHandler[DatasetsContext]):
"""Get places for given dataset and place group."""

@api.operation(operation_id='getDatasetPlaceGroup',
summary='Get places for given dataset and place group')
summary='Get places for given dataset and place group.',
parameters=[
PATH_PARAM_DATASET_ID,
PATH_PARAM_PLACE_GROUP_ID
])
def get(self, datasetId: str, placeGroupId: str):
response = get_dataset_place_group(self.ctx,
datasetId,
Expand All @@ -132,7 +197,11 @@ class PlacesForDatasetHandler(ApiHandler[DatasetsContext]):
@api.operation(operation_id='findPlacesForDataset',
tags=['places'],
summary='Find places in place group for'
' bounding box of given dataset')
' bounding box of given dataset.',
parameters=[
PATH_PARAM_PLACE_GROUP_ID,
PATH_PARAM_DATASET_ID
])
def get(self, placeGroupId: str, datasetId: str):
query_expr = self.request.get_query_arg("query", default=None)
comb_op = self.request.get_query_arg("comb", default="and")
Expand Down Expand Up @@ -160,11 +229,40 @@ async def get(self, datasetId: str, varName: str):
await self.response.finish(legend)


LEGEND_PARAMETERS = [
PATH_PARAM_DATASET_ID,
PATH_PARAM_VAR_NAME,
QUERY_PARAM_CBAR,
QUERY_PARAM_VMIN,
QUERY_PARAM_VMAX,
{
"name": "width",
"in": "query",
"description": "Width of the legend in pixels",
"schema": {
"type": "number",
"default": 256
}
},
{
"name": "height",
"in": "query",
"description": "Height of the legend in pixels",
"schema": {
"type": "number",
"default": 16
}
},
]


# noinspection PyPep8Naming
@api.route('/datasets/{datasetId}/vars/{varName}/legend.png')
class OldLegendHandler(LegendHandler):
@api.operation(operation_id='getLegendForVariable',
summary='Deprecated.')
summary='Get the legend as PNG used for the tiles'
' for given variable. Deprecated!',
parameters=LEGEND_PARAMETERS)
async def get(self, datasetId: str, varName: str):
await super().get(datasetId, varName)

Expand All @@ -175,14 +273,14 @@ class NewLegendHandler(LegendHandler):
@api.operation(operation_id='getLegendForTiles',
tags=["tiles"],
summary='Get the legend as PNG used for the tiles'
' for given variable.')
' for given variable.',
parameters=LEGEND_PARAMETERS)
async def get(self, datasetId: str, varName: str):
await super().get(datasetId, varName)


# TODO (forman): move as endpoint "styles/colorbars" into API "styles"


@api.route('/colorbars')
class StylesColorBarsHandler(ApiHandler):
"""Get available color bars."""
Expand Down
61 changes: 57 additions & 4 deletions xcube/webapi/ows/wmts/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,59 @@
from .controllers import WMTS_WEB_MERCATOR_TMS_ID
from .controllers import get_crs_name_from_tms_id
from .controllers import get_wmts_capabilities_xml
from ...datasets import PATH_PARAM_DATASET_ID
from ...datasets import PATH_PARAM_VAR_NAME
from ...datasets import QUERY_PARAM_CBAR
from ...datasets import QUERY_PARAM_CRS
from ...datasets import QUERY_PARAM_VMAX
from ...datasets import QUERY_PARAM_VMIN
from ...tiles import PATH_PARAM_X
from ...tiles import PATH_PARAM_Y
from ...tiles import PATH_PARAM_Z
from ...tiles import QUERY_PARAM_RETINA
from ...tiles import QUERY_PARAM_TIME
from ...tiles.controllers import compute_ml_dataset_tile

_VALID_WMTS_TMS_IDS = (WMTS_CRS84_TMS_ID, WMTS_WEB_MERCATOR_TMS_ID)

PATH_PARAM_TMS_ID = {
"name": "tmsId",
"in": "query",
"description": "Tile matrix set identifier",
"schema": {
"type": "string",
"enum": [WMTS_CRS84_TMS_ID, WMTS_WEB_MERCATOR_TMS_ID],
}
}

TILE_PARAMETERS = [
PATH_PARAM_DATASET_ID,
PATH_PARAM_VAR_NAME,
PATH_PARAM_Z,
PATH_PARAM_Y,
PATH_PARAM_X,
QUERY_PARAM_CRS,
QUERY_PARAM_VMIN,
QUERY_PARAM_VMAX,
QUERY_PARAM_CBAR,
QUERY_PARAM_TIME,
QUERY_PARAM_RETINA,
]

TMS_TILE_PARAMETERS = [
PATH_PARAM_DATASET_ID,
PATH_PARAM_VAR_NAME,
PATH_PARAM_Z,
PATH_PARAM_Y,
PATH_PARAM_X,
QUERY_PARAM_CRS,
QUERY_PARAM_VMIN,
QUERY_PARAM_VMAX,
QUERY_PARAM_CBAR,
QUERY_PARAM_TIME,
QUERY_PARAM_RETINA,
]


@api.route('/wmts/1.0.0/WMTSCapabilities.xml')
class WmtsCapabilitiesXmlHandler(ApiHandler[WmtsContext]):
Expand All @@ -56,7 +105,8 @@ class WmtsCapabilitiesXmlForTmsHandler(ApiHandler[WmtsContext]):
# noinspection PyPep8Naming
@api.operation(operationId='getWmtsTmsCapabilities',
summary='Gets the WMTS capabilities'
' for tile matrix set as XML document')
' for tile matrix set as XML document',
parameters=[PATH_PARAM_TMS_ID])
async def get(self, tmsId):
self.request.make_query_lower_case()
_assert_valid_tms_id(tmsId)
Expand All @@ -75,7 +125,8 @@ async def get(self, tmsId):
class WmtsImageTileHandler(ApiHandler[WmtsContext]):
# noinspection PyPep8Naming
@api.operation(operationId='getWmtsImageTile',
summary='Gets a WMTS image tile in PNG format')
summary='Gets a WMTS image tile in PNG format.',
parameters=TILE_PARAMETERS)
async def get(self,
datasetId: str,
varName: str,
Expand Down Expand Up @@ -105,7 +156,8 @@ class WmtsImageTileForTmsHandler(ApiHandler[WmtsContext]):
# noinspection PyPep8Naming
@api.operation(operationId='getWmtsTmsImageTile',
summary='Gets a WMTS image tile'
' for given tile matrix set in PNG format')
' for given tile matrix set in PNG format',
parameters=TMS_TILE_PARAMETERS)
async def get(self,
datasetId: str,
varName: str,
Expand All @@ -131,7 +183,8 @@ async def get(self,
@api.route('/wmts/kvp')
class WmtsKvpHandler(ApiHandler[WmtsContext]):
@api.operation(operationId='invokeWmtsMethodFromKvp',
summary='Invokes the WMTS by key-value pairs')
summary='Invokes the WMTS by key-value pairs',
parameters=TILE_PARAMETERS)
async def get(self):
self.request.make_query_lower_case()
service = self.request.get_query_arg('service')
Expand Down
1 change: 1 addition & 0 deletions xcube/webapi/places/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
# DEALINGS IN THE SOFTWARE.

from .context import PlacesContext
from .routes import PATH_PARAM_PLACE_GROUP_ID
from .routes import api
2 changes: 1 addition & 1 deletion xcube/webapi/places/context.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# The MIT License (MIT)
# Copyright (c) 2022 by the xcube team and contributors
# Copyright (c) 2023 by the xcube team and contributors
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
Expand Down
15 changes: 13 additions & 2 deletions xcube/webapi/places/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,22 @@
from .context import PlacesContext
from .controllers import find_places

PATH_PARAM_PLACE_GROUP_ID = {
"name": "placeGroupId",
"in": "path",
"description": "Place group identifier",
"schema": {"type": "string"}
}


@api.route('/places')
class PlaceGroupsHandler(ApiHandler[PlacesContext]):
@api.operation(operationId='getPlaceGroups')
@api.operation(operationId='getPlaceGroups',
summary='Get place groups including all places.')
def get(self):
place_groups = self.ctx.get_global_place_groups(
self.request.reverse_base_url)
self.request.reverse_base_url
)
self.response.finish({"placeGroups": place_groups})


Expand All @@ -42,6 +51,7 @@ class FindPlacesHandler(ApiHandler):
@api.operation(operationId='findPlacesInPlaceGroup',
summary='Find places in a given place group.',
parameters=[
PATH_PARAM_PLACE_GROUP_ID,
{
"name": "geom",
"in": "query",
Expand Down Expand Up @@ -79,6 +89,7 @@ def get(self, placeGroupId: str):
@api.operation(operationId='findPlacesInPlaceGroup',
summary='Find places in a given place group'
' for a GeoJSON object.',
parameters=[PATH_PARAM_PLACE_GROUP_ID],
description='The request body must be a GeoJSON object.')
def post(self, placeGroupId: str):
# Not implemented yet:
Expand Down
8 changes: 6 additions & 2 deletions xcube/webapi/tiles/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.

# noinspection PyUnresolvedReferences
from .routes import PATH_PARAM_X
from .routes import PATH_PARAM_Y
from .routes import PATH_PARAM_Z
from .routes import QUERY_PARAM_TIME
from .routes import QUERY_PARAM_FORMAT
from .routes import QUERY_PARAM_RETINA
from .routes import api

Loading

0 comments on commit 6a73c79

Please sign in to comment.