Skip to content

Commit 4ea0af3

Browse files
Yngve S. Kristiansenyngve-sk
authored andcommitted
Migrate error type in error.json file
RealizationStorageState IntEnum to StrEnum (cherry picked from commit 72a6ffb)
1 parent 1259a25 commit 4ea0af3

3 files changed

Lines changed: 170 additions & 1 deletion

File tree

src/ert/storage/local_storage.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
logger = logging.getLogger(__name__)
3232

33-
_LOCAL_STORAGE_VERSION = 16
33+
_LOCAL_STORAGE_VERSION = 17
3434

3535

3636
class _Migrations(BaseModel):
@@ -498,6 +498,7 @@ def _migrate(self, version: int) -> None:
498498
to14,
499499
to15,
500500
to16,
501+
to17,
501502
)
502503

503504
try:
@@ -543,6 +544,7 @@ def _migrate(self, version: int) -> None:
543544
13: to14,
544545
14: to15,
545546
15: to16,
547+
16: to17,
546548
}
547549
for from_version in range(version, _LOCAL_STORAGE_VERSION):
548550
migrations[from_version].migrate(self.path)

src/ert/storage/migration/to17.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import json
2+
from pathlib import Path
3+
from typing import Any
4+
5+
info = "Migrate realization error type from IntEnum to StrEnum"
6+
7+
8+
def migrate_realization_errors_json_content(
9+
error_json: dict[str, Any],
10+
) -> dict[str, Any]:
11+
int_to_str = {
12+
1: "undefined",
13+
2: "parameters_loaded",
14+
4: "responses_loaded",
15+
8: "failure_in_current",
16+
16: "failure_in_parent",
17+
}
18+
return error_json | {"type": int_to_str[error_json["type"]]}
19+
20+
21+
def migrate_realization_errors(path: Path) -> None:
22+
for realization_error in path.glob("ensembles/*/realization-*/error.json"):
23+
old_error_json_content = json.loads(
24+
realization_error.read_text(encoding="utf-8")
25+
)
26+
realization_error.write_text(
27+
json.dumps(
28+
migrate_realization_errors_json_content(old_error_json_content),
29+
indent=2,
30+
)
31+
)
32+
33+
34+
def migrate(path: Path) -> None:
35+
migrate_realization_errors(path)
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# test_migrate.py
2+
import json
3+
from datetime import datetime
4+
from pathlib import Path
5+
6+
from ert.storage.migration.to17 import (
7+
migrate,
8+
migrate_realization_errors_json_content,
9+
)
10+
11+
12+
def test_add_experiment_status_to_index_json():
13+
input_json = {
14+
"type": 8,
15+
"message": "An error occurred.",
16+
"time": datetime.now().isoformat(),
17+
}
18+
19+
expected_output = {
20+
"type": "failure_in_current",
21+
"message": "An error occurred.",
22+
"time": input_json["time"],
23+
}
24+
25+
result = migrate_realization_errors_json_content(input_json)
26+
assert migrate_realization_errors_json_content(input_json) == expected_output, (
27+
f"Expected {expected_output}, got {result}"
28+
)
29+
30+
31+
def test_that_realization_storage_state_is_converted_to_strenum_for_all_reals(
32+
use_tmpdir,
33+
):
34+
ensembles = ["ensemble_1", "ensemble_2", "ensemble_3"]
35+
36+
for ensemble in ensembles:
37+
ensemble_path = Path(f"ensembles/{ensemble}")
38+
ensemble_path.mkdir(parents=True, exist_ok=True)
39+
40+
for realization, _error_int, _error_str in [
41+
(0, 1, "undefined"),
42+
(1, 2, "parameters_loaded"),
43+
(2, 4, "responses_loaded"),
44+
(3, 8, "failure_in_current"),
45+
(4, 16, "failure_in_parent"),
46+
]:
47+
real_dir = ensemble_path / f"realization-{realization}"
48+
real_dir.mkdir()
49+
(real_dir / "error.json").write_text(
50+
json.dumps(
51+
{
52+
"type": _error_int,
53+
"message": f"Realization {realization} in {ensemble} failed.",
54+
"time": datetime.now().isoformat(),
55+
}
56+
),
57+
encoding="utf-8",
58+
)
59+
60+
migrate(Path("."))
61+
62+
for ensemble in ensembles:
63+
ensemble_path = Path(f"ensembles/{ensemble}")
64+
for realization, _error_int, _error_str in [
65+
(0, 1, "undefined"),
66+
(1, 2, "parameters_loaded"),
67+
(2, 4, "responses_loaded"),
68+
(3, 8, "failure_in_current"),
69+
(4, 16, "failure_in_parent"),
70+
]:
71+
error_file = ensemble_path / f"realization-{realization}/error.json"
72+
contents = json.loads(error_file.read_text(encoding="utf-8"))
73+
assert contents["type"] == _error_str
74+
75+
76+
def test_realizations_with_missing_error_json(use_tmpdir):
77+
ensembles = ["ensemble_1", "ensemble_2", "ensemble_3"]
78+
79+
missing_files = {
80+
"ensemble_1": [1, 3],
81+
"ensemble_2": [0, 4],
82+
"ensemble_3": [2, 3],
83+
}
84+
85+
for ensemble in ensembles:
86+
ensemble_path = Path(f"ensembles/{ensemble}")
87+
ensemble_path.mkdir(parents=True, exist_ok=True)
88+
89+
for realization, _error_int, _error_str in [
90+
(0, 1, "undefined"),
91+
(1, 2, "parameters_loaded"),
92+
(2, 4, "responses_loaded"),
93+
(3, 8, "failure_in_current"),
94+
(4, 16, "failure_in_parent"),
95+
]:
96+
real_dir = ensemble_path / f"realization-{realization}"
97+
real_dir.mkdir()
98+
error_file = real_dir / "error.json"
99+
error_file.write_text(
100+
json.dumps(
101+
{
102+
"type": _error_int,
103+
"message": f"Realization {realization} in {ensemble} failed.",
104+
"time": datetime.now().isoformat(),
105+
}
106+
),
107+
encoding="utf-8",
108+
)
109+
110+
for missing_real in missing_files[ensemble]:
111+
missing_file = ensemble_path / f"realization-{missing_real}/error.json"
112+
if missing_file.exists():
113+
missing_file.unlink()
114+
115+
migrate(Path("."))
116+
117+
for ensemble in ensembles:
118+
ensemble_path = Path(f"ensembles/{ensemble}")
119+
for realization, _error_int, _error_str in [
120+
(0, 1, "undefined"),
121+
(1, 2, "parameters_loaded"),
122+
(2, 4, "responses_loaded"),
123+
(3, 8, "failure_in_current"),
124+
(4, 16, "failure_in_parent"),
125+
]:
126+
error_file = ensemble_path / f"realization-{realization}/error.json"
127+
128+
if realization in missing_files[ensemble]:
129+
assert not error_file.exists()
130+
else:
131+
contents = json.loads(error_file.read_text(encoding="utf-8"))
132+
assert contents["type"] == _error_str

0 commit comments

Comments
 (0)