Skip to content
This repository was archived by the owner on Nov 19, 2024. It is now read-only.

Commit dc81b96

Browse files
authored
Add remote datetimes (#95)
* add remote datetimes * fix datetimes * fix tests * invalidate cache
1 parent 4639ea9 commit dc81b96

File tree

5 files changed

+74
-51
lines changed

5 files changed

+74
-51
lines changed

cads_api_client/catalogue.py

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,33 +32,28 @@ class Collection(ApiResponse):
3232
"""A class to interact with a catalogue collection."""
3333

3434
@property
35-
def _temporal_interval(self) -> tuple[str, str]:
36-
begin, end = map(str, self.json["extent"]["temporal"]["interval"][0])
37-
return (begin, end)
38-
39-
@property
40-
def begin_datetime(self) -> datetime.datetime:
35+
def begin_datetime(self) -> datetime.datetime | None:
4136
"""Begin datetime of the collection.
4237
4338
Returns
4439
-------
45-
datetime.datetime
40+
datetime.datetime or None
4641
"""
47-
return datetime.datetime.fromisoformat(
48-
self._temporal_interval[0].replace("Z", "+00:00")
49-
)
42+
if (value := self.json["extent"]["temporal"]["interval"][0][0]) is None:
43+
return value
44+
return datetime.datetime.fromisoformat(value.replace("Z", "+00:00"))
5045

5146
@property
52-
def end_datetime(self) -> datetime.datetime:
47+
def end_datetime(self) -> datetime.datetime | None:
5348
"""End datetime of the collection.
5449
5550
Returns
5651
-------
57-
datetime.datetime
52+
datetime.datetime or None
5853
"""
59-
return datetime.datetime.fromisoformat(
60-
self._temporal_interval[1].replace("Z", "+00:00")
61-
)
54+
if (value := self.json["extent"]["temporal"]["interval"][0][1]) is None:
55+
return value
56+
return datetime.datetime.fromisoformat(value.replace("Z", "+00:00"))
6257

6358
@property
6459
def bbox(self) -> tuple[float, float, float, float]:

cads_api_client/processing.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import datetime
34
import functools
45
import logging
56
import os
@@ -447,8 +448,39 @@ def status(self) -> str:
447448
"""
448449
reply = self.json
449450
self._log_metadata(reply.get("metadata", {}))
450-
status: str = reply["status"]
451-
return status
451+
return str(reply["status"])
452+
453+
@property
454+
def creation_datetime(self) -> datetime.datetime:
455+
"""Creation datetime of the job.
456+
457+
Returns
458+
-------
459+
datetime.datetime
460+
"""
461+
return datetime.datetime.fromisoformat(self.json["created"])
462+
463+
@property
464+
def start_datetime(self) -> datetime.datetime | None:
465+
"""Start datetime of the job. If None, job has not started.
466+
467+
Returns
468+
-------
469+
datetime.datetime or None
470+
"""
471+
value = self.json.get("started")
472+
return value if value is None else datetime.datetime.fromisoformat(value)
473+
474+
@property
475+
def end_datetime(self) -> datetime.datetime | None:
476+
"""End datetime of the job. If None, job has not finished.
477+
478+
Returns
479+
-------
480+
datetime.datetime or None
481+
"""
482+
value = self.json.get("finished")
483+
return value if value is None else datetime.datetime.fromisoformat(value)
452484

453485
def _wait_on_results(self) -> None:
454486
sleep = 1.0

tests/integration_test_10_catalogue.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,12 @@ def test_catalogue_collection_submit(collection: Collection) -> None:
4949

5050

5151
def test_catalogue_collection_begin_datetime(collection: Collection) -> None:
52+
assert collection.begin_datetime is not None
5253
assert collection.begin_datetime.isoformat() == "1959-01-01T00:00:00+00:00"
5354

5455

5556
def test_catalogue_collection_end_datetime(collection: Collection) -> None:
57+
assert collection.end_datetime is not None
5658
assert collection.end_datetime.isoformat() == "2023-05-09T00:00:00+00:00"
5759

5860

tests/integration_test_30_remote.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import contextlib
2+
import datetime
23
import os
34
import pathlib
45
import uuid
@@ -86,3 +87,18 @@ def test_remote_cleanup(
8687
client = ApiClient(url=api_root_url, key=api_anon_key, maximum_tries=0)
8788
with raises:
8889
client.get_remote(request_uid)
90+
91+
92+
def test_remote_datetimes(api_anon_client: ApiClient) -> None:
93+
remote = api_anon_client.submit(
94+
"test-adaptor-dummy",
95+
elapsed=1,
96+
_timestamp=datetime.datetime.now().isoformat(),
97+
)
98+
assert isinstance(remote.creation_datetime, datetime.datetime)
99+
assert remote.end_datetime is None
100+
101+
remote.make_results()
102+
assert remote.start_datetime is not None
103+
assert remote.end_datetime is not None
104+
assert remote.creation_datetime < remote.start_datetime < remote.end_datetime

tests/test_10_processing.py

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from cads_api_client import catalogue, processing
1010

1111
COLLECTION_ID = "reanalysis-era5-pressure-levels"
12-
JOB_RUNNING_ID = "9bfc1362-2832-48e1-a235-359267420bb1"
1312
JOB_SUCCESSFUL_ID = "9bfc1362-2832-48e1-a235-359267420bb2"
1413
JOB_FAILED_ID = "9bfc1362-2832-48e1-a235-359267420bb3"
1514

@@ -21,13 +20,9 @@
2120
PROCESS_URL = f"http://localhost:8080/api/retrieve/v1/processes/{COLLECTION_ID}"
2221
EXECUTE_URL = f"{PROCESS_URL}/execution"
2322

24-
JOB_RUNNING_URL = f"http://localhost:8080/api/retrieve/v1/jobs/{JOB_RUNNING_ID}"
2523
JOB_SUCCESSFUL_URL = f"http://localhost:8080/api/retrieve/v1/jobs/{JOB_SUCCESSFUL_ID}"
2624
JOB_FAILED_URL = f"http://localhost:8080/api/retrieve/v1/jobs/{JOB_FAILED_ID}"
2725

28-
RESULT_RUNNING_URL = (
29-
f"http://localhost:8080/api/retrieve/v1/jobs/{JOB_RUNNING_ID}/results"
30-
)
3126
RESULT_SUCCESSFUL_URL = (
3227
f"http://localhost:8080/api/retrieve/v1/jobs/{JOB_SUCCESSFUL_ID}/results"
3328
)
@@ -178,28 +173,6 @@
178173
},
179174
}
180175

181-
JOB_RUNNING_JSON = {
182-
"processID": f"{COLLECTION_ID}",
183-
"type": "process",
184-
"jobID": f"{JOB_RUNNING_ID}",
185-
"status": "running",
186-
"created": "2022-09-02T17:30:48.201213",
187-
"updated": "2022-09-02T17:30:48.201217",
188-
"links": [
189-
{
190-
"href": f"{COLLECTION_URL}/execution",
191-
"rel": "self",
192-
"type": "application/json",
193-
},
194-
{
195-
"href": f"{JOB_RUNNING_URL}",
196-
"rel": "monitor",
197-
"type": "application/json",
198-
"title": "job status info",
199-
},
200-
],
201-
}
202-
203176

204177
JOB_SUCCESSFUL_JSON = {
205178
"processID": f"{COLLECTION_ID}",
@@ -279,13 +252,6 @@
279252
}
280253

281254

282-
RESULT_RUNNING_JSON = {
283-
"type": "http://www.opengis.net/def/exceptions/ogcapi-processes-1/1.0/result-not-ready",
284-
"title": "job results not ready",
285-
"detail": "job 8b7a1f3d-04b1-425d-96f1-f0634d02ee7f results are not yet ready",
286-
"instance": "http://127.0.0.1:8080/api/retrieve/v1/jobs/8b7a1f3d-04b1-425d-96f1-f0634d02ee7f/results",
287-
}
288-
289255
RESULT_FAILED_JSON = {
290256
"type": "job results failed",
291257
"title": "job failed",
@@ -413,6 +379,12 @@ def test_submit(cat: catalogue.Catalogue) -> None:
413379
assert remote.url == JOB_SUCCESSFUL_URL
414380
assert remote.status == "successful"
415381

382+
assert remote.creation_datetime.isoformat() == "2022-09-02T17:30:48.201213"
383+
assert remote.start_datetime is not None
384+
assert remote.start_datetime.isoformat() == "2022-09-02T17:32:43.890617"
385+
assert remote.end_datetime is not None
386+
assert remote.end_datetime.isoformat() == "2022-09-02T17:32:54.308120"
387+
416388

417389
@responses.activate
418390
def test_wait_on_result(cat: catalogue.Catalogue) -> None:
@@ -435,6 +407,12 @@ def test_wait_on_result_failed(cat: catalogue.Catalogue) -> None:
435407
):
436408
remote._wait_on_results()
437409

410+
assert remote.creation_datetime.isoformat() == "2022-09-02T17:30:48.201213"
411+
assert remote.start_datetime is not None
412+
assert remote.start_datetime.isoformat() == "2022-09-02T17:32:43.890617"
413+
assert remote.end_datetime is not None
414+
assert remote.end_datetime.isoformat() == "2022-09-02T17:32:54.308120"
415+
438416

439417
@responses.activate
440418
def test_remote_logs(

0 commit comments

Comments
 (0)