model-config-tests 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/PKG-INFO +1 -1
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/pyproject.toml +3 -1
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/_version.py +3 -3
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/config_tests/qa/test_access_om2_config.py +1 -1
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/config_tests/test_bit_reproducibility.py +33 -26
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/exp_test_helper.py +42 -16
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests.egg-info/PKG-INFO +1 -1
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/tests/test_exp_test_helper.py +72 -6
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/LICENSE +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/README.md +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/setup.cfg +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/setup.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/__init__.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/cmds/compare_exp_tests_cmd.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/cmds/config_tests_cmd.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/compare_exp_tests/conftest.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/compare_exp_tests/test_repro.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/config_tests/conftest.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/config_tests/qa/test_access_esm1p5_config.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/config_tests/qa/test_access_esm1p6_config.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/config_tests/qa/test_access_om3_config.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/config_tests/qa/test_config.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/__init__.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/accessesm1p5.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/accessesm1p6.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/accessom2.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/accessom3.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/model.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/mom5.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/um7.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/util.py +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests.egg-info/SOURCES.txt +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests.egg-info/dependency_links.txt +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests.egg-info/entry_points.txt +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests.egg-info/requires.txt +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests.egg-info/top_level.txt +0 -0
- {model_config_tests-0.2.2 → model_config_tests-0.2.3}/tests/test_util.py +0 -0
|
@@ -112,6 +112,8 @@ tag_prefix = "v"
|
|
|
112
112
|
parentdir_prefix = "model_config_tests-"
|
|
113
113
|
|
|
114
114
|
[tool.coverage.run]
|
|
115
|
+
patch = ["subprocess"]
|
|
115
116
|
omit = [
|
|
116
|
-
"
|
|
117
|
+
"*/model_config_tests/_version.py",
|
|
118
|
+
"src/model_config_tests/_version.py",
|
|
117
119
|
]
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2025-
|
|
11
|
+
"date": "2025-12-19T17:08:47+1100",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "0.2.
|
|
14
|
+
"full-revisionid": "31685c167c305b26642a22f00796dec7d8725551",
|
|
15
|
+
"version": "0.2.3"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -116,7 +116,7 @@ class TestAccessOM2:
|
|
|
116
116
|
|
|
117
117
|
def test_mppncombine_fast_collate_exe(self, config, branch):
|
|
118
118
|
if branch.is_high_resolution:
|
|
119
|
-
pattern = r"
|
|
119
|
+
pattern = r".*mppnccombine-fast"
|
|
120
120
|
if "collate" in config:
|
|
121
121
|
assert re.match(
|
|
122
122
|
pattern, config["collate"]["exe"]
|
|
@@ -9,7 +9,7 @@ from typing import Optional
|
|
|
9
9
|
|
|
10
10
|
import pytest
|
|
11
11
|
|
|
12
|
-
from model_config_tests.exp_test_helper import Experiments
|
|
12
|
+
from model_config_tests.exp_test_helper import Experiments, ExpTestHelper
|
|
13
13
|
from model_config_tests.util import DAY_IN_SECONDS, HOUR_IN_SECONDS
|
|
14
14
|
|
|
15
15
|
# Names of shared experiments
|
|
@@ -147,6 +147,20 @@ def experiments(
|
|
|
147
147
|
return _experiments(experiments_markers, output_path, control_path, keep_archive)
|
|
148
148
|
|
|
149
149
|
|
|
150
|
+
@pytest.fixture
|
|
151
|
+
def requested_experiments(request, experiments: Experiments):
|
|
152
|
+
"""Fixture to check that requested experiments have run successfully
|
|
153
|
+
and return a dictionary of ExpTestHelper instances for each experiment."""
|
|
154
|
+
exp_marker = request.node.get_closest_marker("experiments").args[0]
|
|
155
|
+
requested_exps = {}
|
|
156
|
+
for exp_name in exp_marker:
|
|
157
|
+
# Check experiment has run successfully - this will raise an
|
|
158
|
+
# error if there are any non-zero exit codes in the outputs
|
|
159
|
+
experiments.check_experiment(exp_name)
|
|
160
|
+
requested_exps[exp_name] = experiments.get_experiment(exp_name)
|
|
161
|
+
return requested_exps
|
|
162
|
+
|
|
163
|
+
|
|
150
164
|
class TestBitReproducibility:
|
|
151
165
|
|
|
152
166
|
@pytest.mark.repro
|
|
@@ -160,7 +174,7 @@ class TestBitReproducibility:
|
|
|
160
174
|
self,
|
|
161
175
|
output_path: Path,
|
|
162
176
|
control_path: Path,
|
|
163
|
-
|
|
177
|
+
requested_experiments: dict[str, ExpTestHelper],
|
|
164
178
|
checksum_path: Optional[Path],
|
|
165
179
|
):
|
|
166
180
|
"""
|
|
@@ -178,9 +192,9 @@ class TestBitReproducibility:
|
|
|
178
192
|
Path to the model configuration to test. This is copied for
|
|
179
193
|
for control directories in experiments. Default is set in
|
|
180
194
|
conftests.py.
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
195
|
+
requested_experiments: dict[str, ExpTestHelper]
|
|
196
|
+
A dictionary of requested experiments, where the key is the
|
|
197
|
+
experiment name and the value is an instance of ExpTestHelper.
|
|
184
198
|
checksum_path: Optional[Path]
|
|
185
199
|
Path to checksums to compare model output against. Default is
|
|
186
200
|
set to checksums saved on model configuration. This is a
|
|
@@ -190,12 +204,7 @@ class TestBitReproducibility:
|
|
|
190
204
|
checksum_output_dir = set_checksum_output_dir(output_path=output_path)
|
|
191
205
|
|
|
192
206
|
# Use default runtime experiment to get the historical checksums
|
|
193
|
-
|
|
194
|
-
exp = experiments.get_experiment(EXP_DEFAULT_RUNTIME)
|
|
195
|
-
|
|
196
|
-
assert (
|
|
197
|
-
exp.model.output_exists()
|
|
198
|
-
), "Output file required for model checksums does not exist"
|
|
207
|
+
exp = requested_experiments.get(EXP_DEFAULT_RUNTIME)
|
|
199
208
|
|
|
200
209
|
# Set the checksum output filename using the model default runtime
|
|
201
210
|
runtime_hours = exp.model.default_runtime_seconds // HOUR_IN_SECONDS
|
|
@@ -235,20 +244,16 @@ class TestBitReproducibility:
|
|
|
235
244
|
EXP_1D_RUNTIME_REPEAT: {"n_runs": 1, "model_runtime": DAY_IN_SECONDS},
|
|
236
245
|
}
|
|
237
246
|
)
|
|
238
|
-
def test_repro_determinism(self,
|
|
247
|
+
def test_repro_determinism(self, requested_experiments: dict[str, ExpTestHelper]):
|
|
239
248
|
"""
|
|
240
249
|
Determinism test that confirms repeated model runs for 1 day
|
|
241
250
|
give the same results
|
|
242
251
|
"""
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
exp_1d_runtime_repeat = experiments.get_experiment(EXP_1D_RUNTIME_REPEAT)
|
|
252
|
+
exp_1d_runtime = requested_experiments.get(EXP_1D_RUNTIME)
|
|
253
|
+
exp_1d_runtime_repeat = requested_experiments.get(EXP_1D_RUNTIME_REPEAT)
|
|
246
254
|
|
|
247
255
|
# Compare expected to produced.
|
|
248
|
-
assert exp_1d_runtime.model.output_exists()
|
|
249
256
|
expected = exp_1d_runtime.extract_checksums()
|
|
250
|
-
|
|
251
|
-
assert exp_1d_runtime_repeat.model.output_exists()
|
|
252
257
|
produced = exp_1d_runtime_repeat.extract_checksums()
|
|
253
258
|
|
|
254
259
|
assert produced == expected
|
|
@@ -262,16 +267,17 @@ class TestBitReproducibility:
|
|
|
262
267
|
EXP_2D_RUNTIME: {"n_runs": 1, "model_runtime": 2 * DAY_IN_SECONDS},
|
|
263
268
|
}
|
|
264
269
|
)
|
|
265
|
-
def test_repro_restart(
|
|
270
|
+
def test_repro_restart(
|
|
271
|
+
self, output_path: Path, requested_experiments: dict[str, ExpTestHelper]
|
|
272
|
+
):
|
|
266
273
|
"""
|
|
267
274
|
Restart reproducibility test that confirms two short consecutive
|
|
268
275
|
1-day model runs give the same results as a longer single 2-day model
|
|
269
276
|
run.
|
|
270
277
|
"""
|
|
271
278
|
# Get experiments with 2x1 day and 2 day runtimes
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
exp_2d_runtime = experiments.get_experiment(EXP_2D_RUNTIME)
|
|
279
|
+
exp_1d_runtime = requested_experiments.get(EXP_1D_RUNTIME)
|
|
280
|
+
exp_2d_runtime = requested_experiments.get(EXP_2D_RUNTIME)
|
|
275
281
|
|
|
276
282
|
# Now compare the output between our two short and one long run.
|
|
277
283
|
checksums_1d_0 = exp_1d_runtime.extract_checksums()
|
|
@@ -305,14 +311,15 @@ class TestBitReproducibility:
|
|
|
305
311
|
EXP_1D_RUNTIME_REPEAT: {"n_runs": 2, "model_runtime": DAY_IN_SECONDS},
|
|
306
312
|
}
|
|
307
313
|
)
|
|
308
|
-
def test_repro_determinism_restart(
|
|
314
|
+
def test_repro_determinism_restart(
|
|
315
|
+
self, requested_experiments: dict[str, ExpTestHelper]
|
|
316
|
+
):
|
|
309
317
|
"""
|
|
310
318
|
Determinism test that confirms repeated experiments with two
|
|
311
319
|
consecutive 1-day model runs give the same results
|
|
312
320
|
"""
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
exp_1d_runtime_repeat = experiments.get_experiment(EXP_1D_RUNTIME_REPEAT)
|
|
321
|
+
exp_1d_runtime = requested_experiments.get(EXP_1D_RUNTIME)
|
|
322
|
+
exp_1d_runtime_repeat = requested_experiments.get(EXP_1D_RUNTIME_REPEAT)
|
|
316
323
|
|
|
317
324
|
# Extract checksums, using the output from the second model run
|
|
318
325
|
expected = exp_1d_runtime.extract_checksums(exp_1d_runtime.model.output_1)
|
{model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/exp_test_helper.py
RENAMED
|
@@ -136,9 +136,30 @@ class ExpTestHelper:
|
|
|
136
136
|
# Change to experiment directory and run.
|
|
137
137
|
os.chdir(self.control_path)
|
|
138
138
|
|
|
139
|
-
print("Running payu setup
|
|
140
|
-
sp.run(
|
|
141
|
-
|
|
139
|
+
print("Running payu setup")
|
|
140
|
+
result = sp.run(
|
|
141
|
+
["payu", "setup", "--lab", str(self.lab_path)],
|
|
142
|
+
capture_output=True,
|
|
143
|
+
text=True,
|
|
144
|
+
)
|
|
145
|
+
if result.returncode != 0:
|
|
146
|
+
# Add additional error messaging for debugging
|
|
147
|
+
error_msg = (
|
|
148
|
+
"Failed to run payu setup:\n"
|
|
149
|
+
f"Return code: {result.returncode}\n"
|
|
150
|
+
f"--- stdout ---\n{result.stdout}\n"
|
|
151
|
+
f"--- stderr ---\n{result.stderr}"
|
|
152
|
+
)
|
|
153
|
+
print(error_msg)
|
|
154
|
+
raise RuntimeError(error_msg)
|
|
155
|
+
|
|
156
|
+
print("Running payu sweep")
|
|
157
|
+
sp.run(
|
|
158
|
+
["payu", "sweep", "--lab", str(self.lab_path)],
|
|
159
|
+
capture_output=True,
|
|
160
|
+
text=True,
|
|
161
|
+
check=True,
|
|
162
|
+
)
|
|
142
163
|
|
|
143
164
|
run_command = ["payu", "run", "--lab", str(self.lab_path)]
|
|
144
165
|
if n_runs:
|
|
@@ -208,7 +229,7 @@ class Experiments:
|
|
|
208
229
|
self.output_path = output_path
|
|
209
230
|
self.keep_archive = keep_archive
|
|
210
231
|
self.experiments = {}
|
|
211
|
-
self.
|
|
232
|
+
self.experiment_errors = {}
|
|
212
233
|
|
|
213
234
|
def setup_and_submit(
|
|
214
235
|
self,
|
|
@@ -282,22 +303,27 @@ class Experiments:
|
|
|
282
303
|
try:
|
|
283
304
|
exp.wait_for_payu_run()
|
|
284
305
|
print(f"Experiment {exp_name} completed successfully")
|
|
285
|
-
self.successful_experiments.append(exp_name)
|
|
286
306
|
except RuntimeError as e:
|
|
307
|
+
self.experiment_errors[exp_name] = str(e)
|
|
287
308
|
if catch_errors:
|
|
288
|
-
print(f"Error
|
|
309
|
+
print(f"Error running experiment {exp_name}: {e}")
|
|
289
310
|
else:
|
|
290
|
-
raise
|
|
311
|
+
raise
|
|
291
312
|
|
|
292
|
-
def
|
|
313
|
+
def check_experiment(self, exp_name: str) -> None:
|
|
293
314
|
"""
|
|
294
|
-
Check whether given
|
|
315
|
+
Check whether given experiment name has run successfully
|
|
295
316
|
"""
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
)
|
|
317
|
+
if exp_name in self.experiment_errors:
|
|
318
|
+
raise RuntimeError(
|
|
319
|
+
f"There was an error running experiment {exp_name}:"
|
|
320
|
+
f" {self.experiment_errors[exp_name]}"
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
# Double check if the required experiment output exists
|
|
324
|
+
exp = self.experiments.get(exp_name)
|
|
325
|
+
if not exp.model.output_exists():
|
|
326
|
+
raise RuntimeError(f"Experiment {exp_name} output file does not exist.")
|
|
301
327
|
|
|
302
328
|
|
|
303
329
|
def setup_exp(
|
|
@@ -519,13 +545,13 @@ def wait_for_qsub_job(
|
|
|
519
545
|
# Check whether the run job was successful
|
|
520
546
|
exit_status = parse_exit_status_from_file(stdout)
|
|
521
547
|
if exit_status != 0:
|
|
522
|
-
|
|
548
|
+
raise RuntimeError(
|
|
549
|
+
f"Payu {job_type} job failed with exit status {exit_status}:\n"
|
|
523
550
|
f"Job_ID: {job_id}\n"
|
|
524
551
|
f"Output files: {output_files}\n"
|
|
525
552
|
f"--- stdout ---\n{stdout}\n"
|
|
526
553
|
f"--- stderr ---\n{stderr}\n"
|
|
527
554
|
)
|
|
528
|
-
raise RuntimeError(f"Payu {job_type} job failed with exit status {exit_status}")
|
|
529
555
|
|
|
530
556
|
return stdout, stderr, output_files
|
|
531
557
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import shutil
|
|
2
2
|
import subprocess
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from unittest.mock import patch
|
|
4
|
+
from unittest.mock import Mock, patch
|
|
5
5
|
|
|
6
6
|
import pytest
|
|
7
7
|
import yaml
|
|
8
8
|
from netCDF4 import Dataset
|
|
9
9
|
|
|
10
10
|
from model_config_tests.exp_test_helper import (
|
|
11
|
+
Experiments,
|
|
11
12
|
ExpTestHelper,
|
|
12
13
|
parse_exit_status_from_file,
|
|
13
14
|
parse_gadi_pbs_ids,
|
|
@@ -127,6 +128,7 @@ def test_experiment_setup_for_test_run_remove_postprocessing(exp, tmp_path):
|
|
|
127
128
|
@patch("subprocess.run")
|
|
128
129
|
def test_experiment_submit_payu_run(mock_run, exp):
|
|
129
130
|
mock_run.return_value.stdout = "1234567.gadi-pbs\nsome other output"
|
|
131
|
+
mock_run.return_value.returncode = 0
|
|
130
132
|
|
|
131
133
|
current_working_dir = Path.cwd()
|
|
132
134
|
exp.submit_payu_run()
|
|
@@ -150,6 +152,7 @@ def test_experiment_submit_payu_run(mock_run, exp):
|
|
|
150
152
|
def test_experiment_submit_payu_run_n_runs(mock_run, exp):
|
|
151
153
|
"""Test --n-runs is added to the payu run command"""
|
|
152
154
|
mock_run.return_value.stdout = "1234567.gadi-pbs\nsome other output"
|
|
155
|
+
mock_run.return_value.returncode = 0
|
|
153
156
|
|
|
154
157
|
exp.submit_payu_run(n_runs=2)
|
|
155
158
|
|
|
@@ -172,13 +175,33 @@ def test_experiment_submit_payu_run_disabled(mock_run, exp):
|
|
|
172
175
|
assert job_id is None
|
|
173
176
|
|
|
174
177
|
|
|
178
|
+
@patch("subprocess.run")
|
|
179
|
+
def test_experiment_submit_payu_run_setup_error(mock_run, exp):
|
|
180
|
+
"""Test that an error is raised when payu setup fails"""
|
|
181
|
+
mock_run.return_value.stdout = "Some output"
|
|
182
|
+
mock_run.return_value.stderr = "Some error"
|
|
183
|
+
mock_run.return_value.returncode = 1
|
|
184
|
+
|
|
185
|
+
with pytest.raises(RuntimeError, match="Failed to run payu setup*"):
|
|
186
|
+
exp.submit_payu_run()
|
|
187
|
+
|
|
188
|
+
assert exp.run_id is None
|
|
189
|
+
|
|
190
|
+
|
|
175
191
|
@patch("subprocess.run")
|
|
176
192
|
def test_experiment_submit_payu_run_error(mock_run, exp):
|
|
177
|
-
"""Test that an
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
)
|
|
181
|
-
|
|
193
|
+
"""Test that an RuntimeError is raised with CalledProcessError"""
|
|
194
|
+
# Mock the first call to payu setup to succeed
|
|
195
|
+
# and subsequent payu command to fail
|
|
196
|
+
setup_success = Mock()
|
|
197
|
+
setup_success.stdout = "Setup successful"
|
|
198
|
+
setup_success.returncode = 0
|
|
199
|
+
mock_run.side_effect = [
|
|
200
|
+
setup_success,
|
|
201
|
+
subprocess.CalledProcessError(
|
|
202
|
+
returncode=1, cmd="payu run", output="Some error"
|
|
203
|
+
),
|
|
204
|
+
]
|
|
182
205
|
|
|
183
206
|
with pytest.raises(RuntimeError, match="Failed to submit payu run.*"):
|
|
184
207
|
exp.submit_payu_run()
|
|
@@ -490,3 +513,46 @@ def test_extract_checksums_split_uses_first_tile(exp_with_restarts):
|
|
|
490
513
|
|
|
491
514
|
checksums = exp_accessom3.extract_checksums(output_directory=exp_accessom3.output_0)
|
|
492
515
|
assert checksums["output"]["DTBT"][0] == "AC87F8AC28BD1436"
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def test_experiments_check_experiment_error(tmp_path):
|
|
519
|
+
with patch("model_config_tests.exp_test_helper.setup_exp") as mock_setup_exp:
|
|
520
|
+
# Create an experiment that will error later on
|
|
521
|
+
mock_error_exp = Mock(autospec=ExpTestHelper)
|
|
522
|
+
mock_setup_exp.return_value = mock_error_exp
|
|
523
|
+
mock_error_exp.wait_for_payu_run.side_effect = RuntimeError(
|
|
524
|
+
"Payu run job failed with exit status 1"
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
exps = Experiments(
|
|
528
|
+
control_path=tmp_path / "control",
|
|
529
|
+
output_path=tmp_path / "output",
|
|
530
|
+
keep_archive=True,
|
|
531
|
+
)
|
|
532
|
+
exps.setup_and_submit(exp_name="error_exp")
|
|
533
|
+
assert exps.experiments["error_exp"] == mock_error_exp
|
|
534
|
+
|
|
535
|
+
# Add a second experiment that will succeed
|
|
536
|
+
mock_success_exp = Mock(autospec=ExpTestHelper)
|
|
537
|
+
mock_success_exp.wait_for_payu_run.return_value = None
|
|
538
|
+
mock_setup_exp.return_value = mock_success_exp
|
|
539
|
+
|
|
540
|
+
exps.setup_and_submit(exp_name="success_exp")
|
|
541
|
+
assert exps.experiments["success_exp"] == mock_success_exp
|
|
542
|
+
|
|
543
|
+
# Check no errors are raised here
|
|
544
|
+
exps.wait_for_all_experiments(catch_errors=True)
|
|
545
|
+
assert exps.experiment_errors == {
|
|
546
|
+
"error_exp": "Payu run job failed with exit status 1"
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
# Check no errors with successful experiment
|
|
550
|
+
exps.check_experiment("success_exp")
|
|
551
|
+
|
|
552
|
+
# Check error raised for the failed experiment
|
|
553
|
+
error_msg = (
|
|
554
|
+
"There was an error running experiment error_exp: "
|
|
555
|
+
"Payu run job failed with exit status 1"
|
|
556
|
+
)
|
|
557
|
+
with pytest.raises(RuntimeError, match=error_msg):
|
|
558
|
+
exps.check_experiment("error_exp")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/__init__.py
RENAMED
|
File without changes
|
{model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/accessesm1p5.py
RENAMED
|
File without changes
|
{model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/accessesm1p6.py
RENAMED
|
File without changes
|
{model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/accessom2.py
RENAMED
|
File without changes
|
{model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/accessom3.py
RENAMED
|
File without changes
|
{model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests/models/model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests.egg-info/requires.txt
RENAMED
|
File without changes
|
{model_config_tests-0.2.2 → model_config_tests-0.2.3}/src/model_config_tests.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|