Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
488262f
issue #693 add search for schema and find parameters from the backend
ElienVandermaesenVITO Jan 6, 2025
8699f3c
issue #693 use openeo.internal.process.parse intead of new functions
ElienVandermaesenVITO Jan 8, 2025
7440d71
issue #698 add exception and change documentation
ElienVandermaesenVITO Jan 9, 2025
b506a11
issue #698 add fallback situations
ElienVandermaesenVITO Jan 9, 2025
71b2b79
issue #693 add mock for sar_backscatter test for processes
ElienVandermaesenVITO Jan 9, 2025
53936a6
Merge branch 'master' into issue693-sar_backscatter-get-coefficients-…
ElienVandermaesenVITO Jan 9, 2025
ece05dc
issue #693 add test for search_list_for_dict_key
ElienVandermaesenVITO Jan 9, 2025
503154b
issue #693 add parse.get_parameter, to retrieve parameter in schema m…
ElienVandermaesenVITO Jan 14, 2025
a4b79a0
issue693 move adapt search_list_for_dict_key to get_enum_options for …
ElienVandermaesenVITO Feb 4, 2025
454cf79
issue693 run pre-commit
ElienVandermaesenVITO Feb 4, 2025
877c1a3
Merge branch 'master' into issue693-sar_backscatter-get-coefficients-…
ElienVandermaesenVITO Feb 4, 2025
d8a4718
issue693 add test for sar_backscatter with coefficient check
ElienVandermaesenVITO Feb 4, 2025
7712675
issue693 use default option from backend in datacube.sar_backscatter
ElienVandermaesenVITO Feb 11, 2025
754a399
issue693 replace default by unset and combine enum options
ElienVandermaesenVITO Feb 21, 2025
a2bda78
issue693 detect type null in schema
ElienVandermaesenVITO Feb 27, 2025
6120186
issue693 add changelog entry
ElienVandermaesenVITO Mar 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions openeo/rest/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from openeo.internal.graph_building import FlatGraphableMixin, PGNode, as_flat_graph
from openeo.internal.jupyter import VisualDict, VisualList
from openeo.internal.processes.builder import ProcessBuilderBase
from openeo.internal.processes.parse import Process
from openeo.internal.warnings import deprecated, legacy_alias
from openeo.metadata import (
Band,
Expand Down Expand Up @@ -1066,6 +1067,28 @@ def describe_process(self, id: str, namespace: Optional[str] = None) -> dict:

raise OpenEoClientException("Process does not exist.")

def get_schema_from_process_parameter(
self, process_id: str, parameter_id: str, namespace: Optional[str] = None
) -> Union[dict, list]:
"""
Returns schema of the parameter of the process from the back end.

:param process_id: The id of the process.
:param parameter_id: The id of the parameter.
:param namespace: The namespace of the process.

:return: schema of the parameter in the process.
"""
processes = self.list_processes(namespace)
for process in processes:
if process["id"] == process_id:
schema = Process.from_dict(process)
for parameter in schema.parameters:
if parameter.name == parameter_id:
return parameter.schema.schema
raise OpenEoClientException("Parameter does not exist.")
raise OpenEoClientException("Process does not exist.")

def list_jobs(self, limit: Union[int, None] = None) -> List[dict]:
"""
Lists all jobs of the authenticated user.
Expand Down
16 changes: 12 additions & 4 deletions openeo/rest/datacube.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,14 @@
from openeo.rest.service import Service
from openeo.rest.udp import RESTUserDefinedProcess
from openeo.rest.vectorcube import VectorCube
from openeo.util import dict_no_none, guess_format, load_json, normalize_crs, rfc3339
from openeo.util import (
dict_no_none,
guess_format,
load_json,
normalize_crs,
rfc3339,
search_list_for_dict_key,
)

if typing.TYPE_CHECKING:
# Imports for type checking only (circular import issue at runtime).
Expand Down Expand Up @@ -2732,9 +2739,10 @@ def sar_backscatter(
.. versionadded:: 0.4.9
.. versionchanged:: 0.4.10 replace `orthorectify` and `rtc` arguments with `coefficient`.
"""
coefficient_options = [
"beta0", "sigma0-ellipsoid", "sigma0-terrain", "gamma0-ellipsoid", "gamma0-terrain", None
]
coefficient_options = [None]
if self.connection:
schema = self.connection.get_schema_from_process_parameter("sar_backscatter", "coefficient")
coefficient_options += search_list_for_dict_key(schema, "enum")
if coefficient not in coefficient_options:
raise OpenEoClientException("Invalid `sar_backscatter` coefficient {c!r}. Should be one of {o}".format(
c=coefficient, o=coefficient_options
Expand Down
19 changes: 19 additions & 0 deletions openeo/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -687,3 +687,22 @@ def normalize_crs(crs: Any, *, use_pyproj: bool = True) -> Union[None, int, str]
raise ValueError(f"Can not normalize CRS data {type(crs)}")

return crs


def search_list_for_dict_key(lst: list, key: str) -> Union[dict, list]:
"""
Searches a value of the dict that matches with the key in the list.

:param lst: list with dictionaries.
:param key: The key for which the value is searched for.

:return: value that matches key.
"""
result = None
for item in lst:
if key in item:
if result is None:
result = item[key]
else:
raise ValueError("Multiple keys found with value {v}.".format(v=key))
return result
124 changes: 120 additions & 4 deletions tests/rest/datacube/test_datacube100.py
Original file line number Diff line number Diff line change
Expand Up @@ -2744,7 +2744,36 @@ def test_print_json_file_path(con100, tmp_path, path_factory):
assert path.read_text() == EXPECTED_JSON_EXPORT_S2_NDVI + "\n"


def test_sar_backscatter_defaults(con100):
def test_sar_backscatter_defaults(con100, requests_mock):
requests_mock.get(API_URL, json={"api_version": "1.0.0"})
processes = [
{
"id": "sar_backscatter",
"description": "Computes backscatter from SAR input",
"summary": "Computes backscatter from SAR input",
"parameters": [
{
"default": "gamma0-terrain",
"description": "Select the radiometric correction coefficient.",
"name": "coefficient",
"schema": [
{
"enum": [
"beta0",
"sigma0-ellipsoid",
"sigma0-terrain",
"gamma0-ellipsoid",
"gamma0-terrain",
],
"type": "string",
},
],
},
],
"returns": {"description": "incremented value", "schema": {"type": "integer"}},
}
]
requests_mock.get(API_URL + "/processes", json={"processes": processes})
cube = con100.load_collection("S2").sar_backscatter()
assert _get_leaf_node(cube) == {
"process_id": "sar_backscatter",
Expand All @@ -2762,7 +2791,36 @@ def test_sar_backscatter_defaults(con100):
}


def test_sar_backscatter_custom(con100):
def test_sar_backscatter_custom(con100, requests_mock):
requests_mock.get(API_URL, json={"api_version": "1.0.0"})
processes = [
{
"id": "sar_backscatter",
"description": "Computes backscatter from SAR input",
"summary": "Computes backscatter from SAR input",
"parameters": [
{
"default": "gamma0-terrain",
"description": "Select the radiometric correction coefficient.",
"name": "coefficient",
"schema": [
{
"enum": [
"beta0",
"sigma0-ellipsoid",
"sigma0-terrain",
"gamma0-ellipsoid",
"gamma0-terrain",
],
"type": "string",
},
],
},
],
"returns": {"description": "incremented value", "schema": {"type": "integer"}},
}
]
requests_mock.get(API_URL + "/processes", json={"processes": processes})
cube = con100.load_collection("S2")
cube = cube.sar_backscatter(
coefficient="sigma0-ellipsoid",
Expand All @@ -2786,13 +2844,71 @@ def test_sar_backscatter_custom(con100):
}


def test_sar_backscatter_coefficient_none(con100):
def test_sar_backscatter_coefficient_none(con100, requests_mock):
requests_mock.get(API_URL, json={"api_version": "1.0.0"})
processes = [
{
"id": "sar_backscatter",
"description": "Computes backscatter from SAR input",
"summary": "Computes backscatter from SAR input",
"parameters": [
{
"default": "gamma0-terrain",
"description": "Select the radiometric correction coefficient.",
"name": "coefficient",
"schema": [
{
"enum": [
"beta0",
"sigma0-ellipsoid",
"sigma0-terrain",
"gamma0-ellipsoid",
"gamma0-terrain",
],
"type": "string",
},
],
},
],
"returns": {"description": "incremented value", "schema": {"type": "integer"}},
}
]
requests_mock.get(API_URL + "/processes", json={"processes": processes})
cube = con100.load_collection("S2")
cube = cube.sar_backscatter(coefficient=None)
assert _get_leaf_node(cube)["arguments"]["coefficient"] is None


def test_sar_backscatter_coefficient_invalid(con100):
def test_sar_backscatter_coefficient_invalid(con100, requests_mock):
requests_mock.get(API_URL, json={"api_version": "1.0.0"})
processes = [
{
"id": "sar_backscatter",
"description": "Computes backscatter from SAR input",
"summary": "Computes backscatter from SAR input",
"parameters": [
{
"default": "gamma0-terrain",
"description": "Select the radiometric correction coefficient.",
"name": "coefficient",
"schema": [
{
"enum": [
"beta0",
"sigma0-ellipsoid",
"sigma0-terrain",
"gamma0-ellipsoid",
"gamma0-terrain",
],
"type": "string",
},
],
},
],
"returns": {"description": "incremented value", "schema": {"type": "integer"}},
}
]
requests_mock.get(API_URL + "/processes", json={"processes": processes})
cube = con100.load_collection("S2")
with pytest.raises(OpenEoClientException, match="Invalid.*coef.*unicorn.*Should.*sigma0-ellipsoid.*gamma0-terrain"):
cube.sar_backscatter(coefficient="unicorn")
Expand Down
25 changes: 25 additions & 0 deletions tests/rest/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2874,6 +2874,31 @@ def test_list_processes_namespace(requests_mock):
assert m.call_count == 1


def test_get_schema_from_process_parameter(requests_mock):
requests_mock.get(API_URL, json={"api_version": "1.0.0"})
processes = [
{
"id": "incr",
"description": "Increment a value",
"summary": "Increment a value",
"parameters": [{"name": "x", "description": "value", "schema": {"type": "integer"}}],
"returns": {"description": "incremented value", "schema": {"type": "integer"}},
},
{
"id": "pi",
"description": "Pi",
"summary": "Pi",
"parameters": [],
"returns": {"description": "value of pi", "schema": {"type": "number"}},
},
]
m = requests_mock.get(API_URL + "processes", json={"processes": processes})
conn = Connection(API_URL)
assert conn.list_processes() == processes
schema = conn.get_schema_from_process_parameter("incr", "x")
assert schema == {"type": "integer"}


def test_get_job(requests_mock):
requests_mock.get(API_URL, json={"api_version": "1.0.0"})
conn = Connection(API_URL)
Expand Down
Loading