Skip to content

Commit bae921a

Browse files
committed
PR #727 also check main description
1 parent 6be5813 commit bae921a

File tree

6 files changed

+113
-47
lines changed

6 files changed

+113
-47
lines changed

openeo/internal/documentation.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import re
88
import textwrap
99
from functools import partial
10-
from typing import Callable, Dict, Optional, Tuple, TypeVar, Union
10+
from typing import Callable, Dict, List, Optional, Sequence, Tuple, TypeVar, Union
1111

1212
# TODO: give this a proper public API?
1313
_process_registry = collections.defaultdict(list)
@@ -61,7 +61,7 @@ def decorate(f: Callable) -> Callable:
6161
return decorate
6262

6363

64-
def _get_doc(obj: Union[str, Callable]) -> str:
64+
def get_docstring(obj: Union[str, Callable]) -> str:
6565
"""
6666
Get docstring of a method or function.
6767
"""
@@ -76,7 +76,7 @@ def extract_params(doc: Union[str, Callable]) -> Dict[str, str]:
7676
"""
7777
Extract parameters (``:param name:`` format) from a docstring.
7878
"""
79-
doc = _get_doc(doc)
79+
doc = get_docstring(doc)
8080
params_regex = re.compile(r"^:param\s+(?P<param>\w+)\s*:(?P<doc>.*(\n +.*)*)", re.MULTILINE)
8181
return {m.group("param"): m.group("doc").strip() for m in params_regex.finditer(doc)}
8282

@@ -85,12 +85,27 @@ def extract_return(doc: Union[str, Callable]) -> Union[str, None]:
8585
"""
8686
Extract return value description (``:return:`` format) from a docstring.
8787
"""
88-
doc = _get_doc(doc)
88+
doc = get_docstring(doc)
8989
return_regex = re.compile(r"^:return\s*:(?P<doc>.*(\n +.*)*)", re.MULTILINE)
9090
matches = [m.group("doc").strip() for m in return_regex.finditer(doc)]
9191
assert 0 <= len(matches) <= 1
9292
return matches[0] if matches else None
9393

94+
95+
def extract_main_description(doc: Union[str, Callable]) -> List[str]:
96+
"""
97+
Extract main description from a docstring:
98+
paragraphs before the params/returns description.
99+
"""
100+
paragraphs = []
101+
for part in re.split(r"\s*\n(?:\s*\n)+", get_docstring(doc)):
102+
if re.match(r"\s*:", part):
103+
break
104+
paragraphs.append(part.strip("\n"))
105+
assert len(paragraphs) > 0
106+
return paragraphs
107+
108+
94109
def assert_same_param_docs(doc_a: Union[str, Callable], doc_b: Union[str, Callable], only_intersection: bool = False):
95110
"""
96111
Compare parameters (``:param name:`` format) from two docstrings.
@@ -112,3 +127,17 @@ def assert_same_return_docs(doc_a: Union[str, Callable], doc_b: Union[str, Calla
112127
Compare return value descriptions from two docstrings.
113128
"""
114129
assert extract_return(doc_a) == extract_return(doc_b)
130+
131+
132+
def assert_same_main_description(doc_a: Union[str, Callable], doc_b: Union[str, Callable], ignore: Sequence[str] = ()):
133+
"""
134+
Compare main description from two docstrings.
135+
"""
136+
description_a = extract_main_description(doc_a)
137+
description_b = extract_main_description(doc_b)
138+
139+
for s in ignore:
140+
description_a = [p.replace(s, "<IGNORED>") for p in description_a]
141+
description_b = [p.replace(s, "<IGNORED>") for p in description_b]
142+
143+
assert description_a == description_b

