Skip to content

Commit d545bba

Browse files
authored
Merge pull request #25 from The-Strategy-Unit/v5-fixes
v5 fixes
2 parents fa4a841 + b7ad1b6 commit d545bba

4 files changed

Lines changed: 69 additions & 17 deletions

File tree

src/nhp/aci/run_model/storage.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Methods for uploading model parameters to Azure Blob Storage."""
22

33
import logging
4+
from datetime import datetime, timezone
45
from typing import Any
56

67
from azure.core.credentials import TokenCredential
@@ -67,4 +68,10 @@ def add_table_storage_entry(
6768
"viewable": results_viewable,
6869
**metadata,
6970
}
71+
72+
# fix datatypes
73+
entity["create_datetime"] = datetime.strptime(
74+
str(entity["create_datetime"]), "%Y%m%d_%H%M%S"
75+
).replace(tzinfo=timezone.utc)
76+
7077
table_client.create_entity(entity)

src/nhp/aci/status/model_run_status.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,12 @@ def _get_progress_from_ats(
2828
try:
2929
entity = table_client.get_entity(partition_key=dataset, row_key=model_run_id)
3030

31-
res = {
31+
return {
32+
"status": entity.get("status", "unknown"),
3233
"complete": json.loads(entity.get("progress", "{}")),
3334
"model_runs": entity["model_runs"],
34-
"container_group_name": None,
35+
"container_group_name": entity.get("container_group_name", None),
3536
}
36-
status = entity.get("status")
37-
38-
if status == "complete":
39-
res["status"] = "complete"
40-
else:
41-
res["container_group_name"] = entity.get("container_group_name", None)
42-
43-
return res
4437
except ResourceNotFoundError:
4538
return {}
4639

@@ -84,12 +77,14 @@ def get_model_run_status(
8477
if not status:
8578
return None
8679

87-
container_group_name = status.pop("container_group_name")
88-
if not container_group_name:
80+
if status["status"] == "complete":
8981
return status
9082

83+
if status["container_group_name"] is None:
84+
return {**status, "state": "Creating"}
85+
9186
try:
92-
return {**status, **_get_aci_status(container_group_name, credential, config)}
87+
return {**status, **_get_aci_status(status["container_group_name"], credential, config)}
9388

9489
except ResourceNotFoundError:
9590
return {**status, "state": "Creating"}

tests/unit/nhp/aci/run_model/test_run_model_storage.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Test the storage module in the nhp.aci.run_model package."""
22

3+
from datetime import datetime, timezone
4+
35
from azure.core.exceptions import ResourceExistsError
46

57
from nhp.aci.run_model.storage import add_table_storage_entry, upload_params_to_blob
@@ -78,6 +80,7 @@ def test_add_table_storage_entry(mocker, config):
7880
"scenario": "scenario",
7981
"app_version": "v5.0",
8082
"model_run_id": "model-run-id",
83+
"create_datetime": "20260518_120000",
8184
}
8285

