Skip to content

Commit eeebf63

Browse files
committed
Handle runtime plugins in bulk converter
The summary_to_bulk would fail if any runtime plugins are configured in the ert configuration. This was revealed when testing the tooling on Drogon. This change will load the ErtConfig with respect to runtime plugins such that the workflow does not fail.
1 parent 62b0035 commit eeebf63

3 files changed

Lines changed: 55 additions & 11 deletions

File tree

src/ert/observation_converters/dispatcher.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
from __future__ import annotations
2+
13
from collections.abc import Callable
24
from enum import StrEnum
3-
from typing import Any
45

56
from ert.cli.main import ErtCliError
67
from ert.namespace import Namespace
8+
from ert.plugins import ErtRuntimePlugins
79

810
from .history_to_summary import convert_history_to_summary
911
from .summary_to_bulk import (
@@ -16,15 +18,13 @@ class SupportedFormat(StrEnum):
1618
BULK = "bulk"
1719

1820

19-
ConverterFunction = Callable[[str], None]
20-
21-
_SUPPORTED_CONVERSIONS: dict[SupportedFormat, ConverterFunction] = {
21+
_SUPPORTED_CONVERSIONS: dict[SupportedFormat, Callable[..., None]] = {
2222
SupportedFormat.BULK: convert_summary_to_bulk,
2323
SupportedFormat.SUMMARY: convert_history_to_summary,
2424
}
2525

2626

27-
def convert_observations(args: Namespace, _site_plugins: Any | None = None) -> None:
27+
def convert_observations(args: Namespace, site_plugins: ErtRuntimePlugins) -> None:
2828
converter_func = _SUPPORTED_CONVERSIONS.get(args.format)
2929

3030
if converter_func is None:
@@ -35,4 +35,4 @@ def convert_observations(args: Namespace, _site_plugins: Any | None = None) -> N
3535
f"{supported_formats}"
3636
)
3737

38-
converter_func(args.config)
38+
converter_func(args.config, site_plugins)

src/ert/observation_converters/summary_to_bulk.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
from collections import defaultdict
24
from dataclasses import fields
35
from pathlib import Path
@@ -14,6 +16,7 @@
1416
make_summary_key_data,
1517
)
1618
from ert.config._shapes import CircleShapeConfig
19+
from ert.plugins import ErtRuntimePlugins
1720

1821
INDENT2 = " " * 2
1922
INDENT4 = " " * 4
@@ -221,8 +224,9 @@ def print_bulk_config(
221224
)
222225

223226

224-
def convert_summary_to_bulk(config: str) -> None:
225-
ert_config = ErtConfig.from_file(config)
227+
def convert_summary_to_bulk(config: str, runtime_plugins: ErtRuntimePlugins) -> None:
228+
ert_config = ErtConfig.with_plugins(runtime_plugins).from_file(config)
229+
226230
if any(
227231
obs.type == "summary_observation" for obs in ert_config.observation_declarations
228232
):

tests/ert/unit_tests/cli/test_summary_to_bulk.py

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
BulkConfigConverter,
1818
_breakthrough_to_string,
1919
)
20+
from ert.plugins import ErtRuntimePlugins, get_site_plugins
2021

2122

2223
@pytest.mark.usefixtures("snake_oil_case")
@@ -28,7 +29,7 @@ def test_that_happy_path_on_snake_oil_produces_csv_and_stdout(capsys):
2829
stdout and moving the csv file into the observations folder.
2930
"""
3031
args = MagicMock(format="bulk", config="snake_oil.ert")
31-
convert_observations(args)
32+
convert_observations(args, ErtRuntimePlugins())
3233

3334
assert Path("summary_observations.csv").is_file()
3435
csv_content = Path("summary_observations.csv").read_text(encoding="utf-8")
@@ -349,7 +350,7 @@ def test_that_combination_of_precisions_is_maintained_in_csv_conversion(
349350
def test_that_invalid_format_raises_cli_error():
350351
args = MagicMock(format="Foo")
351352
with pytest.raises(ErtCliError):
352-
convert_observations(args)
353+
convert_observations(args, site_plugins=ErtRuntimePlugins())
353354

354355

355356
def test_that_breakthrough_to_string_strips_hour_minute_second_from_date_precision():
@@ -395,4 +396,43 @@ def test_that_no_summary_observations_raises_ert_cli_error():
395396
)
396397
args = MagicMock(format="bulk", config="snake_oil.ert")
397398
with pytest.raises(ErtCliError, match="No summary observations found"):
398-
convert_observations(args)
399+
convert_observations(args, ErtRuntimePlugins())
400+
401+
402+
def test_that_convert_observations_does_not_fail_when_config_has_hooked_workflows(
403+
use_tmpdir,
404+
):
405+
"""This reproduces the case where ErtConfig.from_file() is called without
406+
plugins while hooked workflows reference plugin-provided jobs.
407+
"""
408+
site_plugins = get_site_plugins()
409+
410+
arbitrary_existing_job = next(iter(site_plugins.installed_workflow_jobs))
411+
412+
workflow_file = Path("my_hook_workflow")
413+
workflow_file.write_text(f"{arbitrary_existing_job}\n", encoding="utf-8")
414+
415+
obs_config = "foo"
416+
summary_obs = (
417+
"SUMMARY_OBSERVATION { KEY = FOPR; VALUE = 10; ERROR = 5; DATE = 2000-01-01; };"
418+
)
419+
Path(obs_config).write_text(
420+
summary_obs,
421+
encoding="utf-8",
422+
)
423+
424+
ert_config = "config.ert"
425+
minimal_workflow_config = f"""\
426+
NUM_REALIZATIONS 10
427+
ECLBASE foo
428+
OBS_CONFIG {obs_config}
429+
LOAD_WORKFLOW {workflow_file} MY_HOOK
430+
HOOK_WORKFLOW MY_HOOK PRE_SIMULATION
431+
"""
432+
Path(ert_config).write_text(
433+
minimal_workflow_config,
434+
encoding="utf-8",
435+
)
436+
437+
args = MagicMock(format="bulk", config=ert_config)
438+
convert_observations(args, site_plugins)

0 commit comments

Comments
 (0)