openeo/rest/connection.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,9 +1559,11 @@ def download(
15591559
job_options: Optional[dict] = None,
15601560
) -> Union[None, bytes]:
15611561
"""
1562-
Downloads the result of a process graph synchronously,
1563-
and save the result to the given file or return bytes object if no outputfile is specified.
1564-
This method is useful to export binary content such as images. For json content, the execute method is recommended.
1562+
Send the underlying process graph to the backend
1563+
for synchronous processing and directly download the result.
1564+
1565+
If ``outputfile`` is provided, the result is downloaded to that path.
1566+
Otherwise a :py:class:`bytes` object is returned with the raw data.
15651567
15661568
:param graph: (flat) dict representing a process graph, or process graph as raw JSON string,
15671569
or as local file path or URL
@@ -1574,8 +1576,9 @@ def download(
15741576
:param job_options: (optional) dictionary of job options to pass to the backend
15751577
(under top-level property "job_options")
15761578
1577-
:return: ``None`` if ``outputfile`` was specified to store to disk.
1578-
Otherwise, a :py:class:`bytes` object containing the raw data.
1579+
:return: if ``outputfile`` was not specified:
1580+
a :py:class:`bytes` object containing the raw data.
1581+
Otherwise, ``None`` is returned.
15791582
15801583
.. versionadded:: 0.36.0
15811584
Added arguments ``additional`` and ``job_options``.
@@ -1663,7 +1666,14 @@ def create_job(
16631666
log_level: Optional[str] = None,
16641667
) -> BatchJob:
16651668
"""
1666-
Create a new job from given process graph on the back-end.
1669+
Send the underlying process graph to the backend
1670+
to create an openEO batch job
1671+
and return a corresponding :py:class:`~openeo.rest.job.BatchJob` instance.
1672+
1673+
Note that this method only *creates* the openEO batch job at the backend,
1674+
but it does not *start* it.
1675+
Use :py:meth:`execute_batch` instead to let the openEO Python client
1676+
take care of the full job life cycle: create, start and track its progress until completion.
16671677
16681678
:param process_graph: openEO-style (flat) process graph representation,
16691679
or an object that can be converted to such a representation:

