Skip to content

Commit 29a3276

Browse files
committed
Issue #668 federation extension: cover "federation:backends" on POST /validation
1 parent 000b026 commit 29a3276

File tree

5 files changed

+91
-3
lines changed

5 files changed

+91
-3
lines changed

openeo/rest/_testing.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,10 @@ def _handle_post_validation(self, request, context):
277277
"""Handler of `POST /validation` (validate process graph)."""
278278
pg = request.json()["process_graph"]
279279
self.validation_requests.append(pg)
280-
return {"errors": self.next_validation_errors}
280+
if isinstance(self.next_validation_errors, list):
281+
return {"errors": self.next_validation_errors}
282+
else:
283+
return self.next_validation_errors
281284

282285
def get_sync_pg(self) -> dict:
283286
"""Get one and only synchronous process graph"""

openeo/rest/connection.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
CollectionListingResponse,
7171
JobListingResponse,
7272
ProcessListingResponse,
73+
ValidationResponse,
7374
)
7475
from openeo.rest.service import Service
7576
from openeo.rest.udp import Parameter, RESTUserDefinedProcess
@@ -965,7 +966,7 @@ def user_defined_process(self, user_defined_process_id: str) -> RESTUserDefinedP
965966

966967
def validate_process_graph(
967968
self, process_graph: Union[dict, FlatGraphableMixin, str, Path, List[FlatGraphableMixin]]
968-
) -> List[dict]:
969+
) -> ValidationResponse:
969970
"""
970971
Validate a process graph without executing it.
971972
@@ -979,7 +980,8 @@ def validate_process_graph(
979980
:return: list of errors (dictionaries with "code" and "message" fields)
980981
"""
981982
pg_with_metadata = self._build_request_with_process_graph(process_graph)["process"]
982-
return self.post(path="/validation", json=pg_with_metadata, expected_status=200).json()["errors"]
983+
data = self.post(path="/validation", json=pg_with_metadata, expected_status=200).json()
984+
return ValidationResponse(response_data=data)
983985

984986
@property
985987
def _api_version(self) -> ComparableVersion:

openeo/rest/models/federation_extension.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,13 @@ def get_federation_missing(data: dict, *, resource_name: str, auto_warn: bool =
2626
if auto_warn and missing:
2727
_log.warning(f"Partial {resource_name}: missing federation components: {missing!r}.")
2828
return missing
29+
30+
31+
def get_federation_backends(data: dict) -> Union[List[str], None]:
32+
"""
33+
Get "federation:backends" field from response data, if present.
34+
:param data: response data
35+
:return:
36+
"""
37+
backends = data.get("federation:backends", None)
38+
return backends

openeo/rest/models/general.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,3 +263,39 @@ def ext_federation_missing(self, *, auto_warn: bool = False) -> Union[None, List
263263
return federation_extension.get_federation_missing(
264264
data=self._data, resource_name="log listing", auto_warn=auto_warn
265265
)
266+
267+
268+
class ValidationResponse(list):
269+
"""
270+
Container for process metadata listing received
271+
from a ``POST /validation`` request.
272+
273+
.. note::
274+
This object mimics, for backward compatibility reasons,
275+
the interface of simple list of validation error dictionaries (``List[dict]``),
276+
:py:meth:`~openeo.rest.connection.Connection.validate_process_graph()`,
277+
but now also provides methods/properties to access additional response data.
278+
279+
:param response_data: response data from a ``POST /validation`` request
280+
281+
.. seealso:: :py:meth:`openeo.rest.connection.Connection.validate_process_graph()`
282+
283+
.. versionadded:: 0.38.0
284+
"""
285+
286+
__slots__ = ["_data"]
287+
288+
def __init__(self, response_data: dict):
289+
self._data = response_data
290+
# Mimic original list of validation error dictionaries
291+
super().__init__(response_data["errors"])
292+
293+
def ext_federation_backends(self) -> Union[None, List[str]]:
294+
"""
295+
Get "federation:backends" value from validation response.
296+
297+
.. seealso:: :ref:`federation-extension`
298+
299+
.. warning:: this API is experimental and subject to change.
300+
"""
301+
return federation_extension.get_federation_backends(data=self._data)

tests/rest/test_connection.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4597,3 +4597,40 @@ def test_web_editor(requests_mock):
45974597
con = Connection(API_URL)
45984598
assert con.web_editor() == "https://editor.openeo.org/?server=https%3A%2F%2Foeo.test%2F"
45994599
assert con.web_editor(anonymous=True) == "https://editor.openeo.org/?server=https%3A%2F%2Foeo.test%2F&discover=1"
4600+
4601+
4602+
def test_validate_process_graph(con120, dummy_backend):
4603+
dummy_backend.next_validation_errors = [{"code": "OddSupport", "message": "Odd values are not supported."}]
4604+
cube = con120.load_collection("S2")
4605+
res = con120.validate_process_graph(cube)
4606+
assert res == [{"code": "OddSupport", "message": "Odd values are not supported."}]
4607+
4608+
4609+
@pytest.mark.parametrize(
4610+
["validation_response", "expected_errors", "expected_backends"],
4611+
[
4612+
(
4613+
{"errors": []},
4614+
[],
4615+
None,
4616+
),
4617+
(
4618+
{"errors": [], "federation:backends": ["oeoa", "oeob"]},
4619+
[],
4620+
["oeoa", "oeob"],
4621+
),
4622+
(
4623+
{"errors": [{"code": "Nope", "message": "Nope!"}], "federation:backends": ["oeoa", "oeob"]},
4624+
[{"code": "Nope", "message": "Nope!"}],
4625+
["oeoa", "oeob"],
4626+
),
4627+
],
4628+
)
4629+
def test_validate_process_graph_extra_metadata(
4630+
con120, dummy_backend, validation_response, expected_errors, expected_backends
4631+
):
4632+
dummy_backend.next_validation_errors = validation_response
4633+
cube = con120.load_collection("S2")
4634+
res = con120.validate_process_graph(cube)
4635+
assert res == expected_errors
4636+
assert res.ext_federation_backends() == expected_backends

0 commit comments

Comments
 (0)