Skip to content

Commit 76bac3b

Browse files
committed
Issue #677 introduce limit argument in Connection.list_jobs()
1 parent 179a852 commit 76bac3b

File tree

3 files changed

+42
-9
lines changed

3 files changed

+42
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- Automatically use `load_url` when providing a URL as geometries to `DataCube.aggregate_spatial()`, `DataCube.mask_polygon()`, etc. ([#104](https://github.com/Open-EO/openeo-python-client/issues/104), [#457](https://github.com/Open-EO/openeo-python-client/issues/457))
13+
- Allow specifying `limit` when listing batch jobs with `Connection.list_jobs()` ([#677](https://github.com/Open-EO/openeo-python-client/issues/677))
1314

1415
### Changed
1516

openeo/rest/connection.py

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ def request(
147147
method: str,
148148
path: str,
149149
*,
150+
params: Optional[dict] = None,
150151
headers: Optional[dict] = None,
151152
auth: Optional[AuthBase] = None,
152153
check_error: bool = True,
@@ -159,13 +160,21 @@ def request(
159160
auth = auth or (self.auth if not self._is_external(url) else None)
160161
slow_response_threshold = kwargs.pop("slow_response_threshold", self.slow_response_threshold)
161162
if _log.isEnabledFor(logging.DEBUG):
162-
_log.debug("Request `{m} {u}` with headers {h}, auth {a}, kwargs {k}".format(
163-
m=method.upper(), u=url, h=headers and headers.keys(), a=type(auth).__name__, k=list(kwargs.keys()))
163+
_log.debug(
164+
"Request `{m} {u}` with params {p}, headers {h}, auth {a}, kwargs {k}".format(
165+
m=method.upper(),
166+
u=url,
167+
p=params,
168+
h=headers and headers.keys(),
169+
a=type(auth).__name__,
170+
k=list(kwargs.keys()),
171+
)
164172
)
165173
with ContextTimer() as timer:
166174
resp = self.session.request(
167175
method=method,
168176
url=url,
177+
params=params,
169178
headers=self._merged_headers(headers),
170179
auth=auth,
171180
timeout=kwargs.pop("timeout", self.default_timeout),
@@ -227,16 +236,25 @@ def _raise_api_error(self, response: requests.Response):
227236

228237
raise OpenEoApiPlainError(message=text, http_status_code=status_code, error_message=error_message)
229238

230-
def get(self, path: str, stream: bool = False, auth: Optional[AuthBase] = None, **kwargs) -> Response:
239+
def get(
240+
self,
241+
path: str,
242+
*,
243+
params: Optional[dict] = None,
244+
stream: bool = False,
245+
auth: Optional[AuthBase] = None,
246+
**kwargs,
247+
) -> Response:
231248
"""
232249
Do GET request to REST API.
233250
234251
:param path: API path (without root url)
252+
:param params: Additional query parameters
235253
:param stream: True if the get request should be streamed, else False
236254
:param auth: optional custom authentication to use instead of the default one
237255
:return: response: Response
238256
"""
239-
return self.request("get", path=path, stream=stream, auth=auth, **kwargs)
257+
return self.request("get", path=path, params=params, stream=stream, auth=auth, **kwargs)
240258

241259
def post(self, path: str, json: Optional[dict] = None, **kwargs) -> Response:
242260
"""
@@ -1047,18 +1065,24 @@ def describe_process(self, id: str, namespace: Optional[str] = None) -> dict:
10471065

10481066
raise OpenEoClientException("Process does not exist.")
10491067

1050-
def list_jobs(self) -> List[dict]:
1068+
def list_jobs(self, limit: Union[int, None] = None) -> List[dict]:
10511069
"""
10521070
Lists all jobs of the authenticated user.
10531071
1072+
:param limit: maximum number of jobs to return. Setting this limit enables pagination.
1073+
10541074
:return: job_list: Dict of all jobs of the user.
1075+
1076+
.. versionadded:: 0.36.0
1077+
Added ``limit`` argument
10551078
"""
1056-
# TODO: Parse the result so that there get Job classes returned?
1057-
resp = self.get('/jobs', expected_status=200).json()
1079+
# TODO: Parse the result so that Job classes returned?
1080+
resp = self.get("/jobs", params={"limit": limit}, expected_status=200).json()
10581081
if resp.get("federation:missing"):
10591082
_log.warning("Partial user job listing due to missing federation components: {c}".format(
10601083
c=",".join(resp["federation:missing"])
10611084
))
1085+
# TODO: when pagination is enabled: how to expose link to next page?
10621086
jobs = resp["jobs"]
10631087
return VisualList("data-table", data=jobs, parameters={'columns': 'jobs'})
10641088

tests/rest/test_job.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,14 @@ def download_tiff(request, context):
687687
assert f.read() == TIFF_CONTENT
688688

689689

690-
def test_list_jobs(con100, requests_mock):
690+
@pytest.mark.parametrize(
691+
["list_jobs_kwargs", "expected_qs"],
692+
[
693+
({}, {}),
694+
({"limit": 123}, {"limit": ["123"]}),
695+
],
696+
)
697+
def test_list_jobs(con100, requests_mock, list_jobs_kwargs, expected_qs):
691698
username = "john"
692699
password = "j0hn!"
693700
access_token = "6cc35!"
@@ -700,6 +707,7 @@ def test_list_jobs(con100, requests_mock):
700707

701708
def get_jobs(request, context):
702709
assert request.headers["Authorization"] == f"Bearer basic//{access_token}"
710+
assert request.qs == expected_qs
703711
return {
704712
"jobs": [
705713
{
@@ -718,7 +726,7 @@ def get_jobs(request, context):
718726
requests_mock.get(API_URL + "/jobs", json=get_jobs)
719727

720728
con100.authenticate_basic(username, password)
721-
jobs = con100.list_jobs()
729+
jobs = con100.list_jobs(**list_jobs_kwargs)
722730
assert jobs == [
723731
{"id": "job123", "status": "running", "created": "2021-02-22T09:00:00Z"},
724732
{"id": "job456", "status": "created", "created": "2021-03-22T10:00:00Z"},

0 commit comments

Comments
 (0)