Source code for weaver.wps_restapi.swagger_definitions

"""
Schema definitions for `OpenAPI` generation and validation of data from received requests and returned responses.

This module should contain any and every definitions in use to build the Swagger UI and the OpenAPI JSON schema
so that one can update the specification without touching any other files after the initial integration.

Schemas defined in this module are employed (through ``deserialize`` method calls) to validate that data conforms to
reported definitions. This makes the documentation of the API better aligned with resulting code execution under it.
It also provides a reference point for external users to understand expected data structures with complete schema
definitions generated on the exposed endpoints (JSON and Swagger UI).

The definitions are also employed to generate the `OpenAPI` definitions reported in the documentation published
on `Weaver`'s `ReadTheDocs` page.
"""
# pylint: disable=C0103,invalid-name
import datetime
import os
from copy import copy
from typing import TYPE_CHECKING

import duration
import yaml
from colander import DateTime, Email, Money, OneOf, Range, Regex, drop, null, required
from dateutil import parser as date_parser

from weaver import __meta__
from weaver.config import WeaverFeature
from weaver.execute import ExecuteControlOption, ExecuteMode, ExecuteResponse, ExecuteTransmissionMode
from weaver.formats import AcceptLanguage, ContentType
from weaver.owsexceptions import OWSMissingParameterValue
from weaver.processes.constants import (
    CWL_REQUIREMENT_APP_BUILTIN,
    CWL_REQUIREMENT_APP_DOCKER,
    CWL_REQUIREMENT_APP_DOCKER_GPU,
    CWL_REQUIREMENT_APP_ESGF_CWT,
    CWL_REQUIREMENT_APP_WPS1,
    CWL_REQUIREMENT_INIT_WORKDIR,
    OAS_COMPLEX_TYPES,
    OAS_DATA_TYPES,
    PACKAGE_ARRAY_BASE,
    PACKAGE_ARRAY_ITEMS,
    PACKAGE_CUSTOM_TYPES,
    PACKAGE_ENUM_BASE,
    PACKAGE_TYPE_POSSIBLE_VALUES,
    WPS_LITERAL_DATA_TYPES,
    ProcessSchema
)
from weaver.quotation.status import QuoteStatus
from weaver.sort import Sort, SortMethods
from weaver.status import JOB_STATUS_CODE_API, Status
from weaver.visibility import Visibility
from weaver.wps_restapi.colander_extras import (
    AllOfKeywordSchema,
    AnyOfKeywordSchema,
    BoundedRange,
    EmptyMappingSchema,
    ExtendedBoolean as Boolean,
    ExtendedFloat as Float,
    ExtendedInteger as Integer,
    ExtendedMappingSchema,
    ExtendedSchemaNode,
    ExtendedSequenceSchema,
    ExtendedString as String,
    NotKeywordSchema,
    OneOfCaseInsensitive,
    OneOfKeywordSchema,
    PermissiveMappingSchema,
    PermissiveSequenceSchema,
    SchemeURL,
    SemanticVersion,
    StringRange,
    XMLObject
)
from weaver.wps_restapi.constants import ConformanceCategory, JobInputsOutputsSchema
from weaver.wps_restapi.patches import ServiceOnlyExplicitGetHead as Service  # warning: don't use 'cornice.Service'

if TYPE_CHECKING:
    from typing import Any, Union

    from weaver.typedefs import DatetimeIntervalType, SettingsType, TypedDict

