Source code for openeo.api.process

from __future__ import annotations

import warnings
from typing import List, Optional, Union


[docs] class Parameter: """ A (process) parameter to build parameterized :ref:`user-defined processes<user-defined-processes>`. Parameter objects can be :ref:`defined <udp-declaring-parameters>` with at least a name and expected schema (e.g. is the parameter a placeholder for a string, a bounding box, a date, ...) and can then be :ref:`used <build_and_store_udp>` with various functions and classes, like :py:class:`~openeo.rest.datacube.DataCube`, to build parameterized user-defined processes. Apart from the generic :py:class:`Parameter` constructor, this class also provides various helpers (class methods) to easily create parameters for common parameter types. :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. :param schema: JSON schema describing the expected data type and structure of the parameter. :param default: default value for the parameter when it's optional. :param optional: toggle to indicate whether the parameter is optional or required. """ # TODO unify with openeo.internal.processes.parse.Parameter? __slots__ = ("name", "description", "schema", "default", "optional") _DEFAULT_UNDEFINED = object() def __init__( self, name: str, description: Optional[str] = None, schema: Union[dict, str, None] = None, default=_DEFAULT_UNDEFINED, optional: Optional[bool] = None, ): self.name = name if description is None: # Description is required in openEO API, we are a bit more permissive here. warnings.warn("Parameter without description: using name as description.") description = name self.description = description self.schema = {"type": schema} if isinstance(schema, str) else (schema or {}) # TODO: automatically set `optional` when `default` is set? self.default = default self.optional = optional
[docs] def to_dict(self) -> dict: """ Convert to dictionary for JSON-serialization. """ d = {"name": self.name, "description": self.description, "schema": self.schema} if self.optional is not None: d["optional"] = self.optional if self.default is not self._DEFAULT_UNDEFINED: d["default"] = self.default d["optional"] = True return d
[docs] @classmethod def raster_cube(cls, name: str = "data", description: str = "A data cube.", **kwargs) -> Parameter: """ Helper to easily create a 'raster-cube' parameter. :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. See the generic :py:class:`Parameter` constructor for information on additional arguments (except ``schema``). """ schema = {"type": "object", "subtype": "raster-cube"} return cls(name=name, description=description, schema=schema, **kwargs)
[docs] @classmethod def datacube(cls, name: str = "data", description: str = "A data cube.", **kwargs) -> Parameter: """ Helper to easily create a 'datacube' parameter. :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. See the generic :py:class:`Parameter` constructor for information on additional arguments (except ``schema``). .. versionadded:: 0.22.0 """ schema = {"type": "object", "subtype": "datacube"} return cls(name=name, description=description, schema=schema, **kwargs)
[docs] @classmethod def string( cls, name: str, description: Optional[str] = None, *, values: Optional[List[str]] = None, subtype: Optional[str] = None, format: Optional[str] = None, **kwargs, ) -> Parameter: """ Helper to easily create a 'string' parameter. :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. :param values: Optional list of allowed string values to make this an "enum". :param subtype: Optional subtype of the 'string' schema. :param format: Optional format of the 'string' schema. See the generic :py:class:`Parameter` constructor for information on additional arguments (except ``schema``). """ schema = {"type": "string"} if values is not None: schema["enum"] = values if subtype: schema["subtype"] = subtype if format: schema["format"] = format return cls(name=name, description=description, schema=schema, **kwargs)
[docs] @classmethod def integer(cls, name: str, description: Optional[str] = None, **kwargs) -> Parameter: """ Helper to create an 'integer' parameter. :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. See the generic :py:class:`Parameter` constructor for information on additional arguments (except ``schema``). """ return cls(name=name, description=description, schema={"type": "integer"}, **kwargs)
[docs] @classmethod def number(cls, name: str, description: Optional[str] = None, **kwargs) -> Parameter: """ Helper to easily create a 'number' parameter. :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. See the generic :py:class:`Parameter` constructor for information on additional arguments (except ``schema``). """ return cls(name=name, description=description, schema={"type": "number"}, **kwargs)
[docs] @classmethod def boolean(cls, name: str, description: Optional[str] = None, **kwargs) -> Parameter: """ Helper to easily create a 'boolean' parameter. :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. See the generic :py:class:`Parameter` constructor for information on additional arguments (except ``schema``). """ return cls(name=name, description=description, schema={"type": "boolean"}, **kwargs)
[docs] @classmethod def array( cls, name: str, description: Optional[str] = None, *, item_schema: Optional[Union[str, dict]] = None, **kwargs, ) -> Parameter: """ Helper to easily create parameter with an 'array' schema. :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. :param item_schema: Schema of the array items given in JSON Schema style, e.g. ``{"type": "string"}``. Simple schemas can also be specified as single string: e.g. ``"string"`` will be expanded to ``{"type": "string"}``. See the generic :py:class:`Parameter` constructor for information on additional arguments (except ``schema``). .. versionchanged:: 0.23.0 Added ``item_schema`` argument. """ schema = {"type": "array"} if item_schema: if isinstance(item_schema, str): item_schema = {"type": item_schema} schema["items"] = item_schema return cls(name=name, description=description, schema=schema, **kwargs)
[docs] @classmethod def object( cls, name: str, description: Optional[str] = None, *, subtype: Optional[str] = None, **kwargs ) -> Parameter: """ Helper to create an 'object' type parameter :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. :param subtype: subtype of the 'object' schema See the generic :py:class:`Parameter` constructor for information on additional arguments (except ``schema``). .. versionadded:: 0.26.0 """ schema = {"type": "object"} if subtype: schema["subtype"] = subtype return cls(name=name, description=description, schema=schema, **kwargs)
[docs] @classmethod def bounding_box( cls, name: str, description: str = "Spatial extent specified as a bounding box with 'west', 'south', 'east' and 'north' fields.", **kwargs, ) -> Parameter: """ Helper to easily create a 'bounding box' parameter, which allows to specify a spatial extent with "west", "south", "east" and "north" bounds (and optionally a CRS identifier). :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. See the generic :py:class:`Parameter` constructor for information on additional arguments (except ``schema``). .. versionadded:: 0.30.0 """ schema = { "type": "object", "subtype": "bounding-box", "required": ["west", "south", "east", "north"], "properties": { "west": { "type": "number", "description": "West (lower left corner, coordinate axis 1).", }, "south": { "type": "number", "description": "South (lower left corner, coordinate axis 2).", }, "east": { "type": "number", "description": "East (upper right corner, coordinate axis 1).", }, "north": { "type": "number", "description": "North (upper right corner, coordinate axis 2).", }, "crs": { "description": "Coordinate reference system of the extent, specified as as [EPSG code](http://www.epsg-registry.org/) or [WKT2 CRS string](http://docs.opengeospatial.org/is/18-010r7/18-010r7.html). Defaults to `4326` (EPSG code 4326) unless the client explicitly requests a different coordinate reference system.", "anyOf": [ { "type": "integer", "subtype": "epsg-code", "title": "EPSG Code", "minimum": 1000, }, { "type": "string", "subtype": "wkt2-definition", "title": "WKT2 definition", }, ], "default": 4326, }, # TODO: support base and height? }, } return cls(name=name, description=description, schema=schema, **kwargs)
[docs] @classmethod def date(cls, name: str, description: str = "A date.", **kwargs) -> Parameter: """ Helper to easily create a 'date' parameter. :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. See the generic :py:class:`Parameter` constructor for information on additional arguments (except ``schema``). .. versionadded:: 0.30.0 """ schema = {"type": "string", "subtype": "date", "format": "date"} return cls(name=name, description=description, schema=schema, **kwargs)
[docs] @classmethod def date_time(cls, name: str, description: str = "A date with time.", **kwargs) -> Parameter: """ Helper to easily create a 'date-time' parameter. :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. See the generic :py:class:`Parameter` constructor for information on additional arguments (except ``schema``). .. versionadded:: 0.30.0 """ schema = {"type": "string", "subtype": "date-time", "format": "date-time"} return cls(name=name, description=description, schema=schema, **kwargs)
[docs] @classmethod def geojson(cls, name: str, description: str = "Geometries specified as GeoJSON object.", **kwargs) -> Parameter: """ Helper to easily create a 'geojson' parameter, which allows to specify geometries as an inline GeoJSON object. :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. See the generic :py:class:`Parameter` constructor for information on additional arguments (except ``schema``). .. versionadded:: 0.30.0 """ schema = {"type": "object", "subtype": "geojson"} return cls(name=name, description=description, schema=schema, **kwargs)
[docs] @classmethod def temporal_interval( cls, name: str, description: str = "Temporal extent specified as two-element array with start and end date/date-time.", **kwargs, ) -> Parameter: """ Helper to easily create a 'temporal-interval' parameter, which allows to specify a temporal extent as a two-element array with start and end date/date-time. :param name: parameter name, which will be used to assign concrete values to. It is recommended to stick to the convention of snake case naming (using lowercase with underscores). :param description: human-readable description of the parameter. See the generic :py:class:`Parameter` constructor for information on additional arguments (except ``schema``). .. versionadded:: 0.30.0 """ schema = { "type": "array", "subtype": "temporal-interval", "uniqueItems": True, "minItems": 2, "maxItems": 2, "items": { "anyOf": [ {"type": "string", "subtype": "date-time", "format": "date-time"}, {"type": "string", "subtype": "date", "format": "date"}, {"type": "null"}, ] }, } return cls(name=name, description=description, schema=schema, **kwargs)