8386
# act
@@ -95,6 +98,8 @@ def test_add_table_storage_entry(mocker, config):
9598
"modelruns",
9699
credential="credential",
97100
)
101+
102+
metadata["create_datetime"] = datetime(2026, 5, 18, 12, 0, tzinfo=timezone.utc) # ty: ignore[invalid-assignment]
98103
m_table_client().create_entity.assert_called_once_with(
99104
{
100105
"PartitionKey": "dataset",

tests/unit/nhp/aci/status/test_status_model_run_status.py

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ def test__get_progress_from_ats(mocker, config):
2727

2828
# assert
2929
assert actual == {
30+
"status": "running",
3031
"complete": {"inpatients": 100, "outpatients": 50, "aae": 0},
31-
"model_runs": 100,
3232
"container_group_name": "name",
33+
"model_runs": 100,
3334
}
3435

3536
m_tc.assert_called_once_with(
@@ -108,6 +109,7 @@ def test_get_model_run_status(mocker, config):
108109
m_gpa = mocker.patch(
109110
"nhp.aci.status.model_run_status._get_progress_from_ats",
110111
return_value={
112+
"status": "running",
111113
"complete": {"inpatients": 100, "outpatients": 50, "aae": 0},
112114
"model_runs": 100,
113115
"container_group_name": "name",
@@ -122,8 +124,10 @@ def test_get_model_run_status(mocker, config):
122124

123125
# assert
124126
assert actual == {
127+
"status": "running",
125128
"complete": {"inpatients": 100, "outpatients": 50, "aae": 0},
126129
"model_runs": 100,
130+
"container_group_name": "name",
127131
"state": "running",
128132
}
129133
m_gpa.assert_called_once_with("dataset", "id", "credential", config)
@@ -145,6 +149,7 @@ def test_get_model_run_status_creates_credential_and_config_if_none(mocker, conf
145149
m_gpa = mocker.patch(
146150
"nhp.aci.status.model_run_status._get_progress_from_ats",
147151
return_value={
152+
"status": "running",
148153
"complete": {"inpatients": 100, "outpatients": 50, "aae": 0},
149154
"model_runs": 100,
150155
"container_group_name": "name",
@@ -159,8 +164,10 @@ def test_get_model_run_status_creates_credential_and_config_if_none(mocker, conf
159164

160165
# assert
161166
assert actual == {
167+
"status": "running",
162168
"complete": {"inpatients": 100, "outpatients": 50, "aae": 0},
163169
"model_runs": 100,
170+
"container_group_name": "name",
164171
"state": "running",
165172
}
166173
m_gpa.assert_called_once_with("dataset", "id", "credential", config)
@@ -175,6 +182,7 @@ def test_get_model_run_status_resource_not_found_with_status(mocker, config):
175182
mocker.patch(
176183
"nhp.aci.status.model_run_status._get_progress_from_ats",
177184
return_value={
185+
"status": "running",
178186
"complete": {"inpatients": 100, "outpatients": 50, "aae": 0},
179187
"model_runs": 100,
180188
"container_group_name": "name",
@@ -195,8 +203,46 @@ def test_get_model_run_status_resource_not_found_with_status(mocker, config):
195203

196204
# assert
197205
assert actual == {
206+
"status": "running",
207+
"complete": {"inpatients": 100, "outpatients": 50, "aae": 0},
208+
"model_runs": 100,
209+
"container_group_name": "name",
210+
"state": "Creating",
211+
}
212+
213+
214+
def test_get_model_run_status_returns_progress_without_aci_when_no_container_group_name(
215+
mocker, config
216+
):
217+
# arrange
218+
mocker.patch(
219+
"nhp.aci.status.model_run_status._get_progress_from_ats",
220+
return_value={
221+
"status": "running",
222+
"complete": {"inpatients": 100, "outpatients": 50, "aae": 0},
223+
"model_runs": 100,
224+
"container_group_name": None,
225+
},
226+
)
227+
mocker.patch(
228+
"nhp.aci.status.model_run_status._get_aci_status",
229+
side_effect=ResourceNotFoundError("Not Found"),
230+
)
231+
232+
# act
233+
actual = get_model_run_status(
234+
"dataset",
235+
"id",
236+
"credential", # ty: ignore[invalid-argument-type]
237+
config,
238+
)
239+
240+
# assert
241+
assert actual == {
242+
"status": "running",
198243
"complete": {"inpatients": 100, "outpatients": 50, "aae": 0},
199244
"model_runs": 100,
245+
"container_group_name": None,
200246
"state": "Creating",
201247
}
202248

@@ -224,9 +270,7 @@ def test_get_model_run_status_resource_not_found_without_status(mocker, config):
224270
assert actual is None
225271

226272

227-
def test_get_model_run_status_returns_progress_without_aci_when_no_container_group_name(
228-
mocker, config
229-
):
273+
def test_get_model_run_status_returns_progress_without_aci_when_complete(mocker, config):
230274
# arrange
231275
m_gas = mocker.patch("nhp.aci.status.model_run_status._get_aci_status")
232276
mocker.patch(
@@ -251,6 +295,7 @@ def test_get_model_run_status_returns_progress_without_aci_when_no_container_gro
251295
assert actual == {
252296
"complete": {"inpatients": 100, "outpatients": 50, "aae": 0},
253297
"model_runs": 100,
298+
"container_group_name": None,
254299
"status": "complete",
255300
}
256301
m_gas.assert_not_called()

0 commit comments

Comments
 (0)