[docs] ViewInfo = TypedDict("ViewInfo", {"name": str, "pattern": str})
[docs]WEAVER_CONFIG_REMOTE_LIST = "[" + ", ".join(WeaverFeature.REMOTE) + "]"
[docs]API_TITLE = "Weaver REST API"
[docs]API_INFO = { "description": __meta__.__description__, "contact": {"name": __meta__.__authors__, "email": __meta__.__emails__, "url": __meta__.__source_repository__}
}
[docs]API_DOCS = { "description": f"{__meta__.__title__} documentation", "url": __meta__.__documentation_url__
}
[docs]DOC_URL = f"{__meta__.__documentation_url__}/en/latest"
[docs]CWL_VERSION = "v1.1"
[docs]CWL_REPO_URL = "https://github.com/common-workflow-language"
[docs]CWL_BASE_URL = "https://www.commonwl.org"
[docs]CWL_SPEC_URL = f"{CWL_BASE_URL}/#Specification"
[docs]CWL_USER_GUIDE_URL = f"{CWL_BASE_URL}/user_guide"
[docs]CWL_CMD_TOOL_URL = f"{CWL_BASE_URL}/{CWL_VERSION}/CommandLineTool.html"
[docs]CWL_WORKFLOW_URL = f"{CWL_BASE_URL}/{CWL_VERSION}/Workflow.html"
[docs]CWL_DOC_MESSAGE = ( "Note that multiple formats are supported and not all specification variants or parameters "
f"are presented here. Please refer to official CWL documentation for more details ({CWL_BASE_URL})." )
[docs]IO_INFO_IDS = ( "Identifier of the {first} {what}. To merge details between corresponding {first} and {second} "
"{what} specifications, this is the value that will be used to associate them together." )
[docs]OGC_API_REPO_URL = "https://github.com/opengeospatial/ogcapi-processes"
[docs]OGC_API_SCHEMA_URL = "https://raw.githubusercontent.com/opengeospatial/ogcapi-processes"
[docs]OGC_API_SCHEMA_VERSION = "master"
[docs]DATETIME_INTERVAL_CLOSED_SYMBOL = "/"
[docs]DATETIME_INTERVAL_OPEN_START_SYMBOL = "../"
[docs]DATETIME_INTERVAL_OPEN_END_SYMBOL = "/.."
# fields ordering for generation of ProcessDescription body (shared for OGC/OLD schema format)
[docs]PROCESS_DESCRIPTION_FIELD_FIRST = [ "id", "title", "version", "mutable", "abstract", # backward compat for deployment "description", "keywords", "metadata", "inputs", "outputs"
]
[docs]PROCESS_DESCRIPTION_FIELD_AFTER = [ "processDescriptionURL", "processEndpointWPS1", "executeEndpoint", "deploymentProfile", "links"
] # fields ordering for nested process definition of OLD schema format of ProcessDescription
[docs]PROCESS_DESCRIPTION_FIELD_FIRST_OLD_SCHEMA = ["process"]
[docs]PROCESS_DESCRIPTION_FIELD_AFTER_OLD_SCHEMA = ["links"]
[docs]PROCESS_IO_FIELD_FIRST = ["id", "title", "description", "minOccurs", "maxOccurs"]
[docs]PROCESS_IO_FIELD_AFTER = ["literalDataDomains", "formats", "crs", "bbox"]
[docs]PROVIDER_DESCRIPTION_FIELD_FIRST = [ "id", "title", "version", "mutable", "description", "url", "type", "public", "keywords", "metadata",
]
[docs]PROVIDER_DESCRIPTION_FIELD_AFTER = ["links"]
######################################################### # Examples ######################################################### # load examples by file names as keys
[docs]SCHEMA_EXAMPLE_DIR = os.path.join(os.path.dirname(__file__), "examples")
[docs]EXAMPLES = {}
for name in os.listdir(SCHEMA_EXAMPLE_DIR):
[docs] path = os.path.join(SCHEMA_EXAMPLE_DIR, name)
ext = os.path.splitext(name)[-1] with open(path, "r", encoding="utf-8") as f: if ext in [".json", ".yaml", ".yml"]: EXAMPLES[name] = yaml.safe_load(f) # both JSON/YAML else: EXAMPLES[name] = f.read() ######################################################### # API tags #########################################################
[docs]TAG_API = "API"
[docs]TAG_JOBS = "Jobs"
[docs]TAG_VISIBILITY = "Visibility"
[docs]TAG_BILL_QUOTE = "Billing & Quoting"
[docs]TAG_PROVIDERS = "Providers"
[docs]TAG_PROCESSES = "Processes"
[docs]TAG_GETCAPABILITIES = "GetCapabilities"
[docs]TAG_DESCRIBEPROCESS = "DescribeProcess"
[docs]TAG_EXECUTE = "Execute"
[docs]TAG_DISMISS = "Dismiss"
[docs]TAG_STATUS = "Status"
[docs]TAG_DEPLOY = "Deploy"
[docs]TAG_RESULTS = "Results"
[docs]TAG_EXCEPTIONS = "Exceptions"
[docs]TAG_LOGS = "Logs"
[docs]TAG_STATISTICS = "Statistics"
[docs]TAG_VAULT = "Vault"
[docs]TAG_WPS = "WPS"
[docs]TAG_DEPRECATED = "Deprecated Endpoints"
############################################################################### # API endpoints # These "services" are wrappers that allow Cornice to generate the JSON API ###############################################################################
[docs]api_frontpage_service = Service(name="api_frontpage", path="/")
[docs]api_openapi_ui_service = Service(name="api_openapi_ui", path="/api") # idem to swagger
[docs]api_swagger_ui_service = Service(name="api_swagger_ui", path="/swagger")
[docs]api_redoc_ui_service = Service(name="api_redoc_ui", path="/redoc")
[docs]api_versions_service = Service(name="api_versions", path="/versions")
[docs]api_conformance_service = Service(name="api_conformance", path="/conformance")
[docs]openapi_json_service = Service(name="openapi_json", path="/json")
[docs]quotes_service = Service(name="quotes", path="/quotations")
[docs]quote_service = Service(name="quote", path=quotes_service.path + "/{quote_id}")
[docs]bills_service = Service(name="bills", path="/bills")
[docs]bill_service = Service(name="bill", path=bills_service.path + "/{bill_id}")
[docs]jobs_service = Service(name="jobs", path="/jobs")
[docs]job_service = Service(name="job", path=jobs_service.path + "/{job_id}")
[docs]job_results_service = Service(name="job_results", path=job_service.path + "/results")
[docs]job_exceptions_service = Service(name="job_exceptions", path=job_service.path + "/exceptions")
[docs]job_outputs_service = Service(name="job_outputs", path=job_service.path + "/outputs")
[docs]job_inputs_service = Service(name="job_inputs", path=job_service.path + "/inputs")
[docs]job_logs_service = Service(name="job_logs", path=job_service.path + "/logs")
[docs]job_stats_service = Service(name="job_stats", path=job_service.path + "/statistics")
[docs]processes_service = Service(name="processes", path="/processes")
[docs]process_service = Service(name="process", path=processes_service.path + "/{process_id}")
[docs]process_quotes_service = Service(name="process_quotes", path=process_service.path + quotes_service.path)
[docs]process_quote_service = Service(name="process_quote", path=process_service.path + quote_service.path)
[docs]process_visibility_service = Service(name="process_visibility", path=process_service.path + "/visibility")
[docs]process_package_service = Service(name="process_package", path=process_service.path + "/package")
[docs]process_payload_service = Service(name="process_payload", path=process_service.path + "/payload")
[docs]process_jobs_service = Service(name="process_jobs", path=process_service.path + jobs_service.path)
[docs]process_job_service = Service(name="process_job", path=process_service.path + job_service.path)
[docs]process_results_service = Service(name="process_results", path=process_service.path + job_results_service.path)
[docs]process_inputs_service = Service(name="process_inputs", path=process_service.path + job_inputs_service.path)
[docs]process_outputs_service = Service(name="process_outputs", path=process_service.path + job_outputs_service.path)
[docs]process_exceptions_service = Service(name="process_exceptions", path=process_service.path + job_exceptions_service.path)
[docs]process_logs_service = Service(name="process_logs", path=process_service.path + job_logs_service.path)
[docs]process_stats_service = Service(name="process_stats", path=process_service.path + job_stats_service.path)
[docs]process_execution_service = Service(name="process_execution", path=process_service.path + "/execution")
[docs]providers_service = Service(name="providers", path="/providers")
[docs]provider_service = Service(name="provider", path=providers_service.path + "/{provider_id}")
[docs]provider_processes_service = Service(name="provider_processes", path=provider_service.path + processes_service.path)
[docs]provider_process_service = Service(name="provider_process", path=provider_service.path + process_service.path)
[docs]provider_jobs_service = Service(name="provider_jobs", path=provider_service.path + process_jobs_service.path)
[docs]provider_job_service = Service(name="provider_job", path=provider_service.path + process_job_service.path)
[docs]provider_results_service = Service(name="provider_results", path=provider_service.path + process_results_service.path)
[docs]provider_inputs_service = Service(name="provider_inputs", path=provider_service.path + process_inputs_service.path)
[docs]provider_outputs_service = Service(name="provider_outputs", path=provider_service.path + process_outputs_service.path)
[docs]provider_logs_service = Service(name="provider_logs", path=provider_service.path + process_logs_service.path)
[docs]provider_stats_service = Service(name="provider_stats", path=provider_service.path + process_stats_service.path)
[docs]provider_exceptions_service = Service(name="provider_exceptions", path=provider_service.path + process_exceptions_service.path)
[docs]provider_execution_service = Service(name="provider_execution", path=provider_service.path + "/execution")
# backward compatibility deprecated routes
[docs]job_result_service = Service(name="job_result", path=job_service.path + "/result")
[docs]process_result_service = Service(name="process_result", path=process_service.path + job_result_service.path)
[docs]provider_result_service = Service(name="provider_result", path=provider_service.path + process_result_service.path)
[docs]vault_service = Service(name="vault", path="/vault")
[docs]vault_file_service = Service(name="vault_file", path=vault_service.path + "/{file_id}")
######################################################### # Generic schemas #########################################################
[docs]class SLUG(ExtendedSchemaNode):
[docs] schema_type = String
[docs] description = "Slug name pattern."
[docs] example = "some-object-slug-name"
[docs] pattern = r"^[A-Za-z0-9]+(?:(-|_)[A-Za-z0-9]+)*$"
[docs]class URL(ExtendedSchemaNode):
[docs] schema_type = String
[docs] description = "URL reference."
[docs] format = "url"
[docs]class MediaType(ExtendedSchemaNode):
[docs] schema_type = String
[docs] description = "IANA identifier of content and format."
[docs] example = ContentType.APP_JSON
[docs] pattern = r"^\w+\/[-.\w]+(?:\+[-.\w]+)?(?:\;\s*.+)*$"
[docs]class QueryBoolean(Boolean):
[docs] description = "Boolean query parameter that allows handles common truthy/falsy values."
def __init__(self, *_, **__): # type: (*Any, **Any) -> None super(QueryBoolean, self).__init__( allow_string=True, false_choices=("False", "false", "0", "off", "no", "null", "Null", "none", "None", ""), true_choices=("True", "true", "1", "on", "yes")
)
[docs]class DateTimeInterval(ExtendedSchemaNode):
[docs] schema_type = String
[docs] description = ( "DateTime format against OGC API - Processes, "
"to get values before a certain date-time use '../' before the date-time, " "to get values after a certain date-time use '/..' after the date-time like the example, " "to get values between two date-times use '/' between the date-times, " "to get values with a specific date-time just pass the datetime. " )
[docs] example = "2022-03-02T03:32:38.487000+00:00/.."
[docs] regex_datetime = r"(\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(([+-]\d\d:\d\d)|Z)?)"
[docs] regex_interval_closed = fr"{regex_datetime}\/{regex_datetime}"
[docs] regex_interval_open_start = fr"\.\.\/{regex_datetime}"
[docs] regex_interval_open_end = fr"{regex_datetime}\/\.\."
[docs] pattern = fr"^{regex_datetime}|{regex_interval_closed}|{regex_interval_open_start}|{regex_interval_open_end}$"
[docs]class S3Bucket(ExtendedSchemaNode):
[docs] schema_type = String
[docs] description = "S3 bucket shorthand URL representation [s3://{bucket}/{job-uuid}/{output}.ext]"
[docs] pattern = r"^s3://\S+$"
[docs]class FileLocal(ExtendedSchemaNode):
[docs] schema_type = String
[docs] description = "Local file reference."
[docs] format = "file"
[docs] validator = Regex(r"^(file://)?(?:/|[/?]\S+)$")
[docs]class FileURL(ExtendedSchemaNode):
[docs] schema_type = String
[docs] description = "URL file reference."
[docs] format = "url"
[docs] validator = SchemeURL(schemes=["http", "https"])
[docs]class VaultReference(ExtendedSchemaNode):
[docs] schema_type = String
[docs] description = "Vault file reference."
[docs] example = "vault://399dc5ac-ff66-48d9-9c02-b144a975abe4"
[docs] pattern = r"^vault://[a-f0-9]{8}(?:-?[a-f0-9]{4}){3}-?[a-f0-9]{12}$"
[docs]class ReferenceURL(AnyOfKeywordSchema):
[docs] _any_of = [ FileURL(), FileLocal(), S3Bucket(),
]
[docs]class ExecuteReferenceURL(AnyOfKeywordSchema):
[docs] _any_of = [ FileURL(), FileLocal(), S3Bucket(), VaultReference(),
]
[docs]class UUID(ExtendedSchemaNode):
[docs] schema_type = String
[docs] description = "Unique identifier."
[docs] example = "a9d14bf4-84e0-449a-bac8-16e598efe807"
[docs] format = "uuid"
[docs] pattern = "^[a-f0-9]{8}(?:-?[a-f0-9]{4}){3}-?[a-f0-9]{12}$"
[docs] title = "UUID"
[docs]class AnyIdentifier(SLUG): pass
[docs]class ProcessIdentifier(AnyOfKeywordSchema):
[docs] description = "Process identifier."
[docs] _any_of = [ # UUID first because more strict than SLUG, and SLUG can be similar to UUID, but in the end any is valid UUID(description="Unique identifier."), SLUG(description="Generic identifier. This is a user-friendly slug-name. " "Note that this will represent the latest process matching this name. " "For specific process version, use the UUID instead.", title="ID"),
]
[docs]class Version(ExtendedSchemaNode): # note: internally use LooseVersion, so don't be too strict about pattern
[docs] schema_type = String
[docs] description = "Version string."
[docs] example = "1.2.3"
[docs] validator = SemanticVersion()
[docs]class ContentTypeHeader(ExtendedSchemaNode): # ok to use 'name' in this case because target 'key' in the mapping must # be that specific value but cannot have a field named with this format
[docs] name = "Content-Type"
[docs] schema_type = String
[docs]class ContentLengthHeader(ExtendedSchemaNode):
[docs] name = "Content-Length"
[docs] schema_type = String
[docs] example = "125"
[docs]class ContentDispositionHeader(ExtendedSchemaNode):
[docs] name = "Content-Disposition"
[docs] schema_type = String
[docs] example = "attachment; filename=test.json"
[docs]class DateHeader(ExtendedSchemaNode):
[docs] description = "Creation date and time of the contents."
[docs] name = "Date"
[docs] schema_type = String
[docs] example = "Thu, 13 Jan 2022 12:37:19 GMT"
[docs]class LastModifiedHeader(ExtendedSchemaNode):
[docs] description = "Modification date and time of the contents."
[docs] name = "Last-Modified"
[docs] schema_type = String
[docs] example = "Thu, 13 Jan 2022 12:37:19 GMT"
[docs]class AcceptHeader(ExtendedSchemaNode): # ok to use 'name' in this case because target 'key' in the mapping must # be that specific value but cannot have a field named with this format
[docs] name = "Accept"
[docs] schema_type = String
# FIXME: raise HTTPNotAcceptable in not one of those?
[docs] validator = OneOf([ ContentType.APP_JSON, ContentType.APP_XML, ContentType.TEXT_XML, ContentType.TEXT_HTML, ContentType.TEXT_PLAIN, ContentType.ANY,
])
[docs] missing = drop
[docs] default = ContentType.APP_JSON # defaults to JSON for easy use within browsers
[docs]class AcceptLanguageHeader(ExtendedSchemaNode): # ok to use 'name' in this case because target 'key' in the mapping must # be that specific value but cannot have a field named with this format
[docs] name = "Accept-Language"
[docs] schema_type = String
[docs] missing = drop
[docs] default = AcceptLanguage.EN_CA
# FIXME: oneOf validator for supported languages (?)
[docs]class JsonHeader(ExtendedMappingSchema):
[docs] content_type = ContentTypeHeader(example=ContentType.APP_JSON, default=ContentType.APP_JSON)
[docs]class HtmlHeader(ExtendedMappingSchema):
[docs] content_type = ContentTypeHeader(example=ContentType.TEXT_HTML, default=ContentType.TEXT_HTML)
[docs]class XmlHeader(ExtendedMappingSchema):
[docs] content_type = ContentTypeHeader(example=ContentType.APP_XML, default=ContentType.APP_XML)
[docs]class XAuthDockerHeader(ExtendedSchemaNode):
[docs] summary = "Authentication header for private Docker registry access."
[docs] description = ( "Authentication header for private registry access in order to retrieve the Docker image reference "
"specified in an Application Package during Process deployment. When provided, this header should " "contain similar details as typical Authentication or X-Auth-Token headers " f"(see {DOC_URL}/package.html#dockerized-applications for more details)." )
[docs] name = "X-Auth-Docker"
[docs] example = "Basic {base64-auth-credentials}"
[docs] schema_type = String
[docs] missing = drop
[docs]class RequestContentTypeHeader(OneOfKeywordSchema):
[docs] _one_of = [ JsonHeader(), XmlHeader(),
]
[docs]class ResponseContentTypeHeader(OneOfKeywordSchema):
[docs] _one_of = [ JsonHeader(), XmlHeader(), HtmlHeader(),
]
[docs]class RequestHeaders(RequestContentTypeHeader): """ Headers that can indicate how to adjust the behavior and/or result the be provided in the response. """
[docs] accept = AcceptHeader()
[docs] accept_language = AcceptLanguageHeader()
[docs]class ResponseHeaders(ResponseContentTypeHeader): """ Headers describing resulting response. """
[docs]class RedirectHeaders(ResponseHeaders):
[docs] Location = URL(example="https://job/123/result", description="Redirect resource location.")
[docs]class NoContent(ExtendedMappingSchema):
[docs] description = "Empty response body."
[docs] default = {}
[docs]class FileUploadHeaders(RequestContentTypeHeader): # MUST be multipart for upload
[docs] content_type = ContentTypeHeader( example=f"{ContentType.MULTI_PART_FORM}; boundary=43003e2f205a180ace9cd34d98f911ff", default=ContentType.MULTI_PART_FORM, description="Desired Content-Type of the file being uploaded.", missing=required)
[docs] content_length = ContentLengthHeader(description="Uploaded file contents size in bytes.")
[docs] content_disposition = ContentDispositionHeader(example="form-data; name=\"file\"; filename=\"desired-name.ext\"", description="Expected ")
[docs]class FileUploadContent(ExtendedSchemaNode):
[docs] schema_type = String()
[docs] description = ( "Contents of the file being uploaded with multipart. When prefixed with 'Content-Type: {media-type}', the "
"specified format will be applied to the input that will be attributed the 'vault://{UUID}' during execution. " "Contents can also have 'Content-Disposition' definition to provide the desired file name." )
[docs]class FileResponseHeaders(NoContent):
[docs] content_type = ContentTypeHeader(example=ContentType.APP_JSON)
[docs] content_length = ContentLengthHeader()
[docs] content_disposition = ContentDispositionHeader()
[docs] date = DateHeader()
[docs] last_modified = LastModifiedHeader()
[docs]class AccessToken(ExtendedSchemaNode):
[docs] schema_type = String
[docs]class DescriptionSchema(ExtendedMappingSchema):
[docs] description = ExtendedSchemaNode(String(), description="Description of the obtained contents.")
[docs]class KeywordList(ExtendedSequenceSchema):
[docs] keyword = ExtendedSchemaNode(String())
[docs]class Language(ExtendedSchemaNode):
[docs] schema_type = String
[docs] example = AcceptLanguage.EN_CA
[docs] validator = OneOf(AcceptLanguage.values())
[docs]class ValueLanguage(ExtendedMappingSchema):
[docs] lang = Language(missing=drop, description="Language of the value content.")
[docs]class LinkLanguage(ExtendedMappingSchema):
[docs] hreflang = Language(missing=drop, description="Language of the content located at the link.")
[docs]class LinkHeader(ExtendedSchemaNode):
[docs] schema_type = String
[docs] example = "<http://example.com>; rel=\"relation\"; type=text/plain"
[docs]class MetadataBase(ExtendedMappingSchema):
[docs] title = ExtendedSchemaNode(String(), missing=drop)
[docs]class MetadataRole(ExtendedMappingSchema):
[docs] role = URL(missing=drop)
[docs]class LinkRelationshipType(OneOfKeywordSchema):
[docs] description = ( "Link relation as registered or extension type "
"(see https://www.rfc-editor.org/rfc/rfc8288.html#section-2.1)." )
[docs] _one_of = [ SLUG(description=( "Relationship of the link to the current content. " "This should be one item amongst registered relations https://www.iana.org/assignments/link-relations/." )), URL(description="Fully qualified extension link relation to the current content.")
]
[docs]class LinkRelationship(ExtendedMappingSchema):
[docs] rel = LinkRelationshipType()
[docs]class LinkBase(LinkLanguage, MetadataBase):
[docs] href = URL(description="Hyperlink reference.")
[docs] type = MediaType(description="IANA identifier of content-type located at the link.", missing=drop)
[docs]class MetadataValue(NotKeywordSchema, ValueLanguage, MetadataBase):
[docs] _not = [ # make sure value metadata does not allow 'rel' and 'hreflang' reserved for link reference # explicitly refuse them such that when an href/rel link is provided, only link details are possible LinkRelationship(description="Field 'rel' must refer to a link reference with 'href'."), LinkLanguage(description="Field 'hreflang' must refer to a link reference with 'href'."),
]
[docs] value = ExtendedSchemaNode(String(), description="Plain text value of the information.")
[docs]class MetadataContent(OneOfKeywordSchema):
[docs] _one_of = [ MetadataLink(), MetadataValue(),
]
[docs]class Metadata(MetadataContent, MetadataRole): pass
[docs]class MetadataList(ExtendedSequenceSchema):
[docs] metadata = Metadata()
[docs]class LandingPage(ExtendedMappingSchema):
# sub-schema within: # https://github.com/opengeospatial/ogcapi-processes/blob/master/core/openapi/schemas/format.yaml
[docs]class FormatSchema(OneOfKeywordSchema):
[docs] _one_of = [ # pointer to a file or JSON schema relative item (as in OpenAPI definitions) ReferenceURL(description="Reference where the schema definition can be retrieved to describe referenced data."), # literal JSON schema, permissive since it can be anything PermissiveMappingSchema(description="Explicit schema definition of the formatted reference data.")
] # because some pre-existing processes + pywps default schema is "" # deserialization against the validator pattern of 'ReferenceURL' makes it always fail # this causes the whole 'Format' container (and others similar) fail and be dropped # to resolve this issue, preemptively detect the empty string and signal the parent OneOf to remove it
[docs] def deserialize(self, cstruct): # type: ignore if isinstance(cstruct, str) and cstruct == "": return drop # field that refers to this schema will drop the field key entirely return super(FormatSchema, self).deserialize(cstruct)
[docs]class FormatMimeType(ExtendedMappingSchema): """ Used to respect ``mimeType`` field to work with pre-existing processes. """
[docs] mimeType = MediaType(default=ContentType.TEXT_PLAIN, example=ContentType.APP_JSON)
[docs] encoding = ExtendedSchemaNode(String(), missing=drop)
[docs] schema = FormatSchema(missing=drop)
[docs]class Format(ExtendedMappingSchema): """ Used to respect ``mediaType`` field as suggested per `OGC-API`. """
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/format.yaml"
[docs] mediaType = MediaType(default=ContentType.TEXT_PLAIN, example=ContentType.APP_JSON)
[docs] encoding = ExtendedSchemaNode(String(), missing=drop)
[docs] schema = FormatSchema(missing=drop)
[docs]class DeployFormatDefaultMimeType(FormatMimeType):
[docs] description = ( "Format for process input are assumed plain/text if the media-type was omitted and is not one of the known "
"formats by this instance. When executing a job, the best match against supported formats by the process " "definition will be used to run the process, and will fallback to the default as last resort." ) # NOTE: # The default is overridden from FormatMimeType since the FormatSelection 'oneOf' always fails, # due to the 'default' value which is always generated and it causes the presence of both Format and FormatMimeType
[docs] mimeType = MediaType(example=ContentType.APP_JSON)
[docs]class DeployFormatDefault(Format):
[docs] description = ( "Format for process input are assumed plain/text if the media-type was omitted and is not one of the known "
"formats by this instance. When executing a job, the best match against supported formats by the process " "definition will be used to run the process, and will fallback to the default as last resort." ) # NOTE: # The default is overridden from Format since the FormatSelection 'oneOf' always fails, # due to the 'default' value which is always generated and it causes the presence of both Format and FormatMimeType
[docs] mediaType = MediaType(example=ContentType.APP_JSON)
[docs]class FormatSelection(OneOfKeywordSchema): """ Validation against ``mimeType`` or ``mediaType`` format. .. seealso:: - :class:`DeployFormatDefault` - :class:`DeployFormatDefaultMimeType` .. note:: Format are validated to be retro-compatible with pre-existing/deployed/remote processes. """
[docs] _one_of = [ DeployFormatDefault(), DeployFormatDefaultMimeType()
] # only extra portion from: # https://github.com/opengeospatial/ogcapi-processes/blob/e6893b/extensions/workflows/openapi/workflows.yaml#L1538-L1547
[docs]class FormatDescription(ExtendedMappingSchema):
[docs] maximumMegabytes = ExtendedSchemaNode(Integer(), missing=drop, validator=Range(min=1))
# although original schema defines 'default' in above 'FormatDescription', separate it in order to omit it # from 'ResultFormat' employed for result reporting, which shouldn't have a default (applied vs supported format)
[docs]class FormatDefault(ExtendedMappingSchema):
[docs] default = ExtendedSchemaNode( Boolean(), missing=drop, # don't insert "default" field if omitted in deploy body to avoid causing differing "inputs"/"outputs" # definitions between the submitted payload and the validated one (in 'weaver.processes.utils._check_deploy') # default=False, description=( "Indicates if this format should be considered as the default one in case none of the other "
"allowed or supported formats was matched nor provided as input during job submission." ) )
[docs]class DescriptionFormat(Format, FormatDescription, FormatDefault): pass
[docs]class DeploymentFormat(FormatSelection, FormatDescription, FormatDefault): # NOTE: # The 'OGC-API' suggest to use 'mediaType' field for format representation, but retro-compatibility is # supported during deployment only, where either old 'mimeType' or new 'mediaType', but only 'mediaType' # is used for process description and result reporting. This support is added for deployment so that # pre-existing deploy definitions remain valid without need to update them. pass
[docs]class ResultFormat(FormatDescription): """ Format employed for reference results respecting 'OGC API - Processes' schemas. """
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/formatDescription.yaml"
[docs] mediaType = MediaType(String())
[docs] encoding = ExtendedSchemaNode(String(), missing=drop)
[docs] schema = FormatSchema(missing=drop)
[docs]class DescriptionFormatList(ExtendedSequenceSchema):
[docs] format_item = DescriptionFormat()
[docs]class DeploymentFormatList(ExtendedSequenceSchema):
[docs] format_item = DeploymentFormat()
[docs]class AdditionalParameterUnique(OneOfKeywordSchema):
[docs] _one_of = [ ExtendedSchemaNode(String(), title="InputParameterLiteral.String"), ExtendedSchemaNode(Boolean(), title="InputParameterLiteral.Boolean"), ExtendedSchemaNode(Integer(), title="InputParameterLiteral.Integer"), ExtendedSchemaNode(Float(), title="InputParameterLiteral.Float"),
# PermissiveMappingSchema(title="InputParameterLiteral.object"), ]
[docs]class AdditionalParameterListing(ExtendedSequenceSchema):
[docs] param = AdditionalParameterUnique()
[docs]class AdditionalParameterValues(OneOfKeywordSchema):
[docs] _one_of = [ AdditionalParameterUnique(), AdditionalParameterListing()
]
[docs]class AdditionalParameterDefinition(ExtendedMappingSchema):
[docs] name = SLUG(title="AdditionalParameterName", example="EOImage")
[docs] values = AdditionalParameterValues(example=["true"])
[docs]class AdditionalParameterList(ExtendedSequenceSchema):
[docs] param = AdditionalParameterDefinition()
[docs]class AdditionalParametersMeta(OneOfKeywordSchema):
[docs] _one_of = [ LinkBase(title="AdditionalParameterLink"), MetadataRole(title="AdditionalParameterRole")
]
[docs]class AdditionalParameters(ExtendedMappingSchema):
[docs] parameters = AdditionalParameterList()
[docs]class AdditionalParametersItem(AnyOfKeywordSchema):
[docs] _any_of = [ AdditionalParametersMeta(), AdditionalParameters()
]
[docs]class AdditionalParametersList(ExtendedSequenceSchema):
[docs] additionalParameter = AdditionalParametersItem()
[docs]class Content(ExtendedMappingSchema):
[docs] href = ReferenceURL(description="URL to CWL file.", title="OWSContentURL", default=drop, # if invalid, drop it completely, missing=required, # but still mark as 'required' for parent objects example="http://some.host/applications/cwl/multisensor_ndvi.cwl")
[docs]class Offering(ExtendedMappingSchema):
[docs] code = ExtendedSchemaNode(String(), missing=drop, description="Descriptor of represented information in 'content'.")
[docs] content = Content()
[docs]class OWSContext(ExtendedMappingSchema):
[docs] description = "OGC Web Service definition from an URL reference."
[docs] title = "owsContext"
[docs] offering = Offering()
[docs]class DescriptionBase(ExtendedMappingSchema):
[docs] title = ExtendedSchemaNode(String(), missing=drop, description="Short human-readable name of the object.")
[docs] description = ExtendedSchemaNode(String(), missing=drop, description="Detailed explanation of the object.")
[docs]class ProcessContext(ExtendedMappingSchema):
[docs] owsContext = OWSContext(missing=drop)
[docs]class DescriptionExtra(ExtendedMappingSchema):
[docs] additionalParameters = AdditionalParametersList(missing=drop)
[docs]class DescriptionType(DescriptionBase, DescriptionLinks, DescriptionExtra): pass
[docs]class DeploymentType(DescriptionType):
[docs] deprecated = True
[docs] abstract = ExtendedSchemaNode( String(), missing=drop, deprecated=True, description="Description of the object. Will be replaced by 'description' field if not already provided. "
"Preserved for backward compatibility of pre-existing process deployment. " "Consider using 'description' directly instead." )
[docs]class DescriptionMeta(ExtendedMappingSchema): # employ empty lists by default if nothing is provided for process description
[docs] keywords = KeywordList( default=[], description="Keywords applied to the process for search and categorization purposes.")
[docs] metadata = MetadataList( default=[], description="External references to documentation or metadata sources relevant to the process.")
[docs]class ProcessDeployMeta(ExtendedMappingSchema): # don't require fields at all for process deployment, default to empty if omitted
[docs] keywords = KeywordList( missing=drop, default=[], description="Keywords applied to the process for search and categorization purposes.")
[docs] metadata = MetadataList( missing=drop, default=[], description="External references to documentation or metadata sources relevant to the process.")
[docs]class InputOutputDescriptionMeta(ExtendedMappingSchema): # remove unnecessary empty lists by default if nothing is provided for inputs/outputs def __init__(self, *args, **kwargs): # type: (*Any, **Any) -> None super(InputOutputDescriptionMeta, self).__init__(*args, **kwargs) for child in self.children: if child.name in ["keywords", "metadata"]: child.missing = drop
[docs]class ReferenceOAS(ExtendedMappingSchema):
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/reference.yaml"
[docs] _ref = ReferenceURL(name="$ref", description="External OpenAPI schema reference.")
[docs]class TypeOAS(ExtendedSchemaNode):
[docs] name = "type"
[docs] schema_type = String
[docs] validator = OneOf(OAS_DATA_TYPES)
[docs]class EnumItemOAS(OneOfKeywordSchema):
[docs] _one_of = [ ExtendedSchemaNode(Float()), ExtendedSchemaNode(Integer()), ExtendedSchemaNode(String()),
]
[docs]class EnumOAS(ExtendedSequenceSchema):
[docs] enum = EnumItemOAS()
[docs]class RequiredOAS(ExtendedSequenceSchema):
[docs] required_field = ExtendedSchemaNode(String(), description="Name of the field that is required under the object.")
[docs]class MultipleOfOAS(OneOfKeywordSchema):
[docs] _one_of = [ ExtendedSchemaNode(Float()), ExtendedSchemaNode(Integer()),
]
[docs]class PermissiveDefinitionOAS(NotKeywordSchema, PermissiveMappingSchema):
[docs] _not = [ ReferenceOAS
] # cannot make recursive declarative schemas # simulate it and assume it is sufficient for validation purposes
[docs]class PseudoObjectOAS(OneOfKeywordSchema):
[docs] _one_of = [ ReferenceOAS(), PermissiveDefinitionOAS(),
]
[docs]class KeywordObjectOAS(ExtendedSequenceSchema):
[docs] item = PseudoObjectOAS()
[docs]class AdditionalPropertiesOAS(OneOfKeywordSchema):
[docs] _one_of = [ ReferenceOAS(), PermissiveDefinitionOAS(), ExtendedSchemaNode(Boolean())
]
[docs]class AnyValueOAS(AnyOfKeywordSchema):
[docs] _any_of = [ PermissiveMappingSchema(), PermissiveSequenceSchema(), ExtendedSchemaNode(Float()), ExtendedSchemaNode(Integer()), ExtendedSchemaNode(Boolean()), ExtendedSchemaNode(String()),
] # reference: # https://raw.githubusercontent.com/opengeospatial/ogcapi-processes/master/core/openapi/schemas/schema.yaml # note: # although reference definition provides multiple 'default: 0|false' entries, we omit them since the behaviour # of colander with extended schema nodes is to set this value by default in deserialize result if they were missing, # but reference 'default' correspond more to the default *interpretation* value if none was provided. # It is preferable in our case to omit (i.e.: drop) these defaults to keep obtained/resolved definitions succinct, # since those defaults can be defined (by default...) if needed. No reason to add them explicitly. # WARNING: # cannot use any KeywordMapper derived instance here, otherwise conflicts with same OpenAPI keywords as children nodes
[docs]class PropertyOAS(PermissiveMappingSchema):
[docs] _type = TypeOAS(name="type", missing=drop) # not present if top-most schema is {allOf,anyOf,oneOf,not}
[docs] _format = ExtendedSchemaNode(String(), name="format", missing=drop)
[docs] default = AnyValueOAS(unknown="preserve", missing=drop)
[docs] example = AnyValueOAS(unknown="preserve", missing=drop)
[docs] title = ExtendedSchemaNode(String(), missing=drop)
[docs] description = ExtendedSchemaNode(String(), missing=drop)
[docs] enum = EnumOAS(missing=drop)
[docs] items = PseudoObjectOAS(name="items", missing=drop)
[docs] required = RequiredOAS(missing=drop)
[docs] nullable = ExtendedSchemaNode(Boolean(), missing=drop)
[docs] deprecated = ExtendedSchemaNode(Boolean(), missing=drop)
[docs] read_only = ExtendedSchemaNode(Boolean(), name="readOnly", missing=drop)
[docs] write_only = ExtendedSchemaNode(Boolean(), name="writeOnly", missing=drop)
[docs] multiple_of = MultipleOfOAS(name="multipleOf", missing=drop, validator=BoundedRange(min=0, exclusive_min=True))
[docs] minimum = ExtendedSchemaNode(Integer(), name="minLength", missing=drop, validator=Range(min=0)) # default=0
[docs] maximum = ExtendedSchemaNode(Integer(), name="maxLength", missing=drop, validator=Range(min=0))
[docs] exclusive_min = ExtendedSchemaNode(Boolean(), name="exclusiveMinimum", missing=drop) # default=False
[docs] exclusive_max = ExtendedSchemaNode(Boolean(), name="exclusiveMaximum", missing=drop) # default=False
[docs] min_length = ExtendedSchemaNode(Integer(), name="minLength", missing=drop, validator=Range(min=0)) # default=0
[docs] max_length = ExtendedSchemaNode(Integer(), name="maxLength", missing=drop, validator=Range(min=0))
[docs] pattern = ExtendedSchemaNode(Integer(), missing=drop)
[docs] min_items = ExtendedSchemaNode(Integer(), name="minItems", missing=drop, validator=Range(min=0)) # default=0
[docs] max_items = ExtendedSchemaNode(Integer(), name="maxItems", missing=drop, validator=Range(min=0))
[docs] unique_items = ExtendedSchemaNode(Boolean(), name="uniqueItems", missing=drop) # default=False
[docs] min_prop = ExtendedSchemaNode(Integer(), name="minProperties", missing=drop, validator=Range(min=0)) # default=0
[docs] max_prop = ExtendedSchemaNode(Integer(), name="maxProperties", missing=drop, validator=Range(min=0))
[docs] content_type = ExtendedSchemaNode(String(), name="contentMediaType", missing=drop)
[docs] content_encode = ExtendedSchemaNode(String(), name="contentEncoding", missing=drop)
[docs] content_schema = ExtendedSchemaNode(String(), name="contentSchema", missing=drop)
[docs] _not_key = PseudoObjectOAS(name="not", title="not", missing=drop)
[docs] _all_of = KeywordObjectOAS(name="allOf", missing=drop)
[docs] _any_of = KeywordObjectOAS(name="anyOf", missing=drop)
[docs] _one_of = KeywordObjectOAS(name="oneOf", missing=drop)
[docs] x_props = AdditionalPropertiesOAS(name="additionalProperties", missing=drop)
[docs] properties = PermissiveMappingSchema(missing=drop) # cannot do real recursive definitions, simply check mapping
# this class is only to avoid conflicting names with keyword mappers
[docs]class AnyPropertyOAS(OneOfKeywordSchema):
[docs] _one_of = [ ReferenceOAS(), PropertyOAS(),
]
[docs]class ObjectPropertiesOAS(ExtendedMappingSchema):
[docs] property_name = AnyPropertyOAS( variable="{property-name}", description="Named of the property being defined under the OpenAPI object.",
) # would not need this if we could do explicit recursive definitions but at the very least, validate that when a # object type is specified, its properties are as well and are slightly more specific than permissive mapping
[docs]class ObjectOAS(NotKeywordSchema, ExtendedMappingSchema):
[docs] _not = [ReferenceOAS]
[docs] _type = TypeOAS(name="type", missing=drop, validator=OneOf(OAS_COMPLEX_TYPES))
[docs] properties = ObjectPropertiesOAS() # required and more specific contrary to 'properties' in 'PropertyOAS'
# since we redefine 'properties', do not cause validation error for 'oneOf'
[docs]class DefinitionOAS(AnyOfKeywordSchema):
[docs] _any_of = [ ObjectOAS(), PropertyOAS(), # for top-level keyword schemas {allOf,anyOf,oneOf,not}
]
[docs]class OAS(OneOfKeywordSchema):
[docs] description = "OpenAPI schema definition."
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/schema.yaml"
[docs] _one_of = [ ReferenceOAS(), DefinitionOAS(),
]
[docs]class InputOutputDescriptionSchema(ExtendedMappingSchema): # Validation is accomplished only for the first few levels of the OpenAPI definition. # This is sufficient to know if the I/O type is literal/bbox/complex. If 'schema' is explicitly provided, it # should minimally succeed those top-level validation for proper I/O interpretation. Pseudo-recursive schema # are defined for any more deeply nested definition to keep everything intact (eg: explicit object structure).
[docs] schema = OAS(missing=drop)
[docs]class MinOccursDefinition(OneOfKeywordSchema):
[docs] description = "Minimum amount of values required for this input."
[docs] title = "MinOccurs"
[docs] example = 1
[docs] _one_of = [ ExtendedSchemaNode(Integer(), validator=Range(min=0), title="MinOccurs.integer", ddescription="Positive integer."), ExtendedSchemaNode(String(), validator=StringRange(min=0), pattern="^[0-9]+$", title="MinOccurs.string", description="Numerical string representing a positive integer."),
]
[docs]class MaxOccursDefinition(OneOfKeywordSchema):
[docs] description = "Maximum amount of values allowed for this input."
[docs] title = "MaxOccurs"
[docs] example = 1
[docs] _one_of = [ ExtendedSchemaNode(Integer(), validator=Range(min=0), title="MaxOccurs.integer", description="Positive integer."), ExtendedSchemaNode(String(), validator=StringRange(min=0), pattern="^[0-9]+$", title="MaxOccurs.string", description="Numerical string representing a positive integer."), ExtendedSchemaNode(String(), validator=OneOf(["unbounded"]), title="MaxOccurs.unbounded", description="Special value indicating no limit to occurrences."),
]
[docs]class DescribeMinMaxOccurs(ExtendedMappingSchema):
[docs] minOccurs = MinOccursDefinition()
[docs] maxOccurs = MaxOccursDefinition()
[docs]class DeployMinMaxOccurs(ExtendedMappingSchema): # entirely omitted definitions are permitted to allow inference from fields in package (CWL) or using defaults # if explicitly provided though, schema format and values should be validated # - do not use 'missing=drop' to ensure we raise provided invalid value instead of ignoring it # - do not use any specific value (e.g.: 1) for 'default' such that we do not inject an erroneous value when it # was originally omitted, since it could be resolved differently depending on matching CWL inputs definitions
[docs] minOccurs = MinOccursDefinition(default=null, missing=null)
[docs] maxOccurs = MaxOccursDefinition(default=null, missing=null)
# does not inherit from 'DescriptionLinks' because other 'ProcessDescription<>' schema depend from this without 'links'
[docs]class ProcessDescriptionType(DescriptionBase, DescriptionExtra):
[docs] id = ProcessIdentifier()
[docs] version = Version(missing=drop)
[docs] mutable = ExtendedSchemaNode(Boolean(), default=True, description=( "Indicates if the process is mutable (dynamically deployed), or immutable (builtin with this instance)."
))
[docs]class InputIdentifierType(ExtendedMappingSchema):
[docs] id = AnyIdentifier(description=IO_INFO_IDS.format(first="WPS", second="CWL", what="input"))
[docs]class OutputIdentifierType(ExtendedMappingSchema):
[docs] id = AnyIdentifier(description=IO_INFO_IDS.format(first="WPS", second="CWL", what="output"))
[docs]class DescribeWithFormats(ExtendedMappingSchema):
[docs] formats = DescriptionFormatList()
[docs]class DeployWithFormats(ExtendedMappingSchema):
[docs] formats = DeploymentFormatList()
[docs]class DescribeComplexInputType(DescribeWithFormats): pass
[docs]class DeployComplexInputType(DeployWithFormats): pass
[docs]class SupportedCRS(ExtendedMappingSchema):
[docs] crs = URL(title="CRS", description="Coordinate Reference System")
[docs] default = ExtendedSchemaNode(Boolean(), missing=drop)
[docs]class SupportedCRSList(ExtendedSequenceSchema):
[docs] crs = SupportedCRS(title="SupportedCRS")
[docs]class BoundingBoxInputType(ExtendedMappingSchema):
[docs] supportedCRS = SupportedCRSList()
# FIXME: support byte/binary type (string + format:byte) ? # https://github.com/opengeospatial/ogcapi-processes/blob/master/core/openapi/schemas/binaryInputValue.yaml
[docs]class AnyLiteralType(OneOfKeywordSchema): """ Submitted values that correspond to literal data. .. seealso:: - :class:`AnyLiteralDataType` - :class:`AnyLiteralValueType` - :class:`AnyLiteralDefaultType` """
[docs] _one_of = [ ExtendedSchemaNode(Float(), description="Literal data type representing a floating point number."), ExtendedSchemaNode(Integer(), description="Literal data type representing an integer number."), ExtendedSchemaNode(Boolean(), description="Literal data type representing a boolean flag."), ExtendedSchemaNode(String(), description="Literal data type representing a generic string."),
]
[docs]class NumberType(OneOfKeywordSchema): """ Represents a literal number, integer or float. """
[docs] _one_of = [ ExtendedSchemaNode(Float()), ExtendedSchemaNode(Integer()),
]
[docs]class NumericType(OneOfKeywordSchema): """ Represents a numeric-like value. """
[docs] _one_of = [ ExtendedSchemaNode(Float()), ExtendedSchemaNode(Integer()), ExtendedSchemaNode(String(), pattern="^[0-9]+$"),
]
[docs]class LiteralReference(ExtendedMappingSchema):
[docs] reference = ReferenceURL()
# https://github.com/opengeospatial/ogcapi-processes/blob/e6893b/extensions/workflows/openapi/workflows.yaml#L1707-L1716
[docs]class NameReferenceType(ExtendedMappingSchema):
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/nameReferenceType.yaml"
[docs] name = ExtendedSchemaNode(String())
[docs] reference = ReferenceURL(missing=drop, description="Reference URL to schema definition of the named entity.")
[docs]class DataTypeSchema(NameReferenceType):
[docs] description = "Type of the literal data representation."
[docs] title = "DataType"
# any named type that can be converted by: 'weaver.processes.convert.any2wps_literal_datatype'
[docs] name = ExtendedSchemaNode(String(), validator=OneOf(list(WPS_LITERAL_DATA_TYPES)))
[docs]class UomSchema(NameReferenceType):
[docs] title = "UnitOfMeasure"
# https://github.com/opengeospatial/ogcapi-processes/blob/e6893b/extensions/workflows/openapi/workflows.yaml#L1423 # NOTE: Original is only 'string', but we allow any literal type
[docs]class AllowedValuesList(ExtendedSequenceSchema):
[docs] value = AnyLiteralType()
# https://github.com/opengeospatial/ogcapi-processes/blob/e6893b/extensions/workflows/openapi/workflows.yaml#L1772-L1787 # NOTE: # Contrary to original schema where all fields are 'string', we allow any literal type as well since those make more # sense when parsing corresponding data values (eg: float, integer, bool).
[docs]class AllowedRange(ExtendedMappingSchema):
[docs] minimumValue = NumericType(missing=drop)
[docs] maximumValue = NumericType(missing=drop)
[docs] spacing = NumericType(missing=drop)
[docs] rangeClosure = ExtendedSchemaNode(String(), missing=drop, validator=OneOf(["closed", "open", "open-closed", "closed-open"]))
[docs]class AllowedRangesList(ExtendedSequenceSchema):
[docs] range = AllowedRange()
[docs]class AllowedValues(OneOfKeywordSchema):
[docs] _one_of = [ AllowedRangesList(description="List of value ranges and constraints."), # array of {range} AllowedValuesList(description="List of enumerated allowed values."), # array of "value" ExtendedSchemaNode(String(), description="Single allowed value."), # single "value"
] # https://github.com/opengeospatial/ogcapi-processes/blob/e6893b/extensions/workflows/openapi/workflows.yaml#L1425-L1430
[docs]class AnyValue(ExtendedMappingSchema):
[docs] anyValue = ExtendedSchemaNode( Boolean(), missing=drop, default=True, description="Explicitly indicate if any value is allowed. "
"This is the default behaviour if no other constrains are specified." ) # https://github.com/opengeospatial/ogcapi-processes/blob/e6893b/extensions/workflows/openapi/workflows.yaml#L1801-L1803
[docs]class ValuesReference(ReferenceURL):
[docs] description = "URL where to retrieve applicable values."
[docs]class ArrayLiteralType(ExtendedSequenceSchema):
[docs] value_item = AnyLiteralType()
[docs]class ArrayLiteralDataType(ExtendedMappingSchema):
[docs] data = ArrayLiteralType()
[docs]class ArrayLiteralValueType(ExtendedMappingSchema):
[docs] value = ArrayLiteralType()
[docs]class AnyLiteralDataType(ExtendedMappingSchema):
[docs] data = AnyLiteralType()
[docs]class AnyLiteralValueType(ExtendedMappingSchema):
[docs] value = AnyLiteralType()
[docs]class AnyLiteralDefaultType(ExtendedMappingSchema):
[docs] default = AnyLiteralType()
[docs]class LiteralDataValueDefinition(OneOfKeywordSchema):
[docs] _one_of = [ AllowedValues(description="Constraints of allowed values."), ValuesReference(description="Reference URL where to retrieve allowed values."), # 'AnyValue' must be last because it's the most permissive (always valid, default) AnyValue(description="Permissive definition for any allowed value."),
] # https://github.com/opengeospatial/ogcapi-processes/blob/e6893b/extensions/workflows/openapi/workflows.yaml#L1675-L1688 # literalDataDomain: # valueDefinition: oneOf(<allowedValues, anyValue, valuesReference>) # defaultValue: <string> # dataType: <nameReferenceType> # uom: <nameReferenceType>
[docs]class LiteralDataDomain(ExtendedMappingSchema):
[docs] default = ExtendedSchemaNode(Boolean(), default=True, description="Indicates if this literal data domain definition is the default one.")
[docs] defaultValue = AnyLiteralType(missing=drop, description="Default value to employ if none was provided.")
[docs] dataType = DataTypeSchema(missing=drop, description="Type name and reference of the literal data representation.")
[docs] uom = UomSchema(missing=drop, description="Unit of measure applicable for the data.")
[docs] valueDefinition = LiteralDataValueDefinition(description="Literal data domain constraints.")
[docs]class LiteralDataDomainList(ExtendedSequenceSchema): """ Constraints that apply to the literal data values. """
[docs] literalDataDomain = LiteralDataDomain()
# https://github.com/opengeospatial/ogcapi-processes/blob/e6893b/extensions/workflows/openapi/workflows.yaml#L1689-L1697
[docs]class LiteralDataType(NotKeywordSchema, ExtendedMappingSchema): # NOTE: # Apply 'missing=drop' although original schema of 'literalDataDomains' (see link above) requires it because # we support omitting it for minimalistic literal input definition. # This is because our schema validation allows us to do detection of 'basic' types using the literal parsing. # Because there is not explicit requirement though (ie: missing would fail schema validation), we must check # that 'format' is not present to avoid conflict with minimalistic literal data definition in case of ambiguity.
[docs] literalDataDomains = LiteralDataDomainList(missing=drop)
[docs] _not = [ DescribeWithFormats,
]
[docs]class LiteralInputType(LiteralDataType): pass
[docs]class DescribeInputTypeDefinition(OneOfKeywordSchema):
[docs] _one_of = [ # NOTE: # LiteralInputType could be used to represent a complex input if the 'format' is missing in # process description definition but is instead provided in CWL definition. # This use case is still valid because 'format' can be inferred from the combining Process/CWL contents. BoundingBoxInputType, DescribeComplexInputType, # should be 2nd to last because very permissive, but requires format at least LiteralInputType, # must be last because it"s the most permissive (all can default if omitted)
]
[docs]class DeployInputTypeDefinition(OneOfKeywordSchema):
[docs] _one_of = [ # NOTE: # LiteralInputType could be used to represent a complex input if the 'format' is missing in # process deployment definition but is instead provided in CWL definition. # This use case is still valid because 'format' can be inferred from the combining Process/CWL contents. BoundingBoxInputType, DeployComplexInputType, # should be 2nd to last because very permissive, but requires formats at least LiteralInputType, # must be last because it"s the most permissive (all can default if omitted)
]
[docs]class DescribeInputType(AllOfKeywordSchema):
[docs] _all_of = [ DescriptionType(), InputOutputDescriptionMeta(), InputOutputDescriptionSchema(), DescribeInputTypeDefinition(), DescribeMinMaxOccurs(), DescriptionExtra(),
]
[docs] _sort_first = PROCESS_IO_FIELD_FIRST
[docs] _sort_after = PROCESS_IO_FIELD_AFTER
[docs]class DescribeInputTypeWithID(InputIdentifierType, DescribeInputType):
[docs] title = "DescribeInputTypeWithID"
# Different definition than 'Describe' such that nested 'complex' type 'formats' can be validated and backward # compatible with pre-existing/deployed/remote processes, with either ``mediaType`` and ``mimeType`` formats.
[docs]class DeployInputType(AllOfKeywordSchema):
[docs] _all_of = [ DeploymentType(), InputOutputDescriptionMeta(), InputOutputDescriptionSchema(), DeployInputTypeDefinition(), DeployMinMaxOccurs(), DescriptionExtra(),
]
[docs] _sort_first = PROCESS_IO_FIELD_FIRST
[docs] _sort_after = PROCESS_IO_FIELD_AFTER
[docs]class DeployInputTypeWithID(InputIdentifierType, DeployInputType): pass
# for [{id: "", ...}] representation within ProcessDescription (OLD schema)
[docs]class DescribeInputTypeList(ExtendedSequenceSchema): """ Listing of process inputs descriptions. """
[docs] input = DescribeInputTypeWithID()
# for {"<id>": {...}} representation within ProcessDescription (OGC schema)
[docs]class DescribeInputTypeMap(PermissiveMappingSchema): """ Description of all process inputs under mapping. """
[docs] input_id = DescribeInputType( variable="{input-id}", description="Input definition under mapping of process description.", missing=drop, # allowed because process can have empty inputs (see schema: ProcessDescriptionOGC)
) # for [{id: "", ...}] representation within ProcessDeployment (OLD schema)
[docs]class DeployInputTypeList(ExtendedSequenceSchema): """ Listing of process input definitions to deploy. """
[docs] input_item = DeployInputTypeWithID()
# for {"<id>": {...}} representation within ProcessDeployment (OGC schema)
[docs]class DeployInputTypeMap(PermissiveMappingSchema): """ Definition of all process inputs under mapping. """
[docs] input_id = DeployInputType( variable="{input-id}", description="Input definition under mapping of process deployment."
)
[docs]class DeployInputTypeAny(OneOfKeywordSchema):
[docs] _one_of = [ DeployInputTypeList(), DeployInputTypeMap(),
]
[docs]class LiteralOutputType(LiteralDataType): pass
[docs]class BoundingBoxOutputType(ExtendedMappingSchema):
[docs] supportedCRS = SupportedCRSList()
[docs]class DescribeComplexOutputType(DescribeWithFormats): pass
[docs]class DeployComplexOutputType(DeployWithFormats): pass
[docs]class DescribeOutputTypeDefinition(OneOfKeywordSchema):
[docs] _one_of = [ BoundingBoxOutputType, DescribeComplexOutputType, # should be 2nd to last because very permissive, but requires formats at least LiteralOutputType, # must be last because it's the most permissive (all can default if omitted)
]
[docs]class DeployOutputTypeDefinition(OneOfKeywordSchema):
[docs] _one_of = [ BoundingBoxOutputType, DeployComplexOutputType, # should be 2nd to last because very permissive, but requires formats at least LiteralOutputType, # must be last because it's the most permissive (all can default if omitted)
]
[docs]class DescribeOutputType(AllOfKeywordSchema):
[docs] _all_of = [ DescriptionType(), InputOutputDescriptionMeta(), InputOutputDescriptionSchema(), DescribeOutputTypeDefinition(),
]
[docs] _sort_first = PROCESS_IO_FIELD_FIRST
[docs] _sort_after = PROCESS_IO_FIELD_AFTER
[docs]class DescribeOutputTypeWithID(OutputIdentifierType, DescribeOutputType): pass
[docs]class DescribeOutputTypeList(ExtendedSequenceSchema): """ Listing of process outputs descriptions. """
[docs] output = DescribeOutputTypeWithID()
# for {"<id>": {...}} representation within ProcessDescription (OGC schema)
[docs]class DescribeOutputTypeMap(PermissiveMappingSchema): """ Definition of all process outputs under mapping. """
[docs] output_id = DescribeOutputType( variable="{output-id}", title="ProcessOutputDefinition", description="Output definition under mapping of process description."
) # Different definition than 'Describe' such that nested 'complex' type 'formats' can be validated and backward # compatible with pre-existing/deployed/remote processes, with either ``mediaType`` and ``mimeType`` formats.
[docs]class DeployOutputType(AllOfKeywordSchema):
[docs] _all_of = [ DeploymentType(), InputOutputDescriptionMeta(), InputOutputDescriptionSchema(), DeployOutputTypeDefinition(),
]
[docs] _sort_first = PROCESS_IO_FIELD_FIRST
[docs] _sort_after = PROCESS_IO_FIELD_AFTER
[docs]class DeployOutputTypeWithID(OutputIdentifierType, DeployOutputType): pass
# for [{id: "", ...}] representation within ProcessDeployment (OLD schema)
[docs]class DeployOutputTypeList(ExtendedSequenceSchema): """ Listing of process output definitions to deploy. """
[docs] input = DeployOutputTypeWithID()
# for {"<id>": {...}} representation within ProcessDeployment (OGC schema)
[docs]class DeployOutputTypeMap(PermissiveMappingSchema): """ Definition of all process outputs under mapping. """
[docs] input_id = DeployOutputType( variable="{input-id}", description="Output definition under mapping of process deployment."
)
[docs]class DeployOutputTypeAny(OneOfKeywordSchema):
[docs] _one_of = [ DeployOutputTypeList, DeployOutputTypeMap,
]
[docs]class JobExecuteModeEnum(ExtendedSchemaNode):
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/execute.yaml"
[docs] schema_type = String
[docs] title = "JobExecuteMode"
# no default to enforce required input as per OGC-API schemas # default = EXECUTE_MODE_AUTO
[docs] example = ExecuteMode.ASYNC
[docs] validator = OneOf(ExecuteMode.values())
[docs]class JobControlOptionsEnum(ExtendedSchemaNode):
[docs] schema_type = String
[docs] title = "JobControlOptions"
[docs] default = ExecuteControlOption.ASYNC
[docs] example = ExecuteControlOption.ASYNC
[docs] validator = OneOf(ExecuteControlOption.values())
[docs]class JobResponseOptionsEnum(ExtendedSchemaNode):
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/execute.yaml"
[docs] schema_type = String
[docs] title = "JobResponseOptions"
# no default to enforce required input as per OGC-API schemas # default = ExecuteResponse.DOCUMENT
[docs] example = ExecuteResponse.DOCUMENT
[docs] validator = OneOf(ExecuteResponse.values())
[docs]class TransmissionModeEnum(ExtendedSchemaNode):
[docs] schema_type = String
[docs] title = "TransmissionMode"
[docs] default = ExecuteTransmissionMode.VALUE
[docs] example = ExecuteTransmissionMode.VALUE
[docs] validator = OneOf(ExecuteTransmissionMode.values())
[docs]class JobStatusEnum(ExtendedSchemaNode):
[docs] schema_type = String
[docs] title = "JobStatus"
[docs] default = Status.ACCEPTED
[docs] example = Status.ACCEPTED
[docs] validator = OneOf(JOB_STATUS_CODE_API)
[docs]class JobTypeEnum(ExtendedSchemaNode):
[docs] schema_type = String
[docs] title = "JobType"
[docs] default = null
[docs] example = "process"
[docs] validator = OneOf(["process", "provider", "service"])
[docs]class JobSortEnum(ExtendedSchemaNode):
[docs] schema_type = String
[docs] title = "JobSortingMethod"
[docs] default = Sort.CREATED
[docs] example = Sort.CREATED
[docs] validator = OneOf(SortMethods.JOB)
[docs]class ProcessSortEnum(ExtendedSchemaNode):
[docs] schema_type = String
[docs] title = "ProcessSortMethod"
[docs] default = Sort.ID
[docs] example = Sort.CREATED
[docs] validator = OneOf(SortMethods.PROCESS)
[docs]class QuoteSortEnum(ExtendedSchemaNode):
[docs] schema_type = String
[docs] title = "QuoteSortingMethod"
[docs] default = Sort.ID
[docs] example = Sort.PROCESS
[docs] validator = OneOf(SortMethods.QUOTE)
[docs]class LaunchJobQuerystring(ExtendedMappingSchema):
[docs] tags = ExtendedSchemaNode(String(), title="JobTags", default=None, missing=drop, description="Comma separated tags that can be used to filter jobs later")
[docs]class VisibilityValue(ExtendedSchemaNode):
[docs] schema_type = String
[docs] validator = OneOf(Visibility.values())
[docs] example = Visibility.PUBLIC
[docs]class JobAccess(VisibilityValue): pass
[docs]class VisibilitySchema(ExtendedMappingSchema):
[docs] value = VisibilityValue()
######################################################### # Path parameter definitions #########################################################
[docs]class ProcessPath(ExtendedMappingSchema): # FIXME: support versioning with <id:tag> (https://github.com/crim-ca/weaver/issues/107)
[docs] process_id = AnyIdentifier(description="Process identifier.", example="jsonarray2netcdf")
[docs]class ProviderPath(ExtendedMappingSchema):
[docs] provider_id = AnyIdentifier(description="Remote provider identifier.", example="hummingbird")
[docs]class JobPath(ExtendedMappingSchema):
[docs] job_id = UUID(description="Job ID", example="14c68477-c3ed-4784-9c0f-a4c9e1344db5")
[docs]class BillPath(ExtendedMappingSchema):
[docs] bill_id = UUID(description="Bill ID")
[docs]class QuotePath(ExtendedMappingSchema):
[docs] quote_id = UUID(description="Quote ID")
[docs]class ResultPath(ExtendedMappingSchema):
[docs] result_id = UUID(description="Result ID")
######################################################### # These classes define each of the endpoints parameters #########################################################
[docs]class FrontpageEndpoint(ExtendedMappingSchema):
[docs] header = RequestHeaders()
[docs]class VersionsEndpoint(ExtendedMappingSchema):
[docs] header = RequestHeaders()
[docs]class ConformanceQueries(ExtendedMappingSchema):
[docs] category = ExtendedSchemaNode( String(), missing=drop, default=ConformanceCategory.CONFORMANCE, validator=OneOf(ConformanceCategory.values()), description="Select the desired conformance item references to be returned."
)
[docs]class ConformanceEndpoint(ExtendedMappingSchema):
[docs] header = RequestHeaders()
[docs] querystring = ConformanceQueries()
[docs]class OpenAPIEndpoint(ExtendedMappingSchema):
[docs] header = RequestHeaders()
[docs]class SwaggerUIEndpoint(ExtendedMappingSchema): pass
[docs]class RedocUIEndpoint(ExtendedMappingSchema): pass
[docs]class OWSNamespace(XMLObject):
[docs] prefix = "ows"
[docs] namespace = "http://www.opengis.net/ows/1.1"
[docs]class WPSNamespace(XMLObject):
[docs] prefix = "wps"
[docs] namespace = "http://www.opengis.net/wps/1.0.0"
[docs]class XMLNamespace(XMLObject):
[docs] prefix = "xml"
[docs]class XMLReferenceAttribute(ExtendedSchemaNode, XMLObject):
[docs] schema_type = String
[docs] attribute = True
[docs] name = "href"
[docs] prefix = "xlink"
[docs] format = "url"
[docs]class MimeTypeAttribute(ExtendedSchemaNode, XMLObject):
[docs] schema_type = String
[docs] attribute = True
[docs] name = "mimeType"
[docs] prefix = drop
[docs] example = ContentType.APP_JSON
[docs]class EncodingAttribute(ExtendedSchemaNode, XMLObject):
[docs] schema_type = String
[docs] attribute = True
[docs] name = "encoding"
[docs] prefix = drop
[docs] example = "UTF-8"
[docs]class OWSVersion(ExtendedSchemaNode, OWSNamespace):
[docs] schema_type = String
[docs] name = "Version"
[docs] default = "1.0.0"
[docs] example = "1.0.0"
[docs]class OWSAcceptVersions(ExtendedSequenceSchema, OWSNamespace):
[docs] description = "Accepted versions to produce the response."
[docs] name = "AcceptVersions"
[docs] item = OWSVersion()
[docs]class OWSLanguage(ExtendedSchemaNode, OWSNamespace):
[docs] description = "Desired language to produce the response."
[docs] schema_type = String
[docs] name = "Language"
[docs] default = AcceptLanguage.EN_US
[docs] example = AcceptLanguage.EN_CA
[docs]class OWSLanguageAttribute(OWSLanguage):
[docs] description = "RFC-4646 language code of the human-readable text."
[docs] name = "language"
[docs] attribute = True
[docs]class OWSService(ExtendedSchemaNode, OWSNamespace):
[docs] description = "Desired service to produce the response (SHOULD be 'WPS')."
[docs] schema_type = String
[docs] name = "service"
[docs] attribute = True
[docs] default = AcceptLanguage.EN_US
[docs] example = AcceptLanguage.EN_CA
[docs]class WPSServiceAttribute(ExtendedSchemaNode, XMLObject):
[docs] schema_type = String
[docs] name = "service"
[docs] attribute = True
[docs] default = "WPS"
[docs] example = "WPS"
[docs]class WPSVersionAttribute(ExtendedSchemaNode, XMLObject):
[docs] schema_type = String
[docs] name = "version"
[docs] attribute = True
[docs] default = "1.0.0"
[docs] example = "1.0.0"
[docs]class WPSLanguageAttribute(ExtendedSchemaNode, XMLNamespace):
[docs] schema_type = String
[docs] name = "lang"
[docs] attribute = True
[docs] default = AcceptLanguage.EN_US
[docs] example = AcceptLanguage.EN_CA
[docs]class WPSParameters(ExtendedMappingSchema):
[docs] service = ExtendedSchemaNode(String(), example="WPS", description="Service selection.", validator=OneOfCaseInsensitive(["WPS"]))
[docs] request = ExtendedSchemaNode(String(), example="GetCapabilities", description="WPS operation to accomplish", validator=OneOfCaseInsensitive(["GetCapabilities", "DescribeProcess", "Execute"]))
[docs] version = Version(exaple="1.0.0", default="1.0.0", validator=OneOf(["1.0.0", "2.0.0", "2.0"]))
[docs] identifier = ExtendedSchemaNode(String(), exaple="hello", missing=drop, example="example-process,another-process", description="Single or comma-separated list of process identifiers to describe, "
"and single one for execution.")
[docs] data_inputs = ExtendedSchemaNode(String(), name="DataInputs", missing=drop, example="message=hi&names=user1,user2&value=1", description="Process execution inputs provided as Key-Value Pairs (KVP).")
[docs]class WPSOperationGetNoContent(ExtendedMappingSchema):
[docs] description = "No content body provided (GET requests)."
[docs] default = {}
[docs]class WPSOperationPost(ExtendedMappingSchema):
[docs] schema_ref = "http://schemas.opengis.net/wps/1.0.0/common/RequestBaseType.xsd"
[docs] accepted_versions = OWSAcceptVersions(missing=drop, default="1.0.0")
[docs] language = OWSLanguageAttribute(missing=drop)
[docs] service = OWSService()
[docs]class WPSGetCapabilitiesPost(WPSOperationPost, WPSNamespace):
[docs] schema_ref = "http://schemas.opengis.net/wps/1.0.0/wpsGetCapabilities_request.xsd"
[docs] name = "GetCapabilities"
[docs] title = "GetCapabilities"
[docs]class OWSIdentifier(ExtendedSchemaNode, OWSNamespace):
[docs] schema_type = String
[docs] name = "Identifier"
[docs]class OWSIdentifierList(ExtendedSequenceSchema, OWSNamespace):
[docs] name = "Identifiers"
[docs] item = OWSIdentifier()
[docs]class OWSTitle(ExtendedSchemaNode, OWSNamespace):
[docs] schema_type = String
[docs] name = "Title"
[docs]class OWSAbstract(ExtendedSchemaNode, OWSNamespace):
[docs] schema_type = String
[docs] name = "Abstract"
[docs]class OWSMetadata(ExtendedSequenceSchema, OWSNamespace):
[docs] schema_type = String
[docs] name = "Metadata"
[docs] title = OWSMetadataLink(missing=drop)
[docs]class WPSDescribeProcessPost(WPSOperationPost, WPSNamespace):
[docs] schema_ref = "http://schemas.opengis.net/wps/1.0.0/wpsDescribeProcess_request.xsd"
[docs] name = "DescribeProcess"
[docs] title = "DescribeProcess"
[docs] identifier = OWSIdentifierList( description="Single or comma-separated list of process identifier to describe.", example="example"
)
[docs]class WPSExecuteDataInputs(ExtendedMappingSchema, WPSNamespace):
[docs] description = "XML data inputs provided for WPS POST request (Execute)."
[docs] name = "DataInputs"
[docs] title = "DataInputs"
# FIXME: missing details about 'DataInputs'
[docs]class WPSExecutePost(WPSOperationPost, WPSNamespace):
[docs] schema_ref = "http://schemas.opengis.net/wps/1.0.0/wpsExecute_request.xsd"
[docs] name = "Execute"
[docs] title = "Execute"
[docs] identifier = OWSIdentifier(description="Identifier of the process to execute with data inputs.")
[docs] dataInputs = WPSExecuteDataInputs(description="Data inputs to be provided for process execution.")
[docs]class WPSRequestBody(OneOfKeywordSchema):
[docs] _one_of = [ WPSExecutePost(), WPSDescribeProcessPost(), WPSGetCapabilitiesPost(),
]
[docs] examples = { "Execute": { "summary": "Execute request example.", "value": EXAMPLES["wps_execute_request.xml"]
} }
[docs]class WPSHeaders(ExtendedMappingSchema):
[docs] accept = AcceptHeader(missing=drop)
[docs]class WPSEndpointGet(ExtendedMappingSchema):
[docs] header = WPSHeaders()
[docs] querystring = WPSParameters()
[docs] body = WPSOperationGetNoContent(missing=drop)
[docs]class WPSEndpointPost(ExtendedMappingSchema):
[docs] header = WPSHeaders()
[docs] body = WPSRequestBody()
[docs]class XMLBooleanAttribute(ExtendedSchemaNode, XMLObject):
[docs] schema_type = Boolean
[docs] attribute = True
[docs]class XMLString(ExtendedSchemaNode, XMLObject):
[docs] schema_type = String
[docs]class OWSString(ExtendedSchemaNode, OWSNamespace):
[docs] schema_type = String
[docs]class OWSKeywordList(ExtendedSequenceSchema, OWSNamespace):
[docs] title = "OWSKeywords"
[docs] keyword = OWSString(name="Keyword", title="OWSKeyword", example="Weaver")
[docs]class OWSType(ExtendedMappingSchema, OWSNamespace):
[docs] schema_type = String
[docs] name = "Type"
[docs] example = "theme"
[docs] additionalProperties = { "codeSpace": { "type": "string", "example": "ISOTC211/19115", "xml": {"attribute": True}
} }
[docs]class OWSPhone(ExtendedMappingSchema, OWSNamespace):
[docs] name = "Phone"
[docs] voice = OWSString(name="Voice", title="OWSVoice", example="1-234-567-8910", missing=drop)
[docs] facsimile = OWSString(name="Facsimile", title="OWSFacsimile", missing=drop)
[docs]class OWSAddress(ExtendedMappingSchema, OWSNamespace):
[docs] name = "Address"
[docs] delivery_point = OWSString(name="DeliveryPoint", title="OWSDeliveryPoint", example="123 Place Street", missing=drop)
[docs] city = OWSString(name="City", title="OWSCity", example="Nowhere", missing=drop)
[docs] country = OWSString(name="Country", title="OWSCountry", missing=drop)
[docs] admin_area = OWSString(name="AdministrativeArea", title="AdministrativeArea", missing=drop)
[docs] postal_code = OWSString(name="PostalCode", title="OWSPostalCode", example="A1B 2C3", missing=drop)
[docs] email = OWSString(name="ElectronicMailAddress", title="OWSElectronicMailAddress", example="mail@me.com", validator=Email, missing=drop)
[docs]class OWSContactInfo(ExtendedMappingSchema, OWSNamespace):
[docs] name = "ContactInfo"
[docs] phone = OWSPhone(missing=drop)
[docs] address = OWSAddress(missing=drop)
[docs]class OWSServiceContact(ExtendedMappingSchema, OWSNamespace):
[docs] name = "ServiceContact"
[docs] individual = OWSString(name="IndividualName", title="OWSIndividualName", example="John Smith", missing=drop)
[docs] position = OWSString(name="PositionName", title="OWSPositionName", example="One Man Team", missing=drop)
[docs] contact = OWSContactInfo(missing=drop, default={})
[docs]class OWSServiceProvider(ExtendedMappingSchema, OWSNamespace):
[docs] description = "Details about the institution providing the service."
[docs] name = "ServiceProvider"
[docs] title = "ServiceProvider"
[docs] provider_name = OWSString(name="ProviderName", title="OWSProviderName", example="EXAMPLE")
[docs] provider_site = OWSString(name="ProviderName", title="OWSProviderName", example="http://schema-example.com")
[docs] contact = OWSServiceContact(required=False, defalult={})
[docs]class WPSDescriptionType(ExtendedMappingSchema, OWSNamespace):
[docs] schema_ref = "http://schemas.opengis.net/wps/1.0.0/common/DescriptionType.xsd"
[docs] name = "DescriptionType"
[docs] _title = OWSTitle(description="Title of the service.", example="Weaver")
[docs] abstract = OWSAbstract(description="Detail about the service.", example="Weaver WPS example schema.", missing=drop)
[docs] metadata = OWSMetadata(description="Metadata of the service.", example="Weaver WPS example schema.", missing=drop)
[docs]class OWSServiceIdentification(WPSDescriptionType, OWSNamespace):
[docs] name = "ServiceIdentification"
[docs] title = "ServiceIdentification"
[docs] keywords = OWSKeywordList(name="Keywords")
[docs] type = OWSType()
[docs] svc_type = OWSString(name="ServiceType", title="ServiceType", example="WPS")
[docs] svc_type_ver1 = OWSString(name="ServiceTypeVersion", title="ServiceTypeVersion", example="1.0.0")
[docs] svc_type_ver2 = OWSString(name="ServiceTypeVersion", title="ServiceTypeVersion", example="2.0.0")
[docs] fees = OWSString(name="Fees", title="Fees", example="NONE", missing=drop, default="NONE")
[docs] access = OWSString(name="AccessConstraints", title="AccessConstraints", example="NONE", missing=drop, default="NONE")
[docs] provider = OWSServiceProvider()
[docs]class OWSOperationName(ExtendedSchemaNode, OWSNamespace):
[docs] schema_type = String
[docs] attribute = True
[docs] name = "name"
[docs] example = "GetCapabilities"
[docs] validator = OneOf(["GetCapabilities", "DescribeProcess", "Execute"])
[docs]class OperationRequest(ExtendedMappingSchema, OWSNamespace):
[docs] href = OperationLink()
[docs]class OWS_HTTP(ExtendedMappingSchema, OWSNamespace): # noqa: N802
[docs] get = OperationRequest(name="Get", title="OWSGet")
[docs] post = OperationRequest(name="Post", title="OWSPost")
[docs]class OWS_DCP(ExtendedMappingSchema, OWSNamespace): # noqa: N802
[docs] http = OWS_HTTP(name="HTTP", missing=drop)
[docs] https = OWS_HTTP(name="HTTPS", missing=drop)
[docs]class Operation(ExtendedMappingSchema, OWSNamespace):
[docs] name = OWSOperationName()
[docs] dcp = OWS_DCP()
[docs]class OperationsMetadata(ExtendedSequenceSchema, OWSNamespace):
[docs] name = "OperationsMetadata"
[docs] op = Operation()
[docs]class ProcessVersion(ExtendedSchemaNode, WPSNamespace):
[docs] schema_type = String
[docs] attribute = True
[docs]class OWSProcessSummary(ExtendedMappingSchema, WPSNamespace):
[docs] version = ProcessVersion(name="processVersion", default="None", example="1.2", description="Version of the corresponding process summary.")
[docs] identifier = OWSIdentifier(example="example", description="Identifier to refer to the process.")
[docs] _title = OWSTitle(example="Example Process", description="Title of the process.")
[docs] abstract = OWSAbstract(example="Process for example schema.", description="Detail about the process.")
[docs]class WPSProcessOfferings(ExtendedSequenceSchema, WPSNamespace):
[docs] name = "ProcessOfferings"
[docs] title = "ProcessOfferings"
[docs] process = OWSProcessSummary(name="Process")
[docs]class WPSLanguagesType(ExtendedSequenceSchema, WPSNamespace):
[docs] title = "LanguagesType"
[docs] wrapped = False
[docs] lang = OWSLanguage(name="Language")
[docs]class WPSLanguageSpecification(ExtendedMappingSchema, WPSNamespace):
[docs] name = "Languages"
[docs] title = "Languages"
[docs] default = OWSLanguage(name="Default")
[docs] supported = WPSLanguagesType(name="Supported")
[docs]class WPSResponseBaseType(PermissiveMappingSchema, WPSNamespace):
[docs] schema_ref = "http://schemas.opengis.net/wps/1.0.0/common/ResponseBaseType.xsd"
[docs] service = WPSServiceAttribute()
[docs] version = WPSVersionAttribute()
[docs] lang = WPSLanguageAttribute()
[docs]class WPSProcessVersion(ExtendedSchemaNode, WPSNamespace):
[docs] schema_ref = "http://schemas.opengis.net/wps/1.0.0/common/ProcessVersion.xsd"
[docs] schema_type = String
[docs] description = "Release version of this Process."
[docs] name = "processVersion"
[docs] attribute = True
[docs]class WPSInputDescriptionType(WPSDescriptionType):
[docs] identifier = OWSIdentifier(description="Unique identifier of the input.")
# override below to have different examples/descriptions
[docs] _title = OWSTitle(description="Human-readable representation of the process input.")
[docs] abstract = OWSAbstract(missing=drop)
[docs] metadata = OWSMetadata(missing=drop)
[docs]class WPSLiteralInputType(ExtendedMappingSchema, XMLObject): pass
[docs]class WPSLiteralData(WPSLiteralInputType):
[docs] name = "LiteralData"
[docs]class WPSCRSsType(ExtendedMappingSchema, WPSNamespace):
[docs] crs = XMLString(name="CRS", description="Coordinate Reference System")
[docs]class WPSSupportedCRS(ExtendedSequenceSchema):
[docs] crs = WPSCRSsType(name="CRS")
[docs]class WPSSupportedCRSType(ExtendedMappingSchema, WPSNamespace):
[docs] name = "SupportedCRSsType"
[docs] default = WPSCRSsType(name="Default")
[docs] supported = WPSSupportedCRS(name="Supported")
[docs]class WPSBoundingBoxData(ExtendedMappingSchema, XMLObject):
[docs] data = WPSSupportedCRSType(name="BoundingBoxData")
[docs]class WPSFormatDefinition(ExtendedMappingSchema, XMLObject):
[docs] mime_type = XMLString(name="MimeType", default=ContentType.TEXT_PLAIN, example=ContentType.TEXT_PLAIN)
[docs] encoding = XMLString(name="Encoding", missing=drop, example="base64")
[docs] schema = XMLString(name="Schema", missing=drop)
[docs]class WPSFileFormat(ExtendedMappingSchema, XMLObject):
[docs] name = "Format"
[docs] format_item = WPSFormatDefinition()
[docs]class WPSFormatList(ExtendedSequenceSchema):
[docs] format_item = WPSFileFormat()
[docs]class WPSComplexInputType(ExtendedMappingSchema, WPSNamespace):
[docs] max_mb = XMLString(name="maximumMegabytes", attribute=True)
[docs] defaults = WPSFileFormat(name="Default")
[docs] supported = WPSFormatList(name="Supported")
[docs]class WPSComplexData(ExtendedMappingSchema, XMLObject):
[docs] data = WPSComplexInputType(name="ComplexData")
[docs]class WPSInputFormChoice(OneOfKeywordSchema):
[docs] title = "InputFormChoice"
[docs] _one_of = [ WPSComplexData(), WPSLiteralData(), WPSBoundingBoxData(),
]
[docs]class WPSMinOccursAttribute(MinOccursDefinition, XMLObject):
[docs] name = "minOccurs"
[docs] attribute = True
[docs]class WPSMaxOccursAttribute(MinOccursDefinition, XMLObject):
[docs] name = "maxOccurs"
[docs] prefix = drop
[docs] attribute = True
[docs]class WPSDataInputDescription(ExtendedMappingSchema):
[docs] min_occurs = WPSMinOccursAttribute()
[docs] max_occurs = WPSMaxOccursAttribute()
[docs]class WPSDataInputItem(AllOfKeywordSchema, WPSNamespace):
[docs] _all_of = [ WPSInputDescriptionType(), WPSInputFormChoice(), WPSDataInputDescription(),
]
[docs]class WPSDataInputs(ExtendedSequenceSchema, WPSNamespace):
[docs] name = "DataInputs"
[docs] title = "DataInputs"
[docs] input = WPSDataInputItem()
[docs]class WPSOutputDescriptionType(WPSDescriptionType):
[docs] name = "OutputDescriptionType"
[docs] title = "OutputDescriptionType"
[docs] identifier = OWSIdentifier(description="Unique identifier of the output.")
# override below to have different examples/descriptions
[docs] _title = OWSTitle(description="Human-readable representation of the process output.")
[docs] abstract = OWSAbstract(missing=drop)
[docs] metadata = OWSMetadata(missing=drop)
[docs]class ProcessOutputs(ExtendedSequenceSchema, WPSNamespace):
[docs] name = "ProcessOutputs"
[docs] title = "ProcessOutputs"
[docs] output = WPSOutputDescriptionType()
[docs]class WPSGetCapabilities(WPSResponseBaseType):
[docs] schema_ref = "http://schemas.opengis.net/wps/1.0.0/wpsGetCapabilities_response.xsd"
[docs] name = "Capabilities"
[docs] title = "Capabilities" # not to be confused by 'GetCapabilities' used for request
[docs] svc = OWSServiceIdentification()
[docs] ops = OperationsMetadata()
[docs] offering = WPSProcessOfferings()
[docs] languages = WPSLanguageSpecification()
[docs]class WPSProcessDescriptionType(WPSResponseBaseType, WPSProcessVersion):
[docs] name = "ProcessDescriptionType"
[docs] description = "Description of the requested process by identifier."
[docs] store = XMLBooleanAttribute(name="storeSupported", example=True, default=True)
[docs] status = XMLBooleanAttribute(name="statusSupported", example=True, default=True)
[docs] inputs = WPSDataInputs()
[docs] outputs = ProcessOutputs()
[docs]class WPSProcessDescriptionList(ExtendedSequenceSchema, WPSNamespace):
[docs] name = "ProcessDescriptions"
[docs] title = "ProcessDescriptions"
[docs] description = "Listing of process description for every requested identifier."
[docs] wrapped = False
[docs] process = WPSProcessDescriptionType()
[docs]class WPSDescribeProcess(WPSResponseBaseType):
[docs] schema_ref = "http://schemas.opengis.net/wps/1.0.0/wpsDescribeProcess_response.xsd"
[docs] name = "DescribeProcess"
[docs] title = "DescribeProcess"
[docs] process = WPSProcessDescriptionList()
[docs]class WPSStatusLocationAttribute(ExtendedSchemaNode, XMLObject):
[docs] schema_type = String
[docs] name = "statusLocation"
[docs] prefix = drop
[docs] attribute = True
[docs] format = "file"
[docs]class WPSServiceInstanceAttribute(ExtendedSchemaNode, XMLObject):
[docs] schema_type = String
[docs] name = "serviceInstance"
[docs] prefix = drop
[docs] attribute = True
[docs] format = "url"
[docs]class CreationTimeAttribute(ExtendedSchemaNode, XMLObject):
[docs] schema_type = DateTime
[docs] name = "creationTime"
[docs] title = "CreationTime"
[docs] prefix = drop
[docs] attribute = True
[docs]class WPSStatusSuccess(ExtendedSchemaNode, WPSNamespace):
[docs] schema_type = String
[docs] name = "ProcessSucceeded"
[docs] title = "ProcessSucceeded"
[docs]class WPSStatusFailed(ExtendedSchemaNode, WPSNamespace):
[docs] schema_type = String
[docs] name = "ProcessFailed"
[docs] title = "ProcessFailed"
[docs]class WPSStatus(ExtendedMappingSchema, WPSNamespace):
[docs] name = "Status"
[docs] title = "Status"
[docs] creationTime = CreationTimeAttribute()
[docs] status_success = WPSStatusSuccess(missing=drop)
[docs] status_failed = WPSStatusFailed(missing=drop)
[docs]class WPSProcessSummary(ExtendedMappingSchema, WPSNamespace):
[docs] name = "Process"
[docs] title = "Process"
[docs] identifier = OWSIdentifier()
[docs] _title = OWSTitle()
[docs] abstract = OWSAbstract(missing=drop)
[docs]class WPSOutputBase(ExtendedMappingSchema):
[docs] identifier = OWSIdentifier()
[docs] _title = OWSTitle()
[docs] abstract = OWSAbstract(missing=drop)
[docs]class WPSOutputDefinitionItem(WPSOutputBase, WPSNamespace):
[docs] name = "Output"
# use different title to avoid OpenAPI schema definition clash with 'Output' of 'WPSProcessOutputs'
[docs] title = "OutputDefinition"
[docs]class WPSOutputDefinitions(ExtendedSequenceSchema, WPSNamespace):
[docs] name = "OutputDefinitions"
[docs] title = "OutputDefinitions"
[docs] out_def = WPSOutputDefinitionItem()
[docs]class WPSOutputLiteral(ExtendedMappingSchema):
[docs] data = ()
[docs]class WPSReference(ExtendedMappingSchema, WPSNamespace):
[docs] href = XMLReferenceAttribute()
[docs] mimeType = MimeTypeAttribute()
[docs] encoding = EncodingAttribute()
[docs]class WPSOutputReference(ExtendedMappingSchema):
[docs] title = "OutputReference"
[docs] reference = WPSReference(name="Reference")
[docs]class WPSOutputData(OneOfKeywordSchema):
[docs] _one_of = [ WPSOutputLiteral(), WPSOutputReference(),
]
[docs]class WPSDataOutputItem(AllOfKeywordSchema, WPSNamespace):
[docs] name = "Output"
# use different title to avoid OpenAPI schema definition clash with 'Output' of 'WPSOutputDefinitions'
[docs] title = "DataOutput"
[docs] _all_of = [ WPSOutputBase(), WPSOutputData(),
]
[docs]class WPSProcessOutputs(ExtendedSequenceSchema, WPSNamespace):
[docs] name = "ProcessOutputs"
[docs] title = "ProcessOutputs"
[docs] output = WPSDataOutputItem()
[docs]class WPSExecuteResponse(WPSResponseBaseType, WPSProcessVersion):
[docs] schema_ref = "http://schemas.opengis.net/wps/1.0.0/wpsExecute_response.xsd"
[docs] name = "ExecuteResponse"
[docs] title = "ExecuteResponse" # not to be confused by 'Execute' used for request
[docs] location = WPSStatusLocationAttribute()
[docs] svc_loc = WPSServiceInstanceAttribute()
[docs] process = WPSProcessSummary()
[docs] status = WPSStatus()
[docs] inputs = WPSDataInputs(missing=drop) # when lineage is requested only
[docs] out_def = WPSOutputDefinitions(missing=drop) # when lineage is requested only
[docs] outputs = WPSProcessOutputs()
[docs]class WPSXMLSuccessBodySchema(OneOfKeywordSchema):
[docs] _one_of = [ WPSGetCapabilities(), WPSDescribeProcess(), WPSExecuteResponse(),
]
[docs]class OWSExceptionCodeAttribute(ExtendedSchemaNode, XMLObject):
[docs] schema_type = String
[docs] name = "exceptionCode"
[docs] title = "Exception"
[docs] attribute = True
[docs]class OWSExceptionLocatorAttribute(ExtendedSchemaNode, XMLObject):
[docs] schema_type = String
[docs] name = "locator"
[docs] attribute = True
[docs]class OWSExceptionText(ExtendedSchemaNode, OWSNamespace):
[docs] schema_type = String
[docs] name = "ExceptionText"
[docs]class OWSException(ExtendedMappingSchema, OWSNamespace):
[docs] name = "Exception"
[docs] title = "Exception"
[docs] code = OWSExceptionCodeAttribute(example="MissingParameterValue")
[docs] locator = OWSExceptionLocatorAttribute(default="None", example="service")
[docs] text = OWSExceptionText(example="Missing service")
[docs]class OWSExceptionReport(ExtendedMappingSchema, OWSNamespace):
[docs] name = "ExceptionReport"
[docs] title = "ExceptionReport"
[docs] exception = OWSException()
[docs]class WPSException(ExtendedMappingSchema):
[docs] report = OWSExceptionReport()
[docs]class OkWPSResponse(ExtendedMappingSchema):
[docs] description = "WPS operation successful"
[docs] header = XmlHeader()
[docs] body = WPSXMLSuccessBodySchema()
[docs]class ErrorWPSResponse(ExtendedMappingSchema):
[docs] description = "Unhandled error occurred on WPS endpoint."
[docs] header = XmlHeader()
[docs] body = WPSException()
[docs]class ProviderEndpoint(ProviderPath):
[docs] header = RequestHeaders()
[docs]class ProcessDescriptionQuery(ExtendedMappingSchema): # see: 'ProcessDescription' schema and 'Process.offering' method
[docs] schema = ExtendedSchemaNode( String(), example=ProcessSchema.OGC, default=ProcessSchema.OGC, validator=OneOfCaseInsensitive(ProcessSchema.values()), summary="Selects the desired schema representation of the process description", description=( "Selects the desired schema representation of the process description. "
f"When '{ProcessSchema.OGC}' is used, inputs and outputs will be represented as mapping of objects. " "Process metadata are also directly provided at the root of the content. " f"When '{ProcessSchema.OLD}' is used, inputs and outputs will be represented as list of objects with ID. " "Process metadata are also reported nested under a 'process' field. " "See '#/definitions/ProcessDescription' schema for more details about each case." ) )
[docs]class ProviderProcessEndpoint(ProviderPath, ProcessPath):
[docs] header = RequestHeaders()
[docs] querystring = ProcessDescriptionQuery()
[docs]class ProcessEndpoint(ProcessPath):
[docs] header = RequestHeaders()
[docs] querystring = ProcessDescriptionQuery()
[docs]class ProcessPackageEndpoint(ProcessPath):
[docs] header = RequestHeaders()
[docs]class ProcessPayloadEndpoint(ProcessPath):
[docs] header = RequestHeaders()
[docs]class ProcessVisibilityGetEndpoint(ProcessPath):
[docs] header = RequestHeaders()
[docs]class ProcessVisibilityPutEndpoint(ProcessPath):
[docs] header = RequestHeaders()
[docs] body = VisibilitySchema()
[docs]class ProviderJobEndpoint(ProviderPath, ProcessPath, JobPath):
[docs] header = RequestHeaders()
[docs]class JobEndpoint(JobPath):
[docs] header = RequestHeaders()
[docs]class ProcessInputsEndpoint(ProcessPath, JobPath):
[docs] header = RequestHeaders()
[docs]class ProviderInputsEndpoint(ProviderPath, ProcessPath, JobPath):
[docs] header = RequestHeaders()
[docs]class JobInputsOutputsQuery(ExtendedMappingSchema):
[docs] schema = ExtendedSchemaNode( String(), title="JobInputsOutputsQuerySchema", example=JobInputsOutputsSchema.OGC, default=JobInputsOutputsSchema.OLD, validator=OneOfCaseInsensitive(JobInputsOutputsSchema.values()), summary="Selects the schema employed for representation of submitted job inputs and outputs.", description=( "Selects the schema employed for representing job inputs and outputs that were submitted for execution. "
f"When '{JobInputsOutputsSchema.OLD}' is employed, listing of object with IDs is returned. " f"When '{JobInputsOutputsSchema.OGC}' is employed, mapping of object definitions is returned. " "If no schema is requested, the original formats from submission are employed, which could be a mix of " "both representations. Providing a schema forces their corresponding conversion as applicable." ) )
[docs]class JobInputsEndpoint(JobPath):
[docs] header = RequestHeaders()
[docs] querystring = JobInputsOutputsQuery()
[docs]class JobOutputQuery(ExtendedMappingSchema):
[docs] schema = ExtendedSchemaNode( String(), title="JobOutputResultsSchema", example=JobInputsOutputsSchema.OGC, default=JobInputsOutputsSchema.OLD, validator=OneOfCaseInsensitive(JobInputsOutputsSchema.values()), summary="Selects the schema employed for representation of job outputs.", description=( "Selects the schema employed for representation of job outputs for providing file Content-Type details. "
f"When '{JobInputsOutputsSchema.OLD}' is employed, " "'format.mimeType' is used and 'type' is reported as well. " f"When '{JobInputsOutputsSchema.OGC}' is employed, " "'format.mediaType' is used and 'type' is reported as well. " "When the '+strict' value is added, only the 'format' or 'type' will be represented according to the " f"reference standard ({JobInputsOutputsSchema.OGC}, {JobInputsOutputsSchema.OLD}) representation." ) )
[docs]class ProcessOutputsEndpoint(ProcessPath, JobPath):
[docs] header = RequestHeaders()
[docs] querystring = JobOutputQuery()
[docs]class ProviderOutputsEndpoint(ProviderPath, ProcessPath, JobPath):
[docs] header = RequestHeaders()
[docs] querystring = JobOutputQuery()
[docs]class JobOutputsEndpoint(JobPath):
[docs] header = RequestHeaders()
[docs] querystring = JobOutputQuery()
[docs]class ProcessResultEndpoint(ProcessOutputsEndpoint):
[docs] deprecated = True
[docs] header = RequestHeaders()
[docs]class ProviderResultEndpoint(ProviderOutputsEndpoint):
[docs] deprecated = True
[docs] header = RequestHeaders()
[docs]class JobResultEndpoint(JobPath):
[docs] deprecated = True
[docs] header = RequestHeaders()
[docs]class ProcessResultsEndpoint(ProcessPath, JobPath):
[docs] header = RequestHeaders()
[docs]class ProviderResultsEndpoint(ProviderPath, ProcessPath, JobPath):
[docs] header = RequestHeaders()
[docs]class JobResultsEndpoint(ProviderPath, ProcessPath, JobPath):
[docs] header = RequestHeaders()
[docs]class ProviderExceptionsEndpoint(ProviderPath, ProcessPath, JobPath):
[docs] header = RequestHeaders()
[docs]class JobExceptionsEndpoint(JobPath):
[docs] header = RequestHeaders()
[docs]class ProcessExceptionsEndpoint(ProcessPath, JobPath):
[docs] header = RequestHeaders()
[docs]class ProviderLogsEndpoint(ProviderPath, ProcessPath, JobPath):
[docs] header = RequestHeaders()
[docs]class JobLogsEndpoint(JobPath):
[docs] header = RequestHeaders()
[docs]class ProcessLogsEndpoint(ProcessPath, JobPath):
[docs] header = RequestHeaders()
[docs]class JobStatisticsEndpoint(JobPath):
[docs] header = RequestHeaders()
[docs]class ProcessJobStatisticsEndpoint(ProcessPath, JobPath):
[docs] header = RequestHeaders()
[docs]class ProviderJobStatisticsEndpoint(ProviderPath, ProcessPath, JobPath):
[docs] header = RequestHeaders()
################################################################## # These classes define schemas for requests that feature a body ##################################################################
[docs]class ProviderPublic(ExtendedMappingSchema):
[docs] public = ExtendedSchemaNode( Boolean(), default=False, description="Whether the service is defined as publicly visible. "
"This will not control allowance/denial of requests to the registered endpoint of the service. " "It only indicates if it should appear during listing of providers." )
[docs]class CreateProviderRequestBody(ProviderPublic):
[docs] id = AnyIdentifier()
[docs] url = URL(description="Endpoint where to query the provider.")
[docs]class ExecuteInputDataType(InputIdentifierType): pass
[docs]class ExecuteOutputDataType(OutputIdentifierType): pass
[docs]class ExecuteOutputDefinition(ExtendedMappingSchema):
[docs] transmissionMode = TransmissionModeEnum(missing=drop)
[docs] format = Format(missing=drop)
[docs]class ExecuteOutputItem(ExecuteOutputDataType, ExecuteOutputDefinition): pass
[docs]class ExecuteOutputSpecList(ExtendedSequenceSchema): """ Filter list of outputs to be obtained from execution and their reporting method. """
[docs] output = ExecuteOutputItem()
[docs]class ExecuteOutputMapAdditionalProperties(ExtendedMappingSchema):
[docs] output_id = ExecuteOutputDefinition(variable="{output-id}", title="ExecuteOutputSpecMap", description="Desired output reporting method.")
[docs]class ExecuteOutputSpecMap(AnyOfKeywordSchema):
[docs] _any_of = [ ExecuteOutputMapAdditionalProperties(), # normal {"<output-id>": {...}} EmptyMappingSchema(), # allows explicitly provided {}
]
[docs]class ExecuteOutputSpec(OneOfKeywordSchema): """ Filter list of outputs to be obtained from execution and define their reporting method. """
[docs] _one_of = [ # OLD format: {"outputs": [{"id": "<id>", "transmissionMode": "value|reference"}, ...]} ExecuteOutputSpecList(), # OGC-API: {"inputs": {"<id>": {"transmissionMode": "value|reference"}, ...}} ExecuteOutputSpecMap(),
]
[docs]class ProviderNameSchema(AnyIdentifier):
[docs] title = "ProviderName"
[docs] description = "Identifier of the remote provider."
[docs]class ProviderSummarySchema(DescriptionType, ProviderPublic, DescriptionMeta, DescriptionLinks): """ Service provider summary definition. """
[docs] id = ProviderNameSchema()
[docs] url = URL(description="Endpoint of the service provider.")
[docs] type = ExtendedSchemaNode(String())
[docs] _sort_first = PROVIDER_DESCRIPTION_FIELD_FIRST
[docs] _sort_after = PROVIDER_DESCRIPTION_FIELD_AFTER
[docs]class ProviderCapabilitiesSchema(ProviderSummarySchema): """ Service provider detailed capabilities. """
[docs]class TransmissionModeList(ExtendedSequenceSchema):
[docs] transmissionMode = TransmissionModeEnum()
[docs]class JobControlOptionsList(ExtendedSequenceSchema):
[docs] jobControlOption = JobControlOptionsEnum()
[docs]class ExceptionReportType(ExtendedMappingSchema):
[docs] code = ExtendedSchemaNode(String())
[docs] description = ExtendedSchemaNode(String(), missing=drop)
[docs]class ProcessControl(ExtendedMappingSchema):
[docs] jobControlOptions = JobControlOptionsList(missing=ExecuteControlOption.values(), default=ExecuteControlOption.values())
[docs] outputTransmission = TransmissionModeList(missing=ExecuteTransmissionMode.values(), default=ExecuteTransmissionMode.values())
[docs]class ProcessLocations(ExtendedMappingSchema): """ Additional endpoint locations specific to the process. """
[docs] processDescriptionURL = URL(description="Process description endpoint using OGC-API interface.", missing=drop, title="processDescriptionURL")
[docs] processEndpointWPS1 = URL(description="Process description endpoint using WPS-1 interface.", missing=drop, title="processEndpointWPS1")
[docs] executeEndpoint = URL(description="Endpoint where the process can be executed from.", missing=drop, title="executeEndpoint")
# 'links' already included via 'ProcessDescriptionType->DescriptionType'
[docs]class ProcessSummary( ProcessDescriptionType, DescriptionMeta, ProcessControl, ProcessLocations, DescriptionLinks ): """ Summary process definition. """
[docs] _sort_first = PROCESS_DESCRIPTION_FIELD_FIRST
[docs] _sort_after = PROCESS_DESCRIPTION_FIELD_AFTER
[docs]class ProcessSummaryList(ExtendedSequenceSchema):
[docs] summary = ProcessSummary()
[docs]class ProcessNamesList(ExtendedSequenceSchema):
[docs] process_name = ProcessIdentifier()
[docs]class ProcessListing(OneOfKeywordSchema):
[docs] _one_of = [ ProcessSummaryList(description="Listing of process summary details from existing definitions."), ProcessNamesList(description="Listing of process names when not requesting details.", missing=drop), # in case of empty list, both schema are valid, drop this one to resolve
]
[docs]class ProcessCollection(ExtendedMappingSchema):
[docs] processes = ProcessListing()
[docs]class ProcessPagingQuery(ExtendedMappingSchema):
[docs] sort = ProcessSortEnum(missing=drop)
# if page is omitted but limit provided, use reasonable zero by default
[docs] page = ExtendedSchemaNode(Integer(allow_string=True), missing=0, default=0, validator=Range(min=0))
[docs] limit = ExtendedSchemaNode(Integer(allow_string=True), missing=None, default=None, validator=Range(min=1))
[docs]class ProcessVisibility(ExtendedMappingSchema):
[docs] visibility = VisibilityValue(missing=drop)
[docs]class ProcessDeploymentProfile(ExtendedMappingSchema):
[docs] deploymentProfile = URL(missing=drop)
[docs]class Process( # following are like 'ProcessSummary', # except without 'ProcessControl' and 'DescriptionLinks' that are outside of nested 'process' ProcessDescriptionType, DescriptionMeta, # following are additional fields only in description, just like for OGC-API ProcessDescription ProcessContext, ProcessVisibility, ProcessLocations ): """ Old nested process schema for process description. """ # note: deprecated in favor of OGC-API schema
[docs] inputs = DescribeInputTypeList(description="Inputs definition of the process.")
[docs] outputs = DescribeOutputTypeList(description="Outputs definition of the process.")
[docs] _sort_first = PROCESS_DESCRIPTION_FIELD_FIRST
[docs] _sort_after = PROCESS_DESCRIPTION_FIELD_AFTER
[docs]class ProcessDescriptionOLD(ProcessControl, ProcessDeploymentProfile, DescriptionLinks): """ Old schema for process description. """
[docs] deprecated = True
[docs] process = Process()
[docs] _sort_first = PROCESS_DESCRIPTION_FIELD_FIRST_OLD_SCHEMA
[docs] _sort_after = PROCESS_DESCRIPTION_FIELD_AFTER_OLD_SCHEMA
[docs]class ProcessDescriptionOGC( ProcessSummary, ProcessContext, ProcessVisibility, ProcessLocations, ProcessDeploymentProfile, DescriptionLinks ): """ OGC-API schema for process description. """ # technically, empty inputs are allowed for processes that should generate constant/randomized outputs # example: # https://pavics.ouranos.ca/twitcher/ows/proxy/catalog # ?service=WPS&request=DescribeProcess&version=1.0.0&identifier=pavicstestdocs
[docs] inputs = DescribeInputTypeMap(description="Inputs definition of the process.", missing=drop, default={})
[docs] outputs = DescribeOutputTypeMap(description="Outputs definition of the process.")
[docs] _sort_first = PROCESS_DESCRIPTION_FIELD_FIRST
[docs] _sort_after = PROCESS_DESCRIPTION_FIELD_AFTER
[docs]class ProcessDescription(OneOfKeywordSchema): """ Supported schema representations of a process description (based on specified query parameters). """
[docs] _one_of = [ ProcessDescriptionOGC, ProcessDescriptionOLD,
]
[docs]class ProcessDeployment(ProcessSummary, ProcessContext, ProcessDeployMeta): # explicit "abstract" handling for bw-compat, new versions should use "description" # only allowed in deploy to support older servers that report abstract (or parsed from WPS-1/2) # recent OGC-API v1+ will usually provide directly "description" as per the specification
[docs] abstract = ExtendedSchemaNode(String(), missing=drop, deprecated=True, description="Detailed explanation of the process being deployed. "
"[Deprecated] Consider using 'description' instead.") # allowed undefined I/O during deploy because of reference from owsContext or executionUnit
[docs] inputs = DeployInputTypeAny( missing=drop, title="DeploymentInputs", description="Additional definitions for process inputs to extend generated details by the referred package. "
"These are optional as they can mostly be inferred from the 'executionUnit', but allow specific " f"overrides (see '{DOC_URL}/package.html#correspondence-between-cwl-and-wps-fields')")
[docs] outputs = DeployOutputTypeAny( missing=drop, title="DeploymentOutputs", description="Additional definitions for process outputs to extend generated details by the referred package. "
"These are optional as they can mostly be inferred from the 'executionUnit', but allow specific " f"overrides (see '{DOC_URL}/package.html#correspondence-between-cwl-and-wps-fields')")
[docs] visibility = VisibilityValue(missing=drop)
[docs] _sort_first = PROCESS_DESCRIPTION_FIELD_FIRST
[docs] _sort_after = PROCESS_DESCRIPTION_FIELD_AFTER
[docs]class Duration(ExtendedSchemaNode): # note: using String instead of Time because timedelta object cannot be directly handled (missing parts at parsing)
[docs] schema_type = String
[docs] description = "Human-readable representation of the duration."
[docs] example = "hh:mm:ss"
# FIXME: use ISO-8601 duration (?) - P[n]Y[n]M[n]DT[n]H[n]M[n]S # https://pypi.org/project/isodate/ # https://en.wikipedia.org/wiki/ISO_8601#Durations # See: # 'duration.to_iso8601' already employed for quotes, should apply for jobs as well
[docs]class DurationISO(ExtendedSchemaNode): """ Duration represented using ISO-8601 format. .. seealso:: - https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.7.3.1 - :rfc:`3339#appendix-A` """
[docs] schema_ref = "https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.7.3.1"
[docs] schema_type = String
[docs] description = "ISO-8601 representation of the duration."
[docs] example = "P[n]Y[n]M[n]DT[n]H[n]M[n]S"
[docs] format = "duration"
[docs] def deserialize(self, cstruct): # type: (Union[datetime.timedelta, str]) -> str if isinstance(cstruct, datetime.timedelta) or isinstance(cstruct, str) and not cstruct.startswith("P"): return duration.to_iso8601(cstruct) return cstruct
[docs]class JobStatusInfo(ExtendedMappingSchema):
[docs] jobID = UUID(example="a9d14bf4-84e0-449a-bac8-16e598efe807", description="ID of the job.")
[docs] processID = ProcessIdentifier(missing=None, default=None, description="Process identifier corresponding to the job execution.")
[docs] providerID = ProcessIdentifier(missing=None, default=None, description="Provider identifier corresponding to the job execution.")
[docs] type = JobTypeEnum(description="Type of the element associated to the creation of this job.")
[docs] status = JobStatusEnum(description="Last updated status.")
[docs] message = ExtendedSchemaNode(String(), missing=drop, description="Information about the last status update.")
[docs] created = ExtendedSchemaNode(DateTime(), missing=drop, default=None, description="Timestamp when the process execution job was created.")
[docs] started = ExtendedSchemaNode(DateTime(), missing=drop, default=None, description="Timestamp when the process started execution if applicable.")
[docs] finished = ExtendedSchemaNode(DateTime(), missing=drop, default=None, description="Timestamp when the process completed execution if applicable.")
[docs] updated = ExtendedSchemaNode(DateTime(), missing=drop, default=None, description="Timestamp of the last update of the job status. This can correspond to "
"any of the other timestamps according to current execution status or " "even slightly after job finished execution according to the duration " "needed to deallocate job resources and store results.")
[docs] duration = Duration(missing=drop, description="Duration since the start of the process execution.")
[docs] runningDuration = DurationISO(missing=drop, description="Duration in ISO-8601 format since the start of the process execution.")
[docs] runningSeconds = NumberType(missing=drop, description="Duration in seconds since the start of the process execution.")
[docs] expirationDate = ExtendedSchemaNode(DateTime(), missing=drop, description="Timestamp when the job will be canceled if not yet completed.")
[docs] estimatedCompletion = ExtendedSchemaNode(DateTime(), missing=drop)
[docs] nextPoll = ExtendedSchemaNode(DateTime(), missing=drop, description="Timestamp when the job will prompted for updated status details.")
[docs] percentCompleted = NumberType(example=0, validator=Range(min=0, max=100), description="Completion percentage of the job as indicated by the process.")
[docs] progress = ExtendedSchemaNode(Integer(), example=100, validator=Range(0, 100), description="Completion progress of the job (alias to 'percentCompleted').")
[docs]class JobEntrySchema(OneOfKeywordSchema): # note: # Since JobID is a simple string (not a dict), no additional mapping field can be added here. # They will be discarded by `OneOfKeywordSchema.deserialize()`.
[docs] _one_of = [ JobStatusInfo, UUID(description="Job ID."),
]
[docs]class JobCollection(ExtendedSequenceSchema):
[docs] item = JobEntrySchema()
[docs]class CreatedJobStatusSchema(DescriptionSchema):
[docs] jobID = UUID(description="Unique identifier of the created job for execution.")
[docs] processID = ProcessIdentifier(description="Identifier of the process that will be executed.")
[docs] providerID = AnyIdentifier(description="Remote provider identifier if applicable.", missing=drop)
[docs] status = ExtendedSchemaNode(String(), example=Status.ACCEPTED)
[docs] location = ExtendedSchemaNode(String(), example="http://{host}/weaver/processes/{my-process-id}/jobs/{my-job-id}")
[docs]class CreatedQuotedJobStatusSchema(CreatedJobStatusSchema):
[docs] bill = UUID(description="ID of the created bill.")
[docs]class GetPagingJobsSchema(ExtendedMappingSchema):
[docs] jobs = JobCollection()
[docs] limit = ExtendedSchemaNode(Integer(), missing=10, default=10, validator=Range(min=1, max=10000))
[docs] page = ExtendedSchemaNode(Integer(), validator=Range(min=0))
[docs]class JobCategoryFilters(PermissiveMappingSchema):
[docs] category = ExtendedSchemaNode(String(), title="CategoryFilter", variable="{category}", default=None, missing=None, description="Value of the corresponding parameter forming that category group.")
[docs]class GroupedJobsCategorySchema(ExtendedMappingSchema):
[docs] category = JobCategoryFilters(description="Grouping values that compose the corresponding job list category.")
[docs] jobs = JobCollection(description="List of jobs that matched the corresponding grouping values.")
[docs] count = ExtendedSchemaNode(Integer(), description="Number of matching jobs for the corresponding group category.")
[docs]class GroupedCategoryJobsSchema(ExtendedSequenceSchema):
[docs] job_group_category_item = GroupedJobsCategorySchema()
[docs]class GetGroupedJobsSchema(ExtendedMappingSchema):
[docs] groups = GroupedCategoryJobsSchema()
[docs]class GetQueriedJobsSchema(OneOfKeywordSchema):
[docs] _one_of = [ GetPagingJobsSchema(description="Matched jobs according to filter queries."), GetGroupedJobsSchema(description="Matched jobs grouped by specified categories."),
]
[docs] total = ExtendedSchemaNode(Integer(), description="Total number of matched jobs regardless of grouping or paging result.")
[docs]class DismissedJobSchema(ExtendedMappingSchema):
[docs] status = JobStatusEnum()
[docs] jobID = UUID(description="ID of the job.")
[docs] message = ExtendedSchemaNode(String(), example="Job dismissed.")
[docs] percentCompleted = ExtendedSchemaNode(Integer(), example=0)
# same as base Format, but for process/job responses instead of process submission # (ie: 'Format' is for allowed/supported formats, this is the result format)
[docs]class DataEncodingAttributes(FormatSelection): pass
[docs]class Reference(ExtendedMappingSchema):
[docs] title = "Reference"
[docs] href = ExecuteReferenceURL(description="Endpoint of the reference.")
[docs] format = DataEncodingAttributes(missing=drop)
[docs] body = ExtendedSchemaNode(String(), missing=drop)
[docs] bodyReference = ReferenceURL(missing=drop)
[docs]class ArrayReference(ExtendedSequenceSchema):
[docs] item = Reference()
[docs]class ArrayReferenceValueType(ExtendedMappingSchema):
[docs] value = ArrayReference()
# Backward compatible data-input that allows values to be nested under 'data' or 'value' fields, # both for literal values and link references, for inputs submitted as list-items. # Also allows the explicit 'href' (+ optional format) reference for a link. # # Because this data-input structure applies only to list-items (see 'ExecuteInputItem' below), mapping is always needed. # (i.e.: values cannot be submitted inline in the list, because field 'id' of each input must also be provided) # For this reason, one of 'value', 'data', 'href' or 'reference' is mandatory.
[docs]class ExecuteInputAnyType(OneOfKeywordSchema): """ Permissive variants that we attempt to parse automatically. """
[docs] _one_of = [ # Array of literal data with 'data' key ArrayLiteralDataType(), # same with 'value' key (OGC specification) ArrayLiteralValueType(), # Array of HTTP references with various keywords ArrayReferenceValueType(), # literal data with 'data' key AnyLiteralDataType(), # same with 'value' key (OGC specification) AnyLiteralValueType(), # HTTP references with various keywords LiteralReference(), Reference()
]
[docs]class ExecuteInputItem(ExecuteInputDataType, ExecuteInputAnyType):
[docs] description = ( "Default value to be looked for uses key 'value' to conform to older drafts of OGC-API standard. "
"Even older drafts that allowed other fields 'data' instead of 'value' and 'reference' instead of 'href' " "are also looked for to remain back-compatible." ) # backward compatible definition: # # inputs: [ # {"id": "<id>", "value": <data>}, # {"id": "<id>", "href": <link>} # ... (other variants) ... # ] #
[docs]class ExecuteInputListValues(ExtendedSequenceSchema):
[docs] input_item = ExecuteInputItem(summary="Received list input value definition during job submission.")
# same as 'ExecuteInputReference', but using 'OGC' schema with 'type' field # Defined as: # https://github.com/opengeospatial/ogcapi-processes/blob/master/core/openapi/schemas/link.yaml # But explicitly in the context of an execution input, rather than any other link (eg: metadata) # same as 'ExecuteInputLink', but using 'OLD' schema with 'format' field
[docs]class ExecuteInputReference(Reference):
[docs] summary = "Execute input reference link definition with parameters."
[docs]class ExecuteInputFile(AnyOfKeywordSchema):
[docs] _any_of = [ ExecuteInputFileLink(), # 'OGC' schema with 'type: <MediaType>' ExecuteInputReference(), # 'OLD' schema with 'format: {mimeType|mediaType: <MediaType>}'
] # https://github.com/opengeospatial/ogcapi-processes/blob/master/core/openapi/schemas/inputValueNoObject.yaml # Any literal value directly provided inline in input mapping. # # {"inputs": {"<id>": <literal-data>}} # # Excludes objects to avoid conflict with later object mapping and {"value": <data>} definitions. # Excludes array literals that will be defined separately with allowed array of any item within this schema. # FIXME: does not support byte/binary type (string + format:byte) - see also: 'AnyLiteralType' # https://github.com/opengeospatial/ogcapi-processes/blob/master/core/openapi/schemas/binaryInputValue.yaml # FIXME: does not support bbox # https://github.com/opengeospatial/ogcapi-processes/blob/master/core/openapi/schemas/bbox.yaml
[docs]class ExecuteInputInlineValue(OneOfKeywordSchema):
[docs] description = "Execute input value provided inline."
[docs] _one_of = [ ExtendedSchemaNode(Float(), title="ExecuteInputValueFloat"), ExtendedSchemaNode(Integer(), title="ExecuteInputValueInteger"), ExtendedSchemaNode(Boolean(), title="ExecuteInputValueBoolean"), ExtendedSchemaNode(String(), title="ExecuteInputValueString"),
] # https://github.com/opengeospatial/ogcapi-processes/blob/master/core/openapi/schemas/inputValue.yaml # # oneOf: # - $ref: "inputValueNoObject.yaml" # - type: object
[docs]class ExecuteInputObjectData(OneOfKeywordSchema):
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/inputValue.yaml"
[docs] description = "Data value of any schema "
[docs] _one_of = [ ExecuteInputInlineValue(), PermissiveMappingSchema(description="Data provided as any object schema."),
] # https://github.com/opengeospatial/ogcapi-processes/blob/master/core/openapi/schemas/qualifiedInputValue.yaml
[docs]class ExecuteInputQualifiedValue(Format):
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/qualifiedInputValue.yaml"
[docs] value = ExecuteInputObjectData() # can be anything, including literal value, array of them, nested object
# https://github.com/opengeospatial/ogcapi-processes/blob/master/core/openapi/schemas/inlineOrRefData.yaml # # oneOf: # - $ref: "inputValueNoObject.yaml" # in OGC-API spec, includes a generic array # - $ref: "qualifiedInputValue.yaml" # - $ref: "link.yaml" #
[docs]class ExecuteInputInlineOrRefData(OneOfKeywordSchema):
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/inlineOrRefData.yaml"
[docs] _one_of = [ ExecuteInputInlineValue(), # <inline-literal> ExecuteInputQualifiedValue(), # {"value": <anything>} ExecuteInputFile(), # 'href' with either 'type' (OGC) or 'format' (OLD)
# FIXME: other types here, 'bbox+crs', 'collection', 'nested process', etc. ]
[docs]class ExecuteInputArrayValues(ExtendedSequenceSchema):
[docs] item_value = ExecuteInputInlineOrRefData()
# combine 'inlineOrRefData' and its 'array[inlineOrRefData]' variants to simplify 'ExecuteInputAny' definition
[docs]class ExecuteInputData(OneOfKeywordSchema):
[docs] description = "Execute data definition of the input."
[docs] _one_of = [ ExecuteInputInlineOrRefData, ExecuteInputArrayValues,
] # https://github.com/opengeospatial/ogcapi-processes/blob/master/core/openapi/schemas/execute.yaml # # inputs: # additionalProperties: # this is the below 'variable=<input-id>' # oneOf: # - $ref: "inlineOrRefData.yaml" # - type: array # items: # $ref: "inlineOrRefData.yaml" #
[docs]class ExecuteInputMapAdditionalProperties(ExtendedMappingSchema):
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/execute.yaml"
[docs] input_id = ExecuteInputData(variable="{input-id}", title="ExecuteInputValue", description="Received mapping input value definition during job submission.")
[docs]class ExecuteInputMapValues(AnyOfKeywordSchema):
[docs] _any_of = [ ExecuteInputMapAdditionalProperties(), # normal {"<input-id>": {...}} EmptyMappingSchema(), # allows explicitly provided {}
]
[docs]class ExecuteInputValues(OneOfKeywordSchema):
[docs] _one_of = [ # OLD format: {"inputs": [{"id": "<id>", "value": <data>}, ...]} ExecuteInputListValues(description="Process job execution inputs defined as item listing."), # OGC-API: {"inputs": {"<id>": <data>, "<id>": {"value": <data>}, ...}} ExecuteInputMapValues(description="Process job execution inputs defined as mapping."),
]
[docs]class ExecuteInputOutputs(ExtendedMappingSchema): # Permit unspecified (optional) inputs for processes that could technically allow no-inputs definition (CWL). # This is very unusual in real world scenarios, but has some possible cases: constant endpoint fetcher, RNG output. # # NOTE: # It is **VERY** important to use 'default={}' and not 'missing=drop' contrary to other optional fields. # Using 'drop' causes and invalid input definition to be ignored/removed and not be validated for expected schema. # We want to ensure format is validated if present to rapidly report the issue and not move on to full execution. # If 'inputs' are indeed omitted, the default with match against and empty 'ExecuteInputMapValues' schema. # If 'inputs' are explicitly provided as '{}' or '[]', it will also behave the right way for no-inputs process. # # See tests validating both cases (incorrect schema vs optionals inputs): # - 'tests.wps_restapi.test_processes.WpsRestApiProcessesTest.test_execute_process_missing_required_params' # - 'tests.wps_restapi.test_providers.WpsRestApiProcessesTest.test_execute_process_no_error_not_required_params' # - 'tests.wps_restapi.test_providers.WpsRestApiProcessesTest.test_get_provider_process_no_inputs' # - 'tests.wps_restapi.test_colander_extras.test_oneof_variable_dict_or_list' # # OGC 'execute.yaml' also does not enforce any required item.
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/execute.yaml"
[docs] inputs = ExecuteInputValues(default={}, description="Values submitted for execution.")
[docs] outputs = ExecuteOutputSpec( description=( "Defines which outputs to be obtained from the execution (filtered or all), " "as well as the reporting method for each output according to 'transmissionMode', " "the 'response' type, and the execution 'mode' provided " "(see for more details: https://pavics-weaver.readthedocs.io/en/latest/processes.html#execution-body)." ), default={}
)
[docs]class Execute(ExecuteInputOutputs):
[docs] mode = JobExecuteModeEnum( missing=drop, default=ExecuteMode.AUTO, deprecated=True, description=( "Desired execution mode specified directly. This is intended for backward compatibility support. " "To obtain more control over execution mode selection, employ the official Prefer header instead " "(see for more details: https://pavics-weaver.readthedocs.io/en/latest/processes.html#execution-mode)." ), validator=OneOf(ExecuteMode.values())
)
[docs] response = JobResponseOptionsEnum( missing=drop, default=ExecuteResponse.DOCUMENT, description=( "Indicates the desired representation format of the response. " "(see for more details: https://pavics-weaver.readthedocs.io/en/latest/processes.html#execution-body)." ), validator=OneOf(ExecuteResponse.values())
)
[docs] notification_email = ExtendedSchemaNode( String(), missing=drop, validator=Email(), description="Optionally send a notification email when the job is done."
)
[docs]class QuoteStatusSchema(ExtendedSchemaNode):
[docs] schema_type = String
[docs] validator = OneOf(QuoteStatus.values())
[docs]class PartialQuoteSchema(ExtendedMappingSchema):
[docs] id = UUID(description="Quote ID.")
[docs] status = QuoteStatusSchema()
[docs] processID = ProcessIdentifier(description="Process identifier corresponding to the quote definition.")
[docs]class Price(ExtendedSchemaNode):
[docs] schema_type = Money
# not official, but common (https://github.com/OAI/OpenAPI-Specification/issues/845#issuecomment-378139730)
[docs] format = "decimal"
[docs]class QuoteProcessParameters(PermissiveMappingSchema, ExecuteInputOutputs):
[docs] description = ( "Parameters passed for traditional process execution (inputs, outputs) "
"with added metadata for quote evaluation." )
[docs]class UserIdSchema(OneOfKeywordSchema):
[docs] _one_of = [ ExtendedSchemaNode(String(), missing=drop), ExtendedSchemaNode(Integer(), default=None),
]
[docs]class StepQuotation(PartialQuoteSchema):
[docs] detail = ExtendedSchemaNode(String(), description="Detail about quote processing.", missing=None)
[docs] price = Price(description="Estimated price for process execution.")
[docs] currency = ExtendedSchemaNode(String(), description="Currency code in ISO-4217 format.", missing=None)
[docs] expire = ExtendedSchemaNode(DateTime(), description="Expiration date and time of the quote in ISO-8601 format.")
[docs] created = ExtendedSchemaNode(DateTime(), description="Creation date and time of the quote in ISO-8601 format.")
[docs] userID = UserIdSchema(description="User ID that requested the quote.", missing=required, default=None)
[docs] estimatedTime = Duration(missing=drop, description="Estimated duration of process execution in human-readable format.")
[docs] estimatedSeconds = ExtendedSchemaNode(Integer(), missing=drop, description="Estimated duration of process execution in seconds.")
[docs] estimatedDuration = DurationISO(missing=drop, description="Estimated duration of process execution in ISO-8601 format.")
[docs] processParameters = QuoteProcessParameters(title="QuoteProcessParameters")
[docs]class StepQuotationList(ExtendedSequenceSchema):
[docs] description = "Detailed child processes and prices part of the complete quote."
[docs] step = StepQuotation(description="Quote of a workflow step process.")
[docs]class Quotation(StepQuotation):
[docs] steps = StepQuotationList(missing=drop)
[docs]class QuoteStepReferenceList(ExtendedSequenceSchema):
[docs] description = "Summary of child process quote references part of the complete quote."
[docs] ref = ReferenceURL()
[docs]class QuoteSummary(PartialQuoteSchema):
[docs] steps = QuoteStepReferenceList()
[docs] total = Price(description="Total of the quote including step processes if applicable.")
[docs]class QuoteSchema(Quotation):
[docs] total = Price(description="Total of the quote including step processes if applicable.")
[docs]class QuotationList(ExtendedSequenceSchema):
[docs] quote = UUID(description="Quote ID.")
[docs]class QuotationListSchema(ExtendedMappingSchema):
[docs] quotations = QuotationList()
[docs]class BillSchema(ExtendedMappingSchema):
[docs] id = UUID(description="Bill ID.")
[docs] quoteID = UUID(description="Original quote ID that produced this bill.", missing=drop)
[docs] title = ExtendedSchemaNode(String(), description="Name of the bill.")
[docs] description = ExtendedSchemaNode(String(), missing=drop)
[docs] price = Price(description="Price associated to the bill.")
[docs] currency = ExtendedSchemaNode(String(), description="Currency code in ISO-4217 format.")
[docs] created = ExtendedSchemaNode(DateTime(), description="Creation date and time of the bill in ISO-8601 format.")
[docs] userID = ExtendedSchemaNode(Integer(), description="User id that requested the quote.")
[docs]class BillList(ExtendedSequenceSchema):
[docs] bill = UUID(description="Bill ID.")
[docs]class BillListSchema(ExtendedMappingSchema):
[docs] bills = BillList()
[docs]class SupportedValues(ExtendedMappingSchema): pass
[docs]class DefaultValues(ExtendedMappingSchema): pass
[docs]class CWLClass(ExtendedSchemaNode): # in this case it is ok to use 'name' because target fields receiving it will # never be able to be named 'class' because of Python reserved keyword
[docs] name = "class"
[docs] title = "Class"
[docs] schema_type = String
[docs] example = "CommandLineTool"
[docs] validator = OneOf(["CommandLineTool", "ExpressionTool", "Workflow"])
[docs] description = ( "CWL class specification. This is used to differentiate between single Application Package (AP)"
"definitions and Workflow that chains multiple packages." )
[docs]class RequirementClass(ExtendedSchemaNode): # in this case it is ok to use 'name' because target fields receiving it will # never be able to be named 'class' because of Python reserved keyword
[docs] name = "class"
[docs] title = "RequirementClass"
[docs] schema_type = String
[docs] description = "CWL requirement class specification."
[docs]class DockerRequirementSpecification(PermissiveMappingSchema):
[docs] dockerPull = ExtendedSchemaNode( String(), example="docker-registry.host.com/namespace/image:1.2.3", title="Docker pull reference", description="Reference package that will be retrieved and executed by CWL."
)
[docs]class DockerRequirementMap(ExtendedMappingSchema):
[docs] DockerRequirement = DockerRequirementSpecification( name=CWL_REQUIREMENT_APP_DOCKER, title=CWL_REQUIREMENT_APP_DOCKER
)
[docs]class DockerRequirementClass(DockerRequirementSpecification):
[docs] _class = RequirementClass(example=CWL_REQUIREMENT_APP_DOCKER, validator=OneOf([CWL_REQUIREMENT_APP_DOCKER]))
[docs]class DockerGpuRequirementSpecification(DockerRequirementSpecification):
[docs] description = ( "Docker requirement with GPU-enabled support (https://github.com/NVIDIA/nvidia-docker). "
"The instance must have the NVIDIA toolkit installed to use this feature." )
[docs]class DockerGpuRequirementMap(ExtendedMappingSchema):
[docs] req = DockerGpuRequirementSpecification(name=CWL_REQUIREMENT_APP_DOCKER_GPU)
[docs]class DockerGpuRequirementClass(DockerGpuRequirementSpecification):
[docs] title = CWL_REQUIREMENT_APP_DOCKER_GPU
[docs] _class = RequirementClass(example=CWL_REQUIREMENT_APP_DOCKER_GPU, validator=OneOf([CWL_REQUIREMENT_APP_DOCKER_GPU]))
[docs]class DirectoryListing(PermissiveMappingSchema):
[docs] entry = ExtendedSchemaNode(String(), missing=drop)
[docs]class InitialWorkDirListing(ExtendedSequenceSchema):
[docs] listing = DirectoryListing()
[docs]class InitialWorkDirRequirementSpecification(PermissiveMappingSchema):
[docs] listing = InitialWorkDirListing()
[docs]class InitialWorkDirRequirementMap(ExtendedMappingSchema):
[docs] req = InitialWorkDirRequirementSpecification(name=CWL_REQUIREMENT_INIT_WORKDIR)
[docs]class InitialWorkDirRequirementClass(InitialWorkDirRequirementSpecification):
[docs] _class = RequirementClass(example=CWL_REQUIREMENT_INIT_WORKDIR, validator=OneOf([CWL_REQUIREMENT_INIT_WORKDIR]))
[docs]class BuiltinRequirementSpecification(PermissiveMappingSchema):
[docs] title = CWL_REQUIREMENT_APP_BUILTIN
[docs] description = ( "Hint indicating that the Application Package corresponds to a builtin process of "
"this instance. (note: can only be an 'hint' as it is unofficial CWL specification)." )
[docs] process = AnyIdentifier(description="Builtin process identifier.")
[docs]class BuiltinRequirementMap(ExtendedMappingSchema):
[docs] req = BuiltinRequirementSpecification(name=CWL_REQUIREMENT_APP_BUILTIN)
[docs]class BuiltinRequirementClass(BuiltinRequirementSpecification):
[docs] _class = RequirementClass(example=CWL_REQUIREMENT_APP_BUILTIN, validator=OneOf([CWL_REQUIREMENT_APP_BUILTIN]))
[docs]class ESGF_CWT_RequirementSpecification(PermissiveMappingSchema): # noqa: N802
[docs] title = CWL_REQUIREMENT_APP_ESGF_CWT
[docs] description = ( "Hint indicating that the Application Package corresponds to an ESGF-CWT provider process"
"that should be remotely executed and monitored by this instance. " "(note: can only be an 'hint' as it is unofficial CWL specification)." )
[docs] process = AnyIdentifier(description="Process identifier of the remote ESGF-CWT provider.")
[docs] provider = URL(description="ESGF-CWT provider endpoint.")
[docs]class ESGF_CWT_RequirementMap(ExtendedMappingSchema): # noqa: N802
[docs] req = ESGF_CWT_RequirementSpecification(name=CWL_REQUIREMENT_APP_ESGF_CWT)
[docs]class ESGF_CWT_RequirementClass(ESGF_CWT_RequirementSpecification): # noqa: N802
[docs] _class = RequirementClass(example=CWL_REQUIREMENT_APP_ESGF_CWT, validator=OneOf([CWL_REQUIREMENT_APP_ESGF_CWT]))
[docs]class WPS1RequirementSpecification(PermissiveMappingSchema):
[docs] title = CWL_REQUIREMENT_APP_WPS1
[docs] description = ( "Hint indicating that the Application Package corresponds to a WPS-1 provider process"
"that should be remotely executed and monitored by this instance. " "(note: can only be an 'hint' as it is unofficial CWL specification)." )
[docs] process = AnyIdentifier(description="Process identifier of the remote WPS provider.")
[docs] provider = URL(description="WPS provider endpoint.")
[docs]class WPS1RequirementMap(ExtendedMappingSchema):
[docs] req = WPS1RequirementSpecification(name=CWL_REQUIREMENT_APP_WPS1)
[docs]class WPS1RequirementClass(WPS1RequirementSpecification):
[docs] _class = RequirementClass(example=CWL_REQUIREMENT_APP_WPS1, validator=OneOf([CWL_REQUIREMENT_APP_WPS1]))
[docs]class UnknownRequirementClass(PermissiveMappingSchema):
[docs] _class = RequirementClass(example="UnknownRequirement")
[docs]class CWLRequirementsMap(AnyOfKeywordSchema):
[docs] _any_of = [ DockerRequirementMap(missing=drop), DockerGpuRequirementMap(missing=drop), InitialWorkDirRequirementMap(missing=drop), PermissiveMappingSchema(missing=drop),
]
[docs]class CWLRequirementsItem(OneOfKeywordSchema):
[docs] _one_of = [ DockerRequirementClass(missing=drop), DockerGpuRequirementClass(missing=drop), InitialWorkDirRequirementClass(missing=drop), UnknownRequirementClass(missing=drop), # allows anything, must be last
]
[docs]class CWLRequirementsList(ExtendedSequenceSchema):
[docs] requirement = CWLRequirementsItem()
[docs]class CWLRequirements(OneOfKeywordSchema):
[docs] _one_of = [ CWLRequirementsMap(), CWLRequirementsList(),
]
[docs]class CWLHintsMap(AnyOfKeywordSchema, PermissiveMappingSchema):
[docs] _any_of = [ BuiltinRequirementMap(missing=drop), DockerRequirementMap(missing=drop), DockerGpuRequirementMap(missing=drop), InitialWorkDirRequirementMap(missing=drop), ESGF_CWT_RequirementMap(missing=drop), WPS1RequirementMap(missing=drop),
]
[docs]class CWLHintsItem(OneOfKeywordSchema, PermissiveMappingSchema): # validators of individual requirements define which one applies # in case of ambiguity, 'discriminator' distinguish between them using their 'example' values in 'class' field
[docs] discriminator = "class"
[docs] _one_of = [ BuiltinRequirementClass(missing=drop), DockerRequirementClass(missing=drop), DockerGpuRequirementClass(missing=drop), InitialWorkDirRequirementClass(missing=drop), ESGF_CWT_RequirementClass(missing=drop), WPS1RequirementClass(missing=drop), UnknownRequirementClass(missing=drop), # allows anything, must be last
]
[docs]class CWLHintsList(ExtendedSequenceSchema):
[docs] hint = CWLHintsItem()
[docs]class CWLHints(OneOfKeywordSchema):
[docs] _one_of = [ CWLHintsMap(), CWLHintsList(),
]
[docs]class CWLArguments(ExtendedSequenceSchema):
[docs] argument = ExtendedSchemaNode(String())
[docs]class CWLTypeString(ExtendedSchemaNode):
[docs] schema_type = String
[docs] description = "Field type definition."
[docs] example = "float"
[docs] validator = OneOf(PACKAGE_TYPE_POSSIBLE_VALUES)
[docs]class CWLTypeSymbolValues(OneOfKeywordSchema):
[docs] _one_of = [ ExtendedSchemaNode(Float()), ExtendedSchemaNode(Integer()), ExtendedSchemaNode(String()),
]
[docs]class CWLTypeSymbols(ExtendedSequenceSchema):
[docs] symbol = CWLTypeSymbolValues()
[docs]class CWLTypeArray(ExtendedMappingSchema):
[docs] type = ExtendedSchemaNode(String(), example=PACKAGE_ARRAY_BASE, validator=OneOf([PACKAGE_ARRAY_BASE]))
[docs] items = CWLTypeString(title="CWLTypeArrayItems", validator=OneOf(PACKAGE_ARRAY_ITEMS))
[docs]class CWLTypeEnum(ExtendedMappingSchema):
[docs] type = ExtendedSchemaNode(String(), example=PACKAGE_ENUM_BASE, validator=OneOf(PACKAGE_CUSTOM_TYPES))
[docs] symbols = CWLTypeSymbols(summary="Allowed values composing the enum.")
[docs]class CWLTypeBase(OneOfKeywordSchema):
[docs] _one_of = [ CWLTypeString(summary="CWL type as literal value."), CWLTypeArray(summary="CWL type as list of items."), CWLTypeEnum(summary="CWL type as enum of values."),
]
[docs]class CWLTypeList(ExtendedSequenceSchema):
[docs] type = CWLTypeBase()
[docs]class CWLType(OneOfKeywordSchema):
[docs] title = "CWL Type"
[docs] _one_of = [ CWLTypeBase(summary="CWL type definition."), CWLTypeList(summary="Combination of allowed CWL types."),
]
[docs]class AnyLiteralList(ExtendedSequenceSchema):
[docs] default = AnyLiteralType()
[docs]class CWLDefault(OneOfKeywordSchema):
[docs] _one_of = [ AnyLiteralType(), AnyLiteralList(),
]
[docs]class CWLInputObject(PermissiveMappingSchema):
[docs] type = CWLType()
[docs] default = CWLDefault(missing=drop, description="Default value of input if not provided for task execution.")
[docs] inputBinding = PermissiveMappingSchema(missing=drop, title="Input Binding", description="Defines how to specify the input for the command.")
[docs]class CWLTypeStringList(ExtendedSequenceSchema):
[docs] description = "List of allowed direct CWL type specifications as strings."
[docs] type = CWLType()
[docs]class CWLInputType(OneOfKeywordSchema):
[docs] description = "CWL type definition of the input."
[docs] _one_of = [ CWLTypeString(summary="Direct CWL type string specification."), CWLTypeStringList(summary="List of allowed CWL type strings."), CWLInputObject(summary="CWL type definition with parameters."),
]
[docs]class CWLInputMap(PermissiveMappingSchema):
[docs] input_id = CWLInputType(variable="{input-id}", title="CWLInputDefinition", description=IO_INFO_IDS.format(first="CWL", second="WPS", what="input") + " (Note: '{input-id}' is a variable corresponding for each identifier)")
[docs]class CWLInputItem(CWLInputObject):
[docs] id = AnyIdentifier(description=IO_INFO_IDS.format(first="CWL", second="WPS", what="input"))
[docs]class CWLInputList(ExtendedSequenceSchema):
[docs] input = CWLInputItem(title="Input", description="Input specification. " + CWL_DOC_MESSAGE)
[docs]class CWLInputsDefinition(OneOfKeywordSchema):
[docs] _one_of = [ CWLInputList(description="Package inputs defined as items."), CWLInputMap(description="Package inputs defined as mapping."),
]
[docs]class OutputBinding(PermissiveMappingSchema):
[docs] glob = ExtendedSchemaNode(String(), missing=drop, description="Glob pattern the will find the output on disk or mounted docker volume.")
[docs]class CWLOutputObject(PermissiveMappingSchema):
[docs] type = CWLType()
# 'outputBinding' should usually be there most of the time (if not always) to retrieve file, # but can technically be omitted in some very specific use-cases such as output literal or output is std logs
[docs] outputBinding = OutputBinding( missing=drop, description="Defines how to retrieve the output result from the command."
)
[docs]class CWLOutputType(OneOfKeywordSchema):
[docs] _one_of = [ CWLTypeString(summary="Direct CWL type string specification."), CWLTypeStringList(summary="List of allowed CWL type strings."), CWLOutputObject(summary="CWL type definition with parameters."),
]
[docs]class CWLOutputMap(ExtendedMappingSchema):
[docs] output_id = CWLOutputType(variable="{output-id}", title="CWLOutputDefinition", description=IO_INFO_IDS.format(first="CWL", second="WPS", what="output") + " (Note: '{output-id}' is a variable corresponding for each identifier)")
[docs]class CWLOutputItem(CWLOutputObject):
[docs] id = AnyIdentifier(description=IO_INFO_IDS.format(first="CWL", second="WPS", what="output"))
[docs]class CWLOutputList(ExtendedSequenceSchema):
[docs] input = CWLOutputItem(description="Output specification. " + CWL_DOC_MESSAGE)
[docs]class CWLOutputsDefinition(OneOfKeywordSchema):
[docs] _one_of = [ CWLOutputList(description="Package outputs defined as items."), CWLOutputMap(description="Package outputs defined as mapping."),
]
[docs]class CWLCommandParts(ExtendedSequenceSchema):
[docs] cmd = ExtendedSchemaNode(String())
[docs]class CWLCommand(OneOfKeywordSchema):
[docs] _one_of = [ ExtendedSchemaNode(String(), title="String command."), CWLCommandParts(title="Command Parts")
]
[docs]class CWLVersion(Version):
[docs] description = "CWL version of the described application package."
[docs] example = CWL_VERSION
[docs] validator = SemanticVersion(v_prefix=True, rc_suffix=False)
[docs]class CWL(PermissiveMappingSchema):
[docs] cwlVersion = CWLVersion()
[docs] _class = CWLClass()
[docs] requirements = CWLRequirements(description="Explicit requirement to execute the application package.", missing=drop)
[docs] hints = CWLHints(description="Non-failing additional hints that can help resolve extra requirements.", missing=drop)
[docs] baseCommand = CWLCommand(description="Command called in the docker image or on shell according to requirements " "and hints specifications. Can be omitted if already defined in the " "docker image.", missing=drop)
[docs] arguments = CWLArguments(description="Base arguments passed to the command.", missing=drop)
[docs] inputs = CWLInputsDefinition(description="All inputs available to the Application Package.")
[docs] outputs = CWLOutputsDefinition(description="All outputs produced by the Application Package.")
[docs]class Unit(ExtendedMappingSchema):
[docs] unit = CWL(description="Execution unit definition as CWL package specification. " + CWL_DOC_MESSAGE)
[docs]class UndeploymentResult(ExtendedMappingSchema):
[docs] id = AnyIdentifier()
[docs]class DeploymentResult(ExtendedMappingSchema):
[docs] processSummary = ProcessSummary()
[docs]class ProviderSummaryList(ExtendedSequenceSchema):
[docs] provider_service = ProviderSummarySchema()
[docs]class ProviderNamesList(ExtendedSequenceSchema):
[docs] provider_name = ProviderNameSchema()
[docs]class ProviderListing(OneOfKeywordSchema):
[docs] _one_of = [ ProviderSummaryList(description="Listing of provider summary details retrieved from remote service."), ProviderNamesList(description="Listing of provider names, possibly unvalidated from remote service.", missing=drop), # in case of empty list, both schema are valid, drop this one to resolve
]
[docs]class ProvidersBodySchema(ExtendedMappingSchema):
[docs] checked = ExtendedSchemaNode( Boolean(), description="Indicates if the listed providers have been validated and are accessible from registered URL. "
"In such case, provider metadata was partially retrieved from remote services and is accessible. " "Otherwise, only local metadata is provided and service availability is not guaranteed." )
[docs] providers = ProviderListing(description="Providers listing according to specified query parameters.")
[docs]class ProviderProcessesSchema(ExtendedSequenceSchema):
[docs] provider_process = ProcessSummary()
[docs]class JobOutputReference(ExtendedMappingSchema):
[docs] href = ReferenceURL(description="Output file reference.")
# either with 'type', 'format.mediaType' or 'format.mimeType' according requested 'schema=OGC/OLD' # if 'schema=strict' as well, either 'type' or 'format' could be dropped altogether
[docs] type = MediaType(missing=drop, description="IANA Content-Type of the file reference.")
[docs] format = FormatSelection(missing=drop)
[docs]class JobOutputValue(OneOfKeywordSchema):
[docs] _one_of = [ JobOutputReference(tilte="JobOutputReference"), AnyLiteralDataType(title="JobOutputLiteral")
]
[docs]class JobOutput(AllOfKeywordSchema):
[docs] _all_of = [ OutputIdentifierType(), JobOutputValue(),
]
[docs]class JobOutputMap(ExtendedMappingSchema):
[docs] output_id = JobOutputValue( variable="{output-id}", title="JobOutputData", description=( "Output data as literal value or file reference. "
"(Note: '{output-id}' is a variable corresponding for each identifier)" ) )
[docs]class JobOutputList(ExtendedSequenceSchema):
[docs] title = "JobOutputList"
[docs] output = JobOutput(description="Job output result with specific keyword according to represented format.")
[docs]class JobOutputs(OneOfKeywordSchema):
[docs] _one_of = [ JobOutputMap(), JobOutputList(),
] # implement only literal parts from following schemas: # https://raw.githubusercontent.com/opengeospatial/ogcapi-processes/master/core/openapi/schemas/inlineOrRefData.yaml # https://raw.githubusercontent.com/opengeospatial/ogcapi-processes/master/core/openapi/schemas/qualifiedInputValue.yaml # # Other parts are implemented separately with: # - 'ValueFormatted' (qualifiedInputValue) # - 'ResultReference' (link)
[docs]class ResultLiteral(AnyLiteralValueType): # value = <AnyLiteralValueType> pass
[docs]class ResultLiteralList(ExtendedSequenceSchema):
[docs] result = ResultLiteral()
[docs]class ValueFormatted(ExtendedMappingSchema):
[docs] value = ExtendedSchemaNode( String(), example="<xml><data>test</data></xml>", description="Formatted content value of the result."
)
[docs] format = ResultFormat()
[docs]class ValueFormattedList(ExtendedSequenceSchema):
[docs] result = ValueFormatted()
[docs]class ResultReference(ExtendedMappingSchema):
[docs] href = ReferenceURL(description="Result file reference.")
[docs] type = MediaType(description="IANA Content-Type of the file reference.")
[docs] format = ResultFormat()
[docs]class ResultReferenceList(ExtendedSequenceSchema):
[docs] result = ResultReference()
[docs]class ResultData(OneOfKeywordSchema):
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/result.yaml"
[docs] _one_of = [ # must place formatted value first since both value/format fields are simultaneously required # other classes require only one of the two, and therefore are more permissive during schema validation ValueFormatted(description="Result formatted content value."), ValueFormattedList(description="Result formatted content of multiple values."), ResultReference(description="Result reference location."), ResultReferenceList(description="Result locations for multiple references."), ResultLiteral(description="Result literal value."), ResultLiteralList(description="Result list of literal values."),
]
[docs]class Result(ExtendedMappingSchema): """ Result outputs obtained from a successful process job execution. """
[docs] example_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/examples/json/Result.json"
[docs] output_id = ResultData( variable="{output-id}", title="ResultData", description=( "Resulting value of the output that conforms to 'OGC API - Processes' standard. "
"(Note: '{output-id}' is a variable corresponding for each output identifier of the process)" ) )
[docs]class JobInputsBody(ExecuteInputOutputs):
[docs]class JobOutputsBody(ExtendedMappingSchema):
[docs] outputs = JobOutputs()
[docs]class JobExceptionPlain(ExtendedSchemaNode):
[docs] schema_type = String
[docs] description = "Generic exception description corresponding to any error message."
[docs]class JobExceptionDetailed(ExtendedMappingSchema):
[docs] description = "Fields correspond exactly to 'owslib.wps.WPSException' represented as dictionary."
[docs] Code = ExtendedSchemaNode(String())
[docs] Locator = ExtendedSchemaNode(String(), default=None)
[docs] Text = ExtendedSchemaNode(String())
[docs]class JobException(OneOfKeywordSchema):
[docs] _one_of = [ JobExceptionDetailed(), JobExceptionPlain()
]
[docs]class JobExceptionsSchema(ExtendedSequenceSchema):
[docs] exceptions = JobException()
[docs]class JobLogsSchema(ExtendedSequenceSchema):
[docs] log = ExtendedSchemaNode(String())
[docs]class ApplicationStatisticsSchema(ExtendedMappingSchema):
[docs] mem = ExtendedSchemaNode(String(), name="usedMemory", example="10 MiB")
[docs] mem_bytes = ExtendedSchemaNode(Integer(), name="usedMemoryBytes", example=10485760)
[docs]class ProcessStatisticsSchema(ExtendedMappingSchema):
[docs] rss = ExtendedSchemaNode(String(), name="rss", example="140 MiB")
[docs] rss_bytes = ExtendedSchemaNode(Integer(), name="rssBytes", example=146800640)
[docs] uss = ExtendedSchemaNode(String(), name="uss", example="80 MiB")
[docs] uss_bytes = ExtendedSchemaNode(Integer(), name="ussBytes", example=83886080)
[docs] vms = ExtendedSchemaNode(String(), name="vms", example="1.4 GiB")
[docs] vms_bytes = ExtendedSchemaNode(Integer(), name="vmsBytes", example=1503238554)
[docs] used_threads = ExtendedSchemaNode(Integer(), name="usedThreads", example=10)
[docs] used_cpu = ExtendedSchemaNode(Integer(), name="usedCPU", example=2)
[docs] used_handles = ExtendedSchemaNode(Integer(), name="usedHandles", example=0)
[docs] mem = ExtendedSchemaNode(String(), name="usedMemory", example="10 MiB", description="RSS memory employed by the job execution omitting worker memory.")
[docs] mem_bytes = ExtendedSchemaNode(Integer(), name="usedMemoryBytes", example=10485760, description="RSS memory employed by the job execution omitting worker memory.")
[docs] total_size = ExtendedSchemaNode(String(), name="totalSize", example="10 MiB", description="Total size to store job output files.")
[docs] total_size_bytes = ExtendedSchemaNode(Integer(), name="totalSizeBytes", example=10485760, description="Total size to store job output files.")
[docs]class OutputStatisticsSchema(ExtendedMappingSchema):
[docs] size = ExtendedSchemaNode(String(), name="size", example="5 MiB")
[docs] size_bytes = ExtendedSchemaNode(Integer(), name="sizeBytes", example=5242880)
[docs]class OutputStatisticsMap(ExtendedMappingSchema):
[docs] output = OutputStatisticsSchema(variable="{output-id}", description="Spaced used by this output file.")
[docs]class JobStatisticsSchema(ExtendedMappingSchema):
[docs] application = ApplicationStatisticsSchema(missing=drop)
[docs] process = ProcessStatisticsSchema(missing=drop)
[docs] outputs = OutputStatisticsMap(missing=drop)
[docs]class FrontpageParameterSchema(ExtendedMappingSchema):
[docs] name = ExtendedSchemaNode(String(), example="api")
[docs] enabled = ExtendedSchemaNode(Boolean(), example=True)
[docs] url = URL(description="Referenced parameter endpoint.", example="https://weaver-host", missing=drop)
[docs] doc = ExtendedSchemaNode(String(), example="https://weaver-host/api", missing=drop)
[docs]class FrontpageParameters(ExtendedSequenceSchema):
[docs] parameter = FrontpageParameterSchema()
[docs]class FrontpageSchema(ExtendedMappingSchema):
[docs] message = ExtendedSchemaNode(String(), default="Weaver Information", example="Weaver Information")
[docs] configuration = ExtendedSchemaNode(String(), default="default", example="default")
[docs] parameters = FrontpageParameters()
[docs]class SwaggerJSONSpecSchema(ExtendedMappingSchema): pass
[docs]class SwaggerUISpecSchema(ExtendedMappingSchema): pass
[docs]class VersionsSpecSchema(ExtendedMappingSchema):
[docs] name = ExtendedSchemaNode(String(), description="Identification name of the current item.", example="weaver")
[docs] type = ExtendedSchemaNode(String(), description="Identification type of the current item.", example="api")
[docs] version = Version(description="Version of the current item.", example="0.1.0")
[docs]class VersionsList(ExtendedSequenceSchema):
[docs] version = VersionsSpecSchema()
[docs]class VersionsSchema(ExtendedMappingSchema):
[docs] versions = VersionsList()
[docs]class ConformanceList(ExtendedSequenceSchema):
[docs] conformance = URL(description="Conformance specification link.", example="http://www.opengis.net/spec/WPS/2.0/req/service/binding/rest-json/core")
[docs]class ConformanceSchema(ExtendedMappingSchema):
[docs] conformsTo = ConformanceList()
################################################################# # Local Processes schemas #################################################################
[docs]class PackageBody(ExtendedMappingSchema): pass
[docs]class ExecutionUnit(OneOfKeywordSchema):
[docs] _one_of = [ Reference(name="Reference", title="Reference", description="Execution Unit reference."), Unit(name="Unit", title="Unit", description="Execution Unit definition."),
]
[docs]class ExecutionUnitList(ExtendedSequenceSchema):
[docs] unit = ExecutionUnit( name="ExecutionUnit", title="ExecutionUnit", description="Definition of the Application Package to execute."
)
[docs]class DeployProcessOffering(ProcessControl):
[docs] process = ProcessDeployment(description="Process definition nested under process field for backward compatibility.")
[docs] processVersion = Version(title="processVersion", missing=drop)
[docs]class DeployProcessDescription(ProcessDeployment, ProcessControl):
[docs] schema_ref = f"{OGC_API_SCHEMA_URL}/{OGC_API_SCHEMA_VERSION}/core/openapi/schemas/process.yaml"
[docs] description = "Process description fields directly provided."
[docs]class ProcessDescriptionChoiceType(OneOfKeywordSchema):
[docs] _one_of = [ Reference(), DeployProcessOffering(), DeployProcessDescription()
]
[docs]class Deploy(ExtendedMappingSchema):
[docs] processDescription = ProcessDescriptionChoiceType()
[docs] executionUnit = ExecutionUnitList()
[docs] immediateDeployment = ExtendedSchemaNode(Boolean(), missing=drop, default=True)
[docs] deploymentProfileName = URL(missing=drop)
[docs] owsContext = OWSContext(missing=drop)
[docs]class DeployHeaders(RequestHeaders):
[docs] x_auth_docker = XAuthDockerHeader()
[docs]class PostProcessesEndpoint(ExtendedMappingSchema):
[docs] header = DeployHeaders(description="Headers employed for process deployment.")
[docs] body = Deploy(title="Deploy")
[docs]class WpsOutputContextHeader(ExtendedSchemaNode): # ok to use 'name' in this case because target 'key' in the mapping must # be that specific value but cannot have a field named with this format
[docs] name = "X-WPS-Output-Context"
[docs] description = ( "Contextual location where to store WPS output results from job execution. ", "When provided, value must be a directory or sub-directories slug. ", "Resulting contextual location will be relative to server WPS outputs when no context is provided.",
)
[docs] schema_type = String
[docs] missing = drop
[docs] example = "my-directory/sub-project"
[docs] default = None
[docs]class ExecuteHeaders(RequestHeaders):
[docs] description = "Request headers supported for job execution."
[docs] x_wps_output_context = WpsOutputContextHeader()
[docs]class PostProcessJobsEndpoint(ProcessPath):
[docs] header = ExecuteHeaders()
[docs] body = Execute()
[docs]class GetJobsQueries(ExtendedMappingSchema): # note: # This schema is also used to generate any missing defaults during filter parameter handling. # Items with default value are added if omitted, except 'default=null' which are removed after handling by alias.
[docs] detail = ExtendedSchemaNode(QueryBoolean(), default=False, example=True, missing=drop, description="Provide job details instead of IDs.")
[docs] groups = ExtendedSchemaNode(String(), description="Comma-separated list of grouping fields with which to list jobs.", default=False, example="process,service", missing=drop)
[docs] page = ExtendedSchemaNode(Integer(allow_string=True), missing=0, default=0, validator=Range(min=0))
[docs] limit = ExtendedSchemaNode(Integer(allow_string=True), missing=10, default=10, validator=Range(min=1, max=10000))
[docs] min_duration = ExtendedSchemaNode( Integer(allow_string=True), name="minDuration", missing=drop, default=null, validator=Range(min=0), description="Minimal duration (seconds) between started time and current/finished time of jobs to find.")
[docs] max_duration = ExtendedSchemaNode( Integer(allow_string=True), name="maxDuration", missing=drop, default=null, validator=Range(min=0), description="Maximum duration (seconds) between started time and current/finished time of jobs to find.")
[docs] datetime = DateTimeInterval(missing=drop, default=None)
[docs] status = JobStatusEnum(missing=drop, default=None)
[docs] processID = ProcessIdentifier(missing=drop, default=null, description="Alias to 'process' for OGC-API compliance.")
[docs] process = ProcessIdentifier(missing=drop, default=None, description="Identifier of the process to filter search.")
[docs] service = AnyIdentifier(missing=drop, default=null, description="Alias to 'provider' for backward compatibility.")
[docs] provider = AnyIdentifier(missing=drop, default=None, description="Identifier of service provider to filter search.")
[docs] type = JobTypeEnum(missing=drop, default=null, description="Filter jobs only to matching type (note: 'service' and 'provider' are aliases).")
[docs] sort = JobSortEnum(missing=drop)
[docs] access = JobAccess(missing=drop, default=None)
[docs] notification_email = ExtendedSchemaNode(String(), missing=drop, validator=Email())
[docs] tags = ExtendedSchemaNode(String(), missing=drop, default=None, description="Comma-separated values of tags assigned to jobs")
[docs]class GetJobsRequest(ExtendedMappingSchema):
[docs] header = RequestHeaders()
[docs] querystring = GetJobsQueries()
[docs]class GetJobsEndpoint(GetJobsRequest): pass
[docs]class GetProcessJobsEndpoint(GetJobsRequest, ProcessPath): pass
[docs]class GetProviderJobsEndpoint(GetJobsRequest, ProviderPath, ProcessPath): pass
[docs]class JobIdentifierList(ExtendedSequenceSchema):
[docs] job_id = UUID(description="ID of a job to dismiss. Identifiers not matching any known job are ignored.")
[docs]class DeleteJobsBodySchema(ExtendedMappingSchema):
[docs] jobs = JobIdentifierList()
[docs]class DeleteJobsEndpoint(ExtendedMappingSchema):
[docs] header = RequestHeaders()
[docs] body = DeleteJobsBodySchema()
[docs]class DeleteProcessJobsEndpoint(DeleteJobsEndpoint, ProcessPath): pass
[docs]class DeleteProviderJobsEndpoint(DeleteJobsEndpoint, ProviderPath, ProcessPath): pass
[docs]class GetProcessJobEndpoint(ProcessPath):
[docs] header = RequestHeaders()
[docs]class DeleteProcessJobEndpoint(ProcessPath):
[docs] header = RequestHeaders()
[docs]class BillsEndpoint(ExtendedMappingSchema):
[docs] header = RequestHeaders()
[docs]class BillEndpoint(BillPath):
[docs] header = RequestHeaders()
[docs]class ProcessQuotesEndpoint(ProcessPath):
[docs] header = RequestHeaders()
[docs]class ProcessQuoteEndpoint(ProcessPath, QuotePath):
[docs] header = RequestHeaders()
[docs]class GetQuotesQueries(ExtendedMappingSchema):
[docs] page = ExtendedSchemaNode(Integer(), missing=drop, default=0)
[docs] limit = ExtendedSchemaNode(Integer(), missing=10, default=10, validator=Range(min=1, max=10000))
[docs] process = AnyIdentifier(missing=None)
[docs] sort = QuoteSortEnum(missing=drop)
[docs]class QuotesEndpoint(ExtendedMappingSchema):
[docs] header = RequestHeaders()
[docs] querystring = GetQuotesQueries()
[docs]class QuoteEndpoint(QuotePath):
[docs] header = RequestHeaders()
[docs]class PostProcessQuote(ProcessPath, QuotePath):
[docs] header = RequestHeaders()
[docs] body = NoContent()
[docs]class PostQuote(QuotePath):
[docs] header = RequestHeaders()
[docs] body = NoContent()
[docs]class QuoteProcessParametersSchema(ExecuteInputOutputs): pass
[docs]class PostProcessQuoteRequestEndpoint(ProcessPath, QuotePath):
[docs] header = RequestHeaders()
[docs] body = QuoteProcessParametersSchema()
# ################################################################ # Provider Processes schemas # ################################################################
[docs]class ProvidersQuerySchema(ExtendedMappingSchema):
[docs] detail = ExtendedSchemaNode( QueryBoolean(), example=True, default=True, missing=drop, description="Return summary details about each provider, or simply their IDs."
)
[docs] check = ExtendedSchemaNode( QueryBoolean(), example=True, default=True, missing=drop, description="List only reachable providers, dropping unresponsive ones that cannot be checked for listing. "
"Otherwise, all registered providers are listed regardless of their availability. When requesting " "details, less metadata will be provided since it will not be fetched from remote services." )
[docs] ignore = ExtendedSchemaNode( QueryBoolean(), example=True, default=True, missing=drop, description="When listing providers with check of reachable remote service definitions, unresponsive response "
"or unprocessable contents will be silently ignored and dropped from full listing in the response. " "Disabling this option will raise an error immediately instead of ignoring invalid services." )
[docs]class GetProviders(ExtendedMappingSchema):
[docs] querystring = ProvidersQuerySchema()
[docs] header = RequestHeaders()
[docs]class PostProvider(ExtendedMappingSchema):
[docs] header = RequestHeaders()
[docs] body = CreateProviderRequestBody()
[docs]class ProcessDetailQuery(ExtendedMappingSchema):
[docs] detail = ExtendedSchemaNode( QueryBoolean(), example=True, default=True, missing=drop, description="Return summary details about each process, or simply their IDs."
)
[docs]class ProviderProcessesQuery(ProcessPagingQuery, ProcessDetailQuery): pass
[docs]class ProviderProcessesEndpoint(ProviderPath):
[docs] header = RequestHeaders()
[docs] querystring = ProviderProcessesQuery()
[docs]class GetProviderProcess(ExtendedMappingSchema):
[docs] header = RequestHeaders()
[docs]class PostProviderProcessJobRequest(ExtendedMappingSchema): """ Launching a new process request definition. """
[docs] header = ExecuteHeaders()
[docs] querystring = LaunchJobQuerystring()
[docs] body = Execute()
# ################################################################ # Responses schemas # ################################################################
[docs]class ErrorDetail(ExtendedMappingSchema):
[docs] code = ExtendedSchemaNode(Integer(), description="HTTP status code.", example=400)
[docs] status = ExtendedSchemaNode(String(), description="HTTP status detail.", example="400 Bad Request")
[docs]class OWSErrorCode(ExtendedSchemaNode):
[docs] schema_type = String
[docs] example = "InvalidParameterValue"
[docs] description = "OWS error code."
[docs]class OWSExceptionResponse(ExtendedMappingSchema): """ Error content in XML format. """
[docs] description = "OWS formatted exception."
[docs] code = OWSErrorCode(example="NoSuchProcess")
[docs] locator = ExtendedSchemaNode(String(), example="identifier", description="Indication of the element that caused the error.")
[docs] message = ExtendedSchemaNode(String(), example="Invalid process ID.", description="Specific description of the error.")
[docs]class ErrorJsonResponseBodySchema(ExtendedMappingSchema):
[docs] code = OWSErrorCode()
[docs] description = ExtendedSchemaNode(String(), description="Detail about the cause of error.")
[docs] error = ErrorDetail(missing=drop)
[docs] exception = OWSExceptionResponse(missing=drop)
[docs]class BadRequestResponseSchema(ExtendedMappingSchema):
[docs] description = "Incorrectly formed request contents."
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class UnprocessableEntityResponseSchema(ExtendedMappingSchema):
[docs] description = "Wrong format of given parameters."
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class ForbiddenProcessAccessResponseSchema(ExtendedMappingSchema):
[docs] description = "Referenced process is not accessible."
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class ForbiddenProviderAccessResponseSchema(ExtendedMappingSchema):
[docs] description = "Referenced provider is not accessible."
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class ForbiddenProviderLocalResponseSchema(ExtendedMappingSchema):
[docs] description = ( "Provider operation is not allowed on local-only Weaver instance. "
f"Applies only when application configuration is not within: {WEAVER_CONFIG_REMOTE_LIST}" )
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class InternalServerErrorResponseSchema(ExtendedMappingSchema):
[docs] description = "Unhandled internal server error."
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class OkGetFrontpageResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = FrontpageSchema()
[docs]class OkGetSwaggerJSONResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = SwaggerJSONSpecSchema(description="OpenAPI JSON schema of Weaver API.")
[docs]class OkGetSwaggerUIResponse(ExtendedMappingSchema):
[docs] header = HtmlHeader()
[docs] body = SwaggerUISpecSchema(description="Swagger UI of Weaver API.")
[docs]class OkGetRedocUIResponse(ExtendedMappingSchema):
[docs] header = HtmlHeader()
[docs] body = SwaggerUISpecSchema(description="Redoc UI of Weaver API.")
[docs]class OkGetVersionsResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = VersionsSchema()
[docs]class OkGetConformanceResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = ConformanceSchema()
[docs]class OkGetProvidersListResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = ProvidersBodySchema()
[docs]class OkGetProviderCapabilitiesSchema(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = ProviderCapabilitiesSchema()
[docs]class NoContentDeleteProviderSchema(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = NoContent()
[docs]class NotImplementedDeleteProviderResponse(ExtendedMappingSchema):
[docs] description = "Provider removal not supported using referenced storage."
[docs]class OkGetProviderProcessesSchema(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = ProviderProcessesSchema()
[docs]class GetProcessesQuery(ProcessPagingQuery, ProcessDetailQuery):
[docs] providers = ExtendedSchemaNode( QueryBoolean(), example=True, default=False, missing=drop, description="List local processes as well as all sub-processes of all registered providers. "
"Paging and sorting query parameters are unavailable when providers are requested since lists are " "populated dynamically and cannot ensure consistent process lists per page across providers. " f"Applicable only for Weaver configurations {WEAVER_CONFIG_REMOTE_LIST}, ignored otherwise." )
[docs] ignore = ExtendedSchemaNode( QueryBoolean(), example=True, default=True, missing=drop, description="Only when listing provider processes, any unreachable remote service definitions "
"or unprocessable contents will be silently ignored and dropped from full listing in the response. " "Disabling this option will raise an error immediately instead of ignoring invalid providers." )
[docs]class GetProcessesEndpoint(ExtendedMappingSchema):
[docs] querystring = GetProcessesQuery()
[docs]class ProviderProcessesListing(ProcessCollection):
[docs] _sort_first = ["id", "processes"]
[docs] id = ProviderNameSchema()
[docs]class ProviderProcessesList(ExtendedSequenceSchema):
[docs] item = ProviderProcessesListing(description="Processes offered by the identified remote provider.")
[docs]class ProvidersProcessesCollection(ExtendedMappingSchema):
[docs] providers = ProviderProcessesList(missing=drop)
[docs]class ProcessListingMetadata(ExtendedMappingSchema):
[docs] description = "Metadata relative to the listed processes."
[docs] page = ExtendedSchemaNode(Integer(), misisng=drop, default=None, validator=Range(min=0))
[docs] limit = ExtendedSchemaNode(Integer(), missing=drop, default=None, validator=Range(min=1))
[docs] total = ExtendedSchemaNode(Integer(), description="Total number of local processes, or also including all "
"remote processes across providers if requested.")
[docs]class MultiProcessesListing(DescriptionSchema, ProcessCollection, ProvidersProcessesCollection, ProcessListingMetadata):
[docs] _sort_first = ["description", "processes"]
[docs] _sort_after = ["links"]
[docs]class OkGetProcessesListResponse(ExtendedMappingSchema):
[docs] description = "Listing of available processes successful."
[docs] header = ResponseHeaders()
[docs] body = MultiProcessesListing()
[docs]class OkPostProcessDeployBodySchema(ExtendedMappingSchema):
[docs] deploymentDone = ExtendedSchemaNode(Boolean(), default=False, example=True, description="Indicates if the process was successfully deployed.")
[docs] processSummary = ProcessSummary(missing=drop, description="Deployed process summary if successful.")
[docs] failureReason = ExtendedSchemaNode(String(), missing=drop, description="Description of deploy failure if applicable.")
[docs]class OkPostProcessesResponse(ExtendedMappingSchema):
[docs] description = "Process successfully deployed."
[docs] header = ResponseHeaders()
[docs] body = OkPostProcessDeployBodySchema()
[docs]class BadRequestGetProcessInfoResponse(ExtendedMappingSchema):
[docs] description = "Missing process identifier."
[docs] body = NoContent()
[docs]class OkGetProcessInfoResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = ProcessDescription()
[docs]class OkGetProcessPackageSchema(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = NoContent()
[docs]class OkGetProcessPayloadSchema(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = NoContent()
[docs]class ProcessVisibilityResponseBodySchema(ExtendedMappingSchema):
[docs] value = VisibilityValue()
[docs]class OkGetProcessVisibilitySchema(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = ProcessVisibilityResponseBodySchema()
[docs]class OkPutProcessVisibilitySchema(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = ProcessVisibilityResponseBodySchema()
[docs]class ForbiddenVisibilityUpdateResponseSchema(ExtendedMappingSchema):
[docs] description = "Visibility value modification not allowed."
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class OkDeleteProcessUndeployBodySchema(ExtendedMappingSchema):
[docs] deploymentDone = ExtendedSchemaNode(Boolean(), default=False, example=True, description="Indicates if the process was successfully undeployed.")
[docs] identifier = ExtendedSchemaNode(String(), example="workflow")
[docs] failureReason = ExtendedSchemaNode(String(), missing=drop, description="Description of undeploy failure if applicable.")
[docs]class OkDeleteProcessResponse(ExtendedMappingSchema):
[docs] description = "Process successfully undeployed."
[docs] header = ResponseHeaders()
[docs] body = OkDeleteProcessUndeployBodySchema()
[docs]class OkGetProviderProcessDescriptionResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = ProcessDescription()
[docs]class CreatedPostProvider(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = ProviderSummarySchema()
[docs]class NotImplementedPostProviderResponse(ExtendedMappingSchema):
[docs] description = "Provider registration not supported using specified definition."
[docs]class PreferenceAppliedHeader(ExtendedSchemaNode):
[docs] description = "Applied preferences from submitted 'Prefer' header after validation."
[docs] name = "Preference-Applied"
[docs] schema_type = String
[docs] example = "wait=10s, respond-async"
[docs]class LocationHeader(URL):
[docs] name = "Location"
[docs]class CreatedJobLocationHeader(ResponseHeaders):
[docs] location = LocationHeader(description="Status monitoring location of the job execution.")
[docs] prefer_applied = PreferenceAppliedHeader(missing=drop)
[docs]class CreatedLaunchJobResponse(ExtendedMappingSchema):
[docs] description = "Job successfully submitted to processing queue. Execution should begin when resources are available."
[docs] header = CreatedJobLocationHeader()
[docs] body = CreatedJobStatusSchema()
[docs]class CompletedJobLocationHeader(ResponseHeaders):
[docs] location = LocationHeader(description="Status location of the completed job execution.")
[docs] prefer_applied = PreferenceAppliedHeader(missing=drop)
[docs]class CompletedJobStatusSchema(DescriptionSchema, JobStatusInfo): pass
[docs]class CompletedJobResponse(ExtendedMappingSchema):
[docs] description = "Job submitted and completed execution synchronously."
[docs] header = CompletedJobLocationHeader()
[docs] body = CompletedJobStatusSchema()
[docs]class FailedSyncJobResponse(CompletedJobResponse):
[docs] description = "Job submitted and failed synchronous execution. See server logs for more details."
[docs]class OkDeleteProcessJobResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = DismissedJobSchema()
[docs]class OkGetQueriedJobsResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = GetQueriedJobsSchema()
[docs]class BatchDismissJobsBodySchema(DescriptionSchema):
[docs] jobs = JobIdentifierList(description="Confirmation of jobs that have been dismissed.")
[docs]class OkBatchDismissJobsResponseSchema(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = BatchDismissJobsBodySchema()
[docs]class OkDismissJobResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = DismissedJobSchema()
[docs]class OkGetJobStatusResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = JobStatusInfo()
[docs]class InvalidJobResponseSchema(ExtendedMappingSchema):
[docs] description = "Job reference is not a valid UUID."
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class NotFoundJobResponseSchema(ExtendedMappingSchema):
[docs] description = "Job reference UUID cannot be found."
[docs] examples = { "JobNotFound": { "summary": "Example response when specified job reference cannot be found.", "value": EXAMPLES["job_not_found.json"]
} }
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class GoneJobResponseSchema(ExtendedMappingSchema):
[docs] description = "Job reference UUID cannot be dismissed again or its result artifacts were removed."
[docs] examples = { "JobDismissed": { "summary": "Example response when specified job reference was already dismissed.", "value": EXAMPLES["job_dismissed_error.json"]
} }
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class OkGetJobInputsResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = JobInputsBody()
[docs]class OkGetJobOutputsResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = JobOutputsBody()
[docs]class RedirectResultResponse(ExtendedMappingSchema):
[docs] header = RedirectHeaders()
[docs]class OkGetJobResultsResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = Result()
[docs]class NoContentJobResultsHeaders(NoContent):
[docs] content_length = ContentLengthHeader(example="0")
"Link relation indicates the result ID. " "Additional parameters indicate expected content-type of the resource. " "Literal data requested by reference are returned with contents dumped to plain text file." ))
[docs]class NoContentJobResultsResponse(ExtendedMappingSchema):
[docs] header = NoContentJobResultsHeaders()
[docs] body = NoContent(default="")
[docs]class CreatedQuoteExecuteResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = CreatedQuotedJobStatusSchema()
[docs]class CreatedQuoteResponse(ExtendedMappingSchema):
[docs] description = "Quote successfully obtained for process execution definition."
[docs] header = ResponseHeaders()
[docs] body = QuoteSchema()
[docs]class AcceptedQuoteResponse(ExtendedMappingSchema):
[docs] summary = "Quote successfully submitted."
[docs] description = ( "Quote successfully submitted for evaluating process execution definition. "
"Complete details will be available once evaluation has completed." )
[docs] header = ResponseHeaders()
[docs] body = PartialQuoteSchema()
[docs]class OkGetQuoteInfoResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = QuoteSchema()
[docs]class OkGetQuoteListResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = QuotationListSchema()
[docs]class OkGetBillDetailResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = BillSchema()
[docs]class OkGetBillListResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = BillListSchema()
[docs]class OkGetJobExceptionsResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = JobExceptionsSchema()
[docs]class OkGetJobLogsResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = JobLogsSchema()
[docs]class OkGetJobStatsResponse(ExtendedMappingSchema):
[docs] header = ResponseHeaders()
[docs] body = JobStatisticsSchema()
[docs]class VaultFileID(UUID):
[docs] description = "Vault file identifier."
[docs] example = "78977deb-28af-46f3-876b-cdd272742678"
[docs]class VaultAccessToken(UUID):
[docs] description = "Vault file access token."
[docs] example = "30d889cfb7ae3a63229a8de5f91abc1ef5966bb664972f234a4db9d28f8148e0e" # nosec
[docs]class VaultEndpoint(ExtendedMappingSchema):
[docs] header = RequestHeaders()
[docs]class VaultUploadBody(ExtendedSchemaNode):
[docs] schema_type = String
[docs] description = "Multipart file contents for upload to the vault."
[docs] examples = { ContentType.MULTI_PART_FORM: { "summary": "Upload JSON file to vault as multipart content.", "value": EXAMPLES["vault_file_upload.txt"],
} }
[docs]class VaultUploadEndpoint(ExtendedMappingSchema):
[docs] header = FileUploadHeaders()
[docs] body = VaultUploadBody()
[docs]class VaultFileUploadedBodySchema(ExtendedMappingSchema):
[docs] access_token = AccessToken()
[docs] file_id = VaultFileID()
[docs] file_href = VaultReference()
[docs]class VaultFileUploadedHeaders(ResponseHeaders):
[docs] location = URL(name="Location", description="File download location.", example="https://localhost:4002" + vault_file_service.path.format(file_id=VaultFileID.example))
[docs]class OkVaultFileUploadedResponse(ExtendedMappingSchema):
[docs] description = "File successfully uploaded to vault."
[docs] header = VaultFileUploadedHeaders()
[docs] body = VaultFileUploadedBodySchema()
[docs]class BadRequestVaultFileUploadResponse(ExtendedMappingSchema):
[docs] description = "Missing or incorrectly formed file contents."
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class UnprocessableEntityVaultFileUploadResponse(ExtendedMappingSchema):
[docs] description = ( "Invalid filename refused for upload. "
"Filename should include only alphanumeric, underscore, dash, and dot characters. " "Filename should include both the base name and the desired file extension." )
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class XAuthVaultFileHeader(ExtendedSchemaNode):
[docs] summary = "Authorization header with token for Vault file access."
[docs] description = ( "For accessing a single file from the Vault, such as to obtain file metadata, requests can simply provide "
"the 'token {access-token}' portion in the header without additional parameters. If multiple files require " "access such as during an Execute request, all applicable tokens should be provided using a comma separated " "list of access tokens, each with their indented input ID and array index if applicable " f"(see {DOC_URL}/processes.html#file-vault-inputs for more details)." )
[docs] name = "X-Auth-Vault"
[docs] example = "token {access-token}[; id={vault-id}]"
[docs] schema_type = String
[docs]class VaultFileRequestHeaders(ExtendedMappingSchema):
[docs] access_token = XAuthVaultFileHeader()
[docs]class VaultFileEndpoint(VaultEndpoint):
[docs] header = VaultFileRequestHeaders()
[docs] file_id = VaultFileID()
[docs]class OkVaultFileDetailResponse(ExtendedMappingSchema):
[docs] header = FileResponseHeaders()
[docs] body = NoContent(default="")
[docs]class OkVaultFileDownloadResponse(OkVaultFileDetailResponse): pass
[docs]class BadRequestVaultFileAccessResponse(ExtendedMappingSchema):
[docs] description = "Invalid file vault reference."
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class ForbiddenVaultFileDownloadResponse(ExtendedMappingSchema):
[docs] description = "Forbidden access to vault file. Invalid authorization from provided token."
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]class GoneVaultFileDownloadResponse(ExtendedMappingSchema):
[docs] description = "Vault File resource corresponding to specified ID is not available anymore."
[docs] header = ResponseHeaders()
[docs] body = ErrorJsonResponseBodySchema()
[docs]get_api_frontpage_responses = { "200": OkGetFrontpageResponse(description="success"), "500": InternalServerErrorResponseSchema(),
}
[docs]get_openapi_json_responses = { "200": OkGetSwaggerJSONResponse(description="success"), "500": InternalServerErrorResponseSchema(),
}
[docs]get_api_swagger_ui_responses = { "200": OkGetSwaggerUIResponse(description="success"), "500": InternalServerErrorResponseSchema(),
}
[docs]get_api_redoc_ui_responses = { "200": OkGetRedocUIResponse(description="success"), "500": InternalServerErrorResponseSchema(),
}
[docs]get_api_versions_responses = { "200": OkGetVersionsResponse(description="success"), "500": InternalServerErrorResponseSchema(),
}
[docs]get_api_conformance_responses = { "200": OkGetConformanceResponse(description="success"), "500": InternalServerErrorResponseSchema(),
}
[docs]get_processes_responses = { "200": OkGetProcessesListResponse(examples={ "ProcessesListing": { "summary": "Listing of identifiers of local processes registered in Weaver.", "value": EXAMPLES["local_process_listing.json"], }, "ProcessesDetails": { "summary": "Detailed definitions of local processes registered in Weaver.", "value": EXAMPLES["local_process_listing.json"], }, "ProvidersProcessesListing": { "summary": "List of identifiers combining all local and remote processes known by Weaver.", "value": EXAMPLES["providers_processes_listing.json"], }, "ProvidersProcessesDetails": { "summary": "Detailed definitions Combining all local and remote processes known by Weaver.", "value": EXAMPLES["providers_processes_listing.json"], } }), "400": BadRequestResponseSchema(description="Error in case of invalid listing query parameters."), "500": InternalServerErrorResponseSchema(),
}
[docs]post_processes_responses = { "201": OkPostProcessesResponse(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_process_responses = { "200": OkGetProcessInfoResponse(description="success", examples={ "ProcessDescriptionSchemaOGC": { "summary": "Description of a local process registered in Weaver (OGC Schema) " "with fields on top-level and using inputs/outputs as mapping with keys as IDs.", "value": EXAMPLES["local_process_description_ogc_api.json"], }, "ProcessDescriptionSchemaOld": { "summary": "Description of a local process registered in Weaver (Old Schema) " "with fields nested under a process section and using inputs/outputs listed with IDs.", "value": EXAMPLES["local_process_description.json"], } }), "400": BadRequestGetProcessInfoResponse(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_process_package_responses = { "200": OkGetProcessPackageSchema(description="success", examples={ "PackageCWL": { "summary": "CWL Application Package definition of the local process.", "value": EXAMPLES["local_process_package.json"], } }), "403": ForbiddenProcessAccessResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_process_payload_responses = { "200": OkGetProcessPayloadSchema(description="success", examples={ "Payload": { "summary": "Payload employed during process deployment and registration.", "value": EXAMPLES["local_process_payload.json"], } }), "403": ForbiddenProcessAccessResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_process_visibility_responses = { "200": OkGetProcessVisibilitySchema(description="success"), "403": ForbiddenProcessAccessResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]put_process_visibility_responses = { "200": OkPutProcessVisibilitySchema(description="success"), "403": ForbiddenVisibilityUpdateResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]delete_process_responses = { "200": OkDeleteProcessResponse(), "403": ForbiddenProcessAccessResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_providers_list_responses = { "200": OkGetProvidersListResponse(description="success", examples={ "ProviderList": { "summary": "Listing of registered remote providers.", "value": EXAMPLES["provider_listing.json"], }, "ProviderNames": { "summary": "Listing of registered providers names without validation.", "value": EXAMPLES["provider_names.json"], } }), "403": ForbiddenProviderAccessResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_provider_responses = { "200": OkGetProviderCapabilitiesSchema(description="success", examples={ "ProviderDescription": { "summary": "Description of a registered remote WPS provider.", "value": EXAMPLES["provider_description.json"], } }), "403": ForbiddenProviderAccessResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]delete_provider_responses = { "204": NoContentDeleteProviderSchema(description="success"), "403": ForbiddenProviderAccessResponseSchema(), "500": InternalServerErrorResponseSchema(), "501": NotImplementedDeleteProviderResponse(),
}
[docs]get_provider_processes_responses = { "200": OkGetProviderProcessesSchema(description="success"), "403": ForbiddenProviderAccessResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_provider_process_responses = { "200": OkGetProviderProcessDescriptionResponse(description="success", examples={ "ProviderProcessWPS": { "summary": "Description of a remote WPS provider process converted to OGC-API Processes format.", "value": EXAMPLES["provider_process_description.json"] } }), "403": ForbiddenProviderAccessResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]post_provider_responses = { "201": CreatedPostProvider(description="success"), "400": ExtendedMappingSchema(description=OWSMissingParameterValue.description), "403": ForbiddenProviderAccessResponseSchema(), "500": InternalServerErrorResponseSchema(), "501": NotImplementedPostProviderResponse(),
}
[docs]post_provider_process_job_responses = { "200": CompletedJobResponse(description="success"), "201": CreatedLaunchJobResponse(description="success"), "204": NoContentJobResultsResponse(description="success"), "400": FailedSyncJobResponse(), "403": ForbiddenProviderAccessResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]post_process_jobs_responses = { "200": CompletedJobResponse(description="success"), "201": CreatedLaunchJobResponse(description="success"), "204": NoContentJobResultsResponse(description="success"), "400": FailedSyncJobResponse(), "403": ForbiddenProviderAccessResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_all_jobs_responses = { "200": OkGetQueriedJobsResponse(description="success", examples={ "JobListing": { "summary": "Job ID listing with default queries.", "value": EXAMPLES["jobs_listing.json"] } }), "400": BadRequestResponseSchema(description="Error in case of invalid search query parameters."), "422": UnprocessableEntityResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]delete_jobs_responses = { "200": OkBatchDismissJobsResponseSchema(description="success"), "400": BadRequestResponseSchema(), "422": UnprocessableEntityResponseSchema(),
}
[docs]get_prov_all_jobs_responses = copy(get_all_jobs_responses)
get_prov_all_jobs_responses.update({ "403": ForbiddenProviderLocalResponseSchema(), })
[docs]get_single_job_status_responses = { "200": OkGetJobStatusResponse(description="success", examples={ "JobStatusSuccess": { "summary": "Successful job status response.", "value": EXAMPLES["job_status_success.json"]}, "JobStatusFailure": { "summary": "Failed job status response.", "value": EXAMPLES["job_status_failed.json"], } }), "400": InvalidJobResponseSchema(), "404": NotFoundJobResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_prov_single_job_status_responses = copy(get_single_job_status_responses)
get_prov_single_job_status_responses.update({ "403": ForbiddenProviderLocalResponseSchema(), })
[docs]delete_job_responses = { "200": OkDismissJobResponse(description="success"), "400": InvalidJobResponseSchema(), "404": NotFoundJobResponseSchema(), "410": GoneJobResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]delete_prov_job_responses = copy(delete_job_responses)
delete_prov_job_responses.update({ "403": ForbiddenProviderLocalResponseSchema(), })
[docs]get_job_inputs_responses = { "200": OkGetJobInputsResponse(description="success", examples={ "JobInputs": { "summary": "Submitted job input values at for process execution.", "value": EXAMPLES["job_inputs.json"], } }), "400": InvalidJobResponseSchema(), "404": NotFoundJobResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_prov_inputs_responses = copy(get_job_inputs_responses)
get_prov_inputs_responses.update({ "403": ForbiddenProviderLocalResponseSchema(), })
[docs]get_job_outputs_responses = { "200": OkGetJobOutputsResponse(description="success", examples={ "JobOutputs": { "summary": "Obtained job outputs values following process execution.", "value": EXAMPLES["job_outputs.json"], } }), "400": InvalidJobResponseSchema(), "404": NotFoundJobResponseSchema(), "410": GoneJobResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_prov_outputs_responses = copy(get_job_outputs_responses)
get_prov_outputs_responses.update({ "403": ForbiddenProviderLocalResponseSchema(), })
[docs]get_result_redirect_responses = { "308": RedirectResultResponse(description="Redirects '/result' (without 's') to corresponding '/results' path."),
}
[docs]get_job_results_responses = { "200": OkGetJobResultsResponse(description="success", examples={ "JobResults": { "summary": "Obtained job results.", "value": EXAMPLES["job_results.json"], } }), "204": NoContentJobResultsResponse(description="success"), "400": InvalidJobResponseSchema(), "404": NotFoundJobResponseSchema(), "410": GoneJobResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_prov_results_responses = copy(get_job_results_responses)
get_prov_results_responses.update({ "403": ForbiddenProviderLocalResponseSchema(), })
[docs]get_exceptions_responses = { "200": OkGetJobExceptionsResponse(description="success", examples={ "JobExceptions": { "summary": "Job exceptions that occurred during failing process execution.", "value": EXAMPLES["job_exceptions.json"], } }), "400": InvalidJobResponseSchema(), "404": NotFoundJobResponseSchema(), "410": GoneJobResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_prov_exceptions_responses = copy(get_exceptions_responses)
get_prov_exceptions_responses.update({ "403": ForbiddenProviderLocalResponseSchema(), })
[docs]get_logs_responses = { "200": OkGetJobLogsResponse(description="success", examples={ "JobLogs": { "summary": "Job logs registered and captured throughout process execution.", "value": EXAMPLES["job_logs.json"], } }), "400": InvalidJobResponseSchema(), "404": NotFoundJobResponseSchema(), "410": GoneJobResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_prov_logs_responses = copy(get_logs_responses)
get_prov_logs_responses.update({ "403": ForbiddenProviderLocalResponseSchema(), })
[docs]get_stats_responses = { "200": OkGetJobStatsResponse(description="success", examples={ "JobStatistics": { "summary": "Job statistics collected following process execution.", "value": EXAMPLES["job_statistics.json"], } }), "400": InvalidJobResponseSchema(), "404": NotFoundJobResponseSchema(), "410": GoneJobResponseSchema(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_prov_stats_responses = copy(get_stats_responses)
get_prov_stats_responses.update({ "403": ForbiddenProviderLocalResponseSchema(), })
[docs]get_quote_list_responses = { "200": OkGetQuoteListResponse(description="success"), "500": InternalServerErrorResponseSchema(),
}
[docs]get_quote_responses = { "200": OkGetQuoteInfoResponse(description="success"), "500": InternalServerErrorResponseSchema(),
}
[docs]post_quotes_responses = { "201": CreatedQuoteResponse(), "202": AcceptedQuoteResponse(), "500": InternalServerErrorResponseSchema(),
}
[docs]post_quote_responses = { "201": CreatedQuoteExecuteResponse(description="success"), "500": InternalServerErrorResponseSchema(),
}
[docs]get_bill_list_responses = { "200": OkGetBillListResponse(description="success"), "500": InternalServerErrorResponseSchema(),
}
[docs]get_bill_responses = { "200": OkGetBillDetailResponse(description="success"), "500": InternalServerErrorResponseSchema(),
}
[docs]post_vault_responses = { "200": OkVaultFileUploadedResponse(description="success", examples={ "VaultFileUploaded": { "summary": "File successfully uploaded to vault.", "value": EXAMPLES["vault_file_uploaded.json"], } }), "400": BadRequestVaultFileUploadResponse(), "422": UnprocessableEntityVaultFileUploadResponse(), "500": InternalServerErrorResponseSchema(),
}
[docs]head_vault_file_responses = { "200": OkVaultFileDetailResponse(description="success", examples={ "VaultFileDetails": { "summary": "Obtain vault file metadata.", "value": EXAMPLES["vault_file_head.json"], } }), "400": BadRequestVaultFileAccessResponse(), "403": ForbiddenVaultFileDownloadResponse(), "410": GoneVaultFileDownloadResponse(), "500": InternalServerErrorResponseSchema(),
}
[docs]get_vault_file_responses = { "200": OkVaultFileDownloadResponse(description="success"), "400": BadRequestVaultFileAccessResponse(), "403": ForbiddenVaultFileDownloadResponse(), "410": GoneVaultFileDownloadResponse(), "500": InternalServerErrorResponseSchema(),
}
[docs]wps_responses = { "200": OkWPSResponse(examples={ "GetCapabilities": { "summary": "GetCapabilities example response.", "value": EXAMPLES["wps_getcapabilities.xml"] }, "DescribeProcess": { "summary": "DescribeProcess example response.", "value": EXAMPLES["wps_describeprocess.xml"] }, "Execute": { "summary": "Execute example response.", "value": EXAMPLES["wps_execute_response.xml"] } }), "400": ErrorWPSResponse(examples={ "MissingParameterError": { "summary": "Error report in case of missing request parameter.", "value": EXAMPLES["wps_missing_parameter.xml"], } }), "500": ErrorWPSResponse(),
} ################################################################# # Utility methods #################################################################
[docs]def service_api_route_info(service_api, settings): # type: (Service, SettingsType) -> ViewInfo """ Automatically generates the view configuration parameters from the :mod:`cornice` service definition. :param service_api: cornice service with name and path definition. :param settings: settings to obtain the base path of the application. :return: view configuration parameters that can be passed directly to ``config.add_route`` call. """ from weaver.wps_restapi.utils import wps_restapi_base_path # import here to avoid circular import errors api_base = wps_restapi_base_path(settings) return {"name": service_api.name, "pattern": f"{api_base}{service_api.path}"}
[docs]def datetime_interval_parser(datetime_interval): # type: (str) -> DatetimeIntervalType """ This function parses a given datetime or interval into a dictionary that will be easy for database process. """ parsed_datetime = {} if datetime_interval.startswith(DATETIME_INTERVAL_OPEN_START_SYMBOL): datetime_interval = datetime_interval.replace(DATETIME_INTERVAL_OPEN_START_SYMBOL, "") parsed_datetime["before"] = date_parser.parse(datetime_interval) elif datetime_interval.endswith(DATETIME_INTERVAL_OPEN_END_SYMBOL): datetime_interval = datetime_interval.replace(DATETIME_INTERVAL_OPEN_END_SYMBOL, "") parsed_datetime["after"] = date_parser.parse(datetime_interval) elif DATETIME_INTERVAL_CLOSED_SYMBOL in datetime_interval: datetime_interval = datetime_interval.split(DATETIME_INTERVAL_CLOSED_SYMBOL) parsed_datetime["after"] = date_parser.parse(datetime_interval[0]) parsed_datetime["before"] = date_parser.parse(datetime_interval[-1]) else: parsed_datetime["match"] = date_parser.parse(datetime_interval) return parsed_datetime