openeo/rest/datacube.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2384,10 +2384,11 @@ def download(
23842384
job_options: Optional[dict] = None,
23852385
) -> Union[None, bytes]:
23862386
"""
2387-
Execute synchronously and download the raster data cube, e.g. as GeoTIFF.
2387+
Send the underlying process graph to the backend
2388+
for synchronous processing and directly download the result.
23882389
2389-
If outputfile is provided, the result is stored on disk locally, otherwise, a bytes object is returned.
2390-
The bytes object can be passed on to a suitable decoder for decoding.
2390+
If ``outputfile`` is provided, the result is downloaded to that path.
2391+
Otherwise a :py:class:`bytes` object is returned with the raw data.
23912392
23922393
:param outputfile: (optional) output path to download to.
23932394
:param format: (optional) an output format supported by the backend.
@@ -2399,8 +2400,9 @@ def download(
23992400
:param job_options: (optional) dictionary of job options to pass to the backend
24002401
(under top-level property "job_options")
24012402
2402-
:return: ``None`` if ``outputfile`` was specified to store to disk.
2403-
Otherwise, a :py:class:`bytes` object containing the raw data.
2403+
:return: if ``outputfile`` was not specified:
2404+
a :py:class:`bytes` object containing the raw data.
2405+
Otherwise, ``None`` is returned.
24042406
24052407
.. versionchanged:: 0.32.0
24062408
Added ``auto_add_save_result`` option

openeo/rest/stac_resource.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,11 @@ def download(
6969
job_options: Optional[dict] = None,
7070
):
7171
"""
72-
Execute synchronously and download the result (cube).
72+
Send the underlying process graph to the backend
73+
for synchronous processing and directly download the result.
7374
74-
If outputfile is provided, the result is stored on disk locally, otherwise, a bytes object is returned.
75-
The bytes object can be passed on to a suitable decoder for decoding.
75+
If ``outputfile`` is provided, the result is downloaded to that path.
76+
Otherwise a :py:class:`bytes` object is returned with the raw data.
7677
7778
:param outputfile: (optional) output path to download to.
7879
:param validate: (optional) toggle to enable/prevent validation of the process graphs before execution
@@ -81,8 +82,9 @@ def download(
8182
:param job_options: (optional) dictionary of job options to pass to the backend
8283
(under top-level property "job_options")
8384
84-
:return: ``None`` if ``outputfile`` was specified to store to disk.
85-
Otherwise, a :py:class:`bytes` object containing the raw data.
85+
:return: if ``outputfile`` was not specified:
86+
a :py:class:`bytes` object containing the raw data.
87+
Otherwise, ``None`` is returned.
8688
"""
8789
return self._connection.download(
8890
graph=self.flat_graph(),

openeo/rest/vectorcube.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,11 @@ def download(
245245
job_options: Optional[dict] = None,
246246
) -> Union[None, bytes]:
247247
"""
248-
Execute synchronously and download the vector cube.
248+
Send the underlying process graph to the backend
249+
for synchronous processing and directly download the result.
249250
250-
The result will be stored to the output path, when specified.
251-
If no output path (or ``None``) is given, the raw download content will be returned as ``bytes`` object.
251+
If ``outputfile`` is provided, the result is downloaded to that path.
252+
Otherwise a :py:class:`bytes` object is returned with the raw data.
252253
253254
:param outputfile: (optional) output path to download to.
254255
:param format: (optional) an output format supported by the backend.
@@ -260,8 +261,9 @@ def download(
260261
:param job_options: (optional) dictionary of job options to pass to the backend
261262
(under top-level property "job_options")
262263
263-
:return: ``None`` if ``outputfile`` was specified to store to disk.
264-
Otherwise, a :py:class:`bytes` object containing the raw data.
264+
:return: if ``outputfile`` was not specified:
265+
a :py:class:`bytes` object containing the raw data.
266+
Otherwise, ``None`` is returned.
265267
266268
.. versionchanged:: 0.21.0
267269
When not specified explicitly, output format is guessed from output file extension.

tests/internal/test_documentation.py

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,44 @@
44

55
from openeo import BatchJob, Connection, DataCube, VectorCube
66
from openeo.internal.documentation import (
7+
assert_same_main_description,
78
assert_same_param_docs,
89
assert_same_return_docs,
10+
extract_main_description,
911
extract_params,
1012
extract_return,
1113
)
1214
from openeo.rest.mlmodel import MlModel
1315
from openeo.rest.stac_resource import StacResource
1416

17+
DOCBLOCK1 = """
18+
The description
1519
16-
def test_extract_params():
17-
doc = """
18-
The description
20+
and more
21+
22+
:param a: description of a
23+
:param b_b : multi-line description
24+
of b
1925
20-
and more
26+
:return: the result
27+
of the operation
2128
22-
:param a: description of a
23-
:param b_b : multi-line description
24-
of b
29+
That's it!
30+
"""
2531

26-
That's it!
27-
"""
28-
assert extract_params(doc) == {
32+
def test_extract_params():
33+
assert extract_params(DOCBLOCK1) == {
2934
"a": "description of a",
3035
"b_b": "multi-line description\n of b",
3136
}
3237

3338

3439
def test_extract_return():
35-
doc = """
36-
The description
37-
38-
and more
40+
assert extract_return(DOCBLOCK1) == "the result\n of the operation"
3941

40-
:param a: description of a
4142

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"
43+
def test_extract_main_description():
44+
assert extract_main_description(DOCBLOCK1) == ["The description", "and more"]
4945

5046

5147
@pytest.mark.parametrize(
@@ -84,3 +80,28 @@ def test_cube_processing_params_and_return(method_a, method_b):
8480

8581
if signature_a.return_annotation == signature_b.return_annotation:
8682
assert_same_return_docs(method_a, method_b)
83+
84+
85+
@pytest.mark.parametrize(
86+
["method_a", "method_b"],
87+
[
88+
# Connection vs DataCube
89+
(Connection.download, DataCube.download),
90+
(Connection.create_job, DataCube.create_job),
91+
# DataCube vs VectorCube
92+
(DataCube.download, VectorCube.download),
93+
(DataCube.create_job, VectorCube.create_job),
94+
(DataCube.execute_batch, VectorCube.execute_batch),
95+
(DataCube.save_result, VectorCube.save_result),
96+
# DataCube vs MlModel
97+
(DataCube.create_job, MlModel.create_job),
98+
(DataCube.execute_batch, MlModel.execute_batch),
99+
# DataCube vs StacResource
100+
(DataCube.download, StacResource.download),
101+
(DataCube.create_job, StacResource.create_job),
102+
(DataCube.execute_batch, StacResource.execute_batch),
103+
],
104+
)
105+
def test_cube_processing_description(method_a, method_b):
106+
"""Check main description of cube download/execute related methods"""
107+
assert_same_main_description(method_a, method_b)

0 commit comments

Comments
 (0)