Skip to content

Commit 6be5813

Browse files
committed
PR #727 also check return description
and involve Connection and BatchJob
1 parent 1cd9b1d commit 6be5813

File tree

8 files changed

+120
-53
lines changed

8 files changed

+120
-53
lines changed

openeo/internal/documentation.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ def extract_params(doc: Union[str, Callable]) -> Dict[str, str]:
8181
return {m.group("param"): m.group("doc").strip() for m in params_regex.finditer(doc)}
8282

8383

84+
def extract_return(doc: Union[str, Callable]) -> Union[str, None]:
85+
"""
86+
Extract return value description (``:return:`` format) from a docstring.
87+
"""
88+
doc = _get_doc(doc)
89+
return_regex = re.compile(r"^:return\s*:(?P<doc>.*(\n +.*)*)", re.MULTILINE)
90+
matches = [m.group("doc").strip() for m in return_regex.finditer(doc)]
91+
assert 0 <= len(matches) <= 1
92+
return matches[0] if matches else None
93+
8494
def assert_same_param_docs(doc_a: Union[str, Callable], doc_b: Union[str, Callable], only_intersection: bool = False):
8595
"""
8696
Compare parameters (``:param name:`` format) from two docstrings.
@@ -95,3 +105,10 @@ def assert_same_param_docs(doc_a: Union[str, Callable], doc_b: Union[str, Callab
95105
params_b = {k: v for k, v in params_b.items() if k in intersection}
96106

97107
assert params_a == params_b
108+
109+
110+
def assert_same_return_docs(doc_a: Union[str, Callable], doc_b: Union[str, Callable]):
111+
"""
112+
Compare return value descriptions from two docstrings.
113+
"""
114+
assert extract_return(doc_a) == extract_return(doc_b)

openeo/rest/connection.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,15 +1565,18 @@ def download(
15651565
15661566
:param graph: (flat) dict representing a process graph, or process graph as raw JSON string,
15671567
or as local file path or URL
1568-
:param outputfile: output file
1568+
:param outputfile: (optional) output path to download to.
15691569
:param timeout: timeout to wait for response
1570-
:param validate: Optional toggle to enable/prevent validation of the process graphs before execution
1570+
:param validate: (optional) toggle to enable/prevent validation of the process graphs before execution
15711571
(overruling the connection's ``auto_validate`` setting).
15721572
:param chunk_size: chunk size for streaming response.
1573-
:param additional: additional (top-level) properties to set in the request body
1574-
:param job_options: dictionary of job options to pass to the backend
1573+
:param additional: (optional) additional (top-level) properties to set in the request body
1574+
:param job_options: (optional) dictionary of job options to pass to the backend
15751575
(under top-level property "job_options")
15761576
1577+
:return: ``None`` if ``outputfile`` was specified to store to disk.
1578+
Otherwise, a :py:class:`bytes` object containing the raw data.
1579+
15771580
.. versionadded:: 0.36.0
15781581
Added arguments ``additional`` and ``job_options``.
15791582
"""
@@ -1595,6 +1598,7 @@ def download(
15951598
with target.open(mode="wb") as f:
15961599
for chunk in response.iter_content(chunk_size=chunk_size):
15971600
f.write(chunk)
1601+
# TODO: return target path instead of None? Or return a generic result wrapper?
15981602
else:
15991603
return response.content
16001604

@@ -1667,19 +1671,20 @@ def create_job(
16671671
a string with a JSON representation,
16681672
a local file path or URL to a JSON representation,
16691673
a :py:class:`~openeo.rest.multiresult.MultiResult` object, ...
1670-
:param title: job title
1671-
:param description: job description
1672-
:param plan: The billing plan to process and charge the job with
1673-
:param budget: Maximum budget to be spent on executing the job.
1674+
:param title: (optional) job title.
1675+
:param description: (optional) job description.
1676+
:param plan: (optional) the billing plan to process and charge the job with.
1677+
:param budget: (optional) maximum budget to be spent on executing the job.
16741678
Note that some backends do not honor this limit.
1675-
:param additional: additional (top-level) properties to set in the request body
1676-
:param job_options: dictionary of job options to pass to the backend
1679+
:param additional: (optional) additional (top-level) properties to set in the request body
1680+
:param job_options: (optional) dictionary of job options to pass to the backend
16771681
(under top-level property "job_options")
1678-
:param validate: Optional toggle to enable/prevent validation of the process graphs before execution
1682+
:param validate: (optional) toggle to enable/prevent validation of the process graphs before execution
16791683
(overruling the connection's ``auto_validate`` setting).
1680-
:param log_level: Optional minimum severity level for log entries that the back-end should keep track of.
1684+
:param log_level: (optional) minimum severity level for log entries that the back-end should keep track of.
16811685
One of "error" (highest severity), "warning", "info", and "debug" (lowest severity).
1682-
:return: Created job
1686+
1687+
:return: Handle to the job created at the backend.
16831688
16841689
.. versionchanged:: 0.35.0
16851690
Add :ref:`multi-result support <multi-result-process-graphs>`.

openeo/rest/datacube.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2399,7 +2399,8 @@ def download(
23992399
:param job_options: (optional) dictionary of job options to pass to the backend
24002400
(under top-level property "job_options")
24012401
2402-
:return: None if the result is stored to disk, or a bytes object returned by the backend.
2402+
:return: ``None`` if ``outputfile`` was specified to store to disk.
2403+
Otherwise, a :py:class:`bytes` object containing the raw data.
24032404
24042405
.. versionchanged:: 0.32.0
24052406
Added ``auto_add_save_result`` option
@@ -2564,6 +2565,8 @@ def execute_batch(
25642565
:param connection_retry_interval: how long to wait when status poll failed due to connection issue
25652566
:param print: print/logging function to show progress/status
25662567
2568+
:return: Handle to the job created at the backend.
2569+
25672570
.. versionchanged:: 0.32.0
25682571
Added ``auto_add_save_result`` option
25692572
@@ -2648,7 +2651,7 @@ def create_job(
26482651
:param log_level: (optional) minimum severity level for log entries that the back-end should keep track of.
26492652
One of "error" (highest severity), "warning", "info", and "debug" (lowest severity).
26502653
2651-
:return: Handle for the job created at the backend.
2654+
:return: Handle to the job created at the backend.
26522655
26532656
.. versionchanged:: 0.32.0
26542657
Added ``auto_add_save_result`` option

openeo/rest/job.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,14 @@ def run_synchronous(
233233
"""
234234
Start the job, wait for it to finish and download result
235235
236-
:param outputfile: The path of a file to which a result can be written
236+
:param outputfile: (optional) output path to download to.
237237
:param print: print/logging function to show progress/status
238238
:param max_poll_interval: maximum number of seconds to sleep between job status polls
239239
:param connection_retry_interval: how long to wait when status poll failed due to connection issue
240240
:param show_error_logs: whether to automatically print error logs when the batch job failed.
241241
242+
:return: Handle to the job created at the backend.
243+
242244
.. versionchanged:: 0.37.0
243245
Added argument ``show_error_logs``.
244246
"""

openeo/rest/mlmodel.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ def execute_batch(
111111
:param connection_retry_interval: how long to wait when status poll failed due to connection issue
112112
:param print: print/logging function to show progress/status
113113
114+
:return: Handle to the job created at the backend.
115+
114116
.. versionchanged:: 0.36.0
115117
Added argument ``additional``.
116118
@@ -170,7 +172,8 @@ def create_job(
170172
(under top-level property "job_options")
171173
:param log_level: (optional) minimum severity level for log entries that the back-end should keep track of.
172174
One of "error" (highest severity), "warning", "info", and "debug" (lowest severity).
173-
:return: Created job.
175+
176+
:return: Handle to the job created at the backend.
174177
175178
.. versionchanged:: 0.36.0
176179
Added argument ``additional``.

openeo/rest/stac_resource.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ def download(
8181
:param job_options: (optional) dictionary of job options to pass to the backend
8282
(under top-level property "job_options")
8383
84-
:return: None if the result is stored to disk, or a bytes object returned by the backend.
84+
:return: ``None`` if ``outputfile`` was specified to store to disk.
85+
Otherwise, a :py:class:`bytes` object containing the raw data.
8586
"""
8687
return self._connection.download(
8788
graph=self.flat_graph(),
@@ -126,7 +127,7 @@ def create_job(
126127
:param log_level: (optional) minimum severity level for log entries that the back-end should keep track of.
127128
One of "error" (highest severity), "warning", "info", and "debug" (lowest severity).
128129
129-
:return: Handle for the job created at the backend.
130+
:return: Handle to the job created at the backend.
130131
"""
131132
return self._connection.create_job(
132133
process_graph=self.flat_graph(),
@@ -192,6 +193,7 @@ def execute_batch(
192193
:param connection_retry_interval: how long to wait when status poll failed due to connection issue
193194
:param show_error_logs: whether to automatically print error logs when the batch job failed.
194195
196+
:return: Handle to the job created at the backend.
195197
"""
196198
job = self.create_job(
197199
title=title,

openeo/rest/vectorcube.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ def download(
260260
:param job_options: (optional) dictionary of job options to pass to the backend
261261
(under top-level property "job_options")
262262
263+
:return: ``None`` if ``outputfile`` was specified to store to disk.
264+
Otherwise, a :py:class:`bytes` object containing the raw data.
265+
263266
.. versionchanged:: 0.21.0
264267
When not specified explicitly, output format is guessed from output file extension.
265268
@@ -336,6 +339,8 @@ def execute_batch(
336339
:param connection_retry_interval: how long to wait when status poll failed due to connection issue
337340
:param print: print/logging function to show progress/status
338341
342+
:return: Handle to the job created at the backend.
343+
339344
.. versionchanged:: 0.21.0
340345
When not specified explicitly, output format is guessed from output file extension.
341346
@@ -418,7 +423,7 @@ def create_job(
418423
:param log_level: (optional) minimum severity level for log entries that the back-end should keep track of.
419424
One of "error" (highest severity), "warning", "info", and "debug" (lowest severity).
420425
421-
:return: Created job.
426+
:return: Handle to the job created at the backend.
422427
423428
.. versionchanged:: 0.32.0
424429
Added ``auto_add_save_result`` option
Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,86 @@
1+
import inspect
2+
13
import pytest
24

3-
from openeo import DataCube, VectorCube
4-
from openeo.internal.documentation import assert_same_param_docs, extract_params
5+
from openeo import BatchJob, Connection, DataCube, VectorCube
6+
from openeo.internal.documentation import (
7+
assert_same_param_docs,
8+
assert_same_return_docs,
9+
extract_params,
10+
extract_return,
11+
)
512
from openeo.rest.mlmodel import MlModel
613
from openeo.rest.stac_resource import StacResource
714

815

916
def test_extract_params():
10-
assert (
11-
extract_params(
12-
"""
13-
The description
17+
doc = """
18+
The description
19+
20+
and more
21+
22+
:param a: description of a
23+
:param b_b : multi-line description
24+
of b
25+
26+
That's it!
27+
"""
28+
assert extract_params(doc) == {
29+
"a": "description of a",
30+
"b_b": "multi-line description\n of b",
31+
}
1432

15-
and more
1633

17-
:param a: description of a
18-
:param b_b : multi-line description
19-
of b
34+
def test_extract_return():
35+
doc = """
36+
The description
2037
21-
That's it!
22-
"""
23-
)
24-
== {
25-
"a": "description of a",
26-
"b_b": "multi-line description\n of b",
27-
}
28-
)
38+
and more
2939
40+
:param a: description of a
3041
42+
:return: the result
43+
of the operation
44+
45+
That's it!
46+
"""
47+
48+
assert extract_return(doc) == "the result\n of the operation"
3149

3250

3351
@pytest.mark.parametrize(
34-
["method_a", "method_b", "only_intersection"],
52+
["method_a", "method_b"],
3553
[
54+
# Connection vs DataCube
55+
(Connection.download, DataCube.download),
56+
(Connection.create_job, DataCube.create_job),
3657
# Compare DataCube methods internally
37-
(DataCube.download, DataCube.create_job, True),
38-
(DataCube.download, DataCube.execute_batch, True),
39-
(DataCube.create_job, DataCube.execute_batch, True),
58+
(DataCube.download, DataCube.create_job),
59+
(DataCube.download, DataCube.execute_batch),
60+
(DataCube.create_job, DataCube.execute_batch),
61+
# DataCube vs BatchJob
62+
(BatchJob.run_synchronous, DataCube.execute_batch),
4063
# DataCube vs VectorCube
41-
(DataCube.download, VectorCube.download, False),
42-
(DataCube.create_job, VectorCube.create_job, False),
43-
(DataCube.execute_batch, VectorCube.execute_batch, False),
44-
(DataCube.save_result, VectorCube.save_result, False),
64+
(DataCube.download, VectorCube.download),
65+
(DataCube.create_job, VectorCube.create_job),
66+
(DataCube.execute_batch, VectorCube.execute_batch),
67+
(DataCube.save_result, VectorCube.save_result),
4568
# DataCube vs MlModel
46-
(DataCube.create_job, MlModel.create_job, True),
47-
(DataCube.execute_batch, MlModel.execute_batch, True),
69+
(DataCube.create_job, MlModel.create_job),
70+
(DataCube.execute_batch, MlModel.execute_batch),
4871
# DataCube vs StacResource
49-
(DataCube.download, StacResource.download, True),
50-
(DataCube.create_job, StacResource.create_job, True),
51-
(DataCube.execute_batch, StacResource.execute_batch, True),
72+
(DataCube.download, StacResource.download),
73+
(DataCube.create_job, StacResource.create_job),
74+
(DataCube.execute_batch, StacResource.execute_batch),
5275
],
5376
)
54-
def test_compare_download_execute_params(method_a, method_b, only_intersection):
77+
def test_cube_processing_params_and_return(method_a, method_b):
78+
"""Check params/return of cube download/execute related methods"""
79+
signature_a = inspect.signature(method_a)
80+
signature_b = inspect.signature(method_b)
81+
82+
only_intersection = set(signature_a.parameters.keys()) != set(signature_b.parameters.keys())
5583
assert_same_param_docs(method_a, method_b, only_intersection=only_intersection)
56-
# TODO: compare return description
84+
85+
if signature_a.return_annotation == signature_b.return_annotation:
86+
assert_same_return_docs(method_a, method_b)

0 commit comments

Comments
 (0)