Skip to content

Commit e5d7d23

Browse files
committed
MAINT: Align fmu init with fmu-settings init behavior
1 parent 1a59d06 commit e5d7d23

File tree

6 files changed

+307
-386
lines changed

6 files changed

+307
-386
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ classifiers = [
3131
dynamic = ["version"]
3232
dependencies = [
3333
"fmu-datamodels",
34-
"fmu-settings",
34+
"fmu-settings>=0.28.0",
3535
"fmu-settings-api",
3636
"fmu-settings-gui",
3737
"rich",

src/fmu_settings_cli/copy/copy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ def log_copy_event_to_target(self: Self) -> None:
577577
try:
578578
target_fmu_dir = get_fmu_directory(self.target)
579579
except FileNotFoundError:
580-
target_fmu_dir = init_fmu_directory(self.target)
580+
target_fmu_dir = init_fmu_directory(self.target, force=True)
581581
except Exception as e:
582582
error("Failed opening project fmu directory.", reason=str(e))
583583
raise typer.Exit(1) from e

src/fmu_settings_cli/init/cli.py

Lines changed: 33 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
"""The 'init' command."""
22

33
from pathlib import Path
4-
from typing import TYPE_CHECKING, Annotated, Final
4+
from typing import TYPE_CHECKING, Annotated
55

66
import typer
77
from fmu.settings._global_config import (
88
InvalidGlobalConfigurationError,
99
find_global_config,
1010
load_global_configuration_if_present,
1111
)
12-
from fmu.settings._init import init_fmu_directory
12+
from fmu.settings._init import (
13+
InvalidFMUProjectPathError,
14+
init_fmu_directory,
15+
)
1316
from pydantic import ValidationError
14-
from rich.table import Table
1517

1618
from fmu_settings_cli.prints import (
1719
error,
@@ -30,28 +32,6 @@
3032
add_completion=True,
3133
)
3234

33-
REQUIRED_FMU_PROJECT_SUBDIRS: Final[list[str]] = ["ert"]
34-
35-
36-
def is_fmu_project(path: Path) -> tuple[bool, list[str]]:
37-
"""Ensures the provided directory looks like an FMU project.
38-
39-
Args:
40-
path: The directory to check
41-
42-
Returns:
43-
Tuple of bool and list of strings, indicating whether the provided path does or
44-
does not appear to be a valid FMU project, and what directories are lacking for
45-
it to be so, respectively.
46-
"""
47-
missing: list[str] = []
48-
for dir_name in REQUIRED_FMU_PROJECT_SUBDIRS:
49-
dir_ = path / dir_name
50-
if not dir_.exists() or not dir_.is_dir():
51-
missing.append(dir_name)
52-
53-
return len(missing) == 0, missing
54-
5535

5636
def _find_global_config_source(base_path: Path) -> Path | None:
5737
"""Find which global config file would have been imported."""
@@ -83,61 +63,35 @@ def init( # noqa: PLR0912
8363
show_default=False,
8464
),
8565
] = False,
86-
skip_config_import: Annotated[
87-
bool,
88-
typer.Option(
89-
"--skip-config-import",
90-
help=(
91-
"Skip searching for and importing masterdata set in the global "
92-
"configuration or global variables."
93-
),
94-
show_default=False,
95-
),
96-
] = False,
9766
) -> None:
9867
"""The main entry point for the init command."""
9968
if ctx.invoked_subcommand is not None: # pragma: no cover
10069
return
10170

10271
cwd = Path.cwd()
10372

104-
if not force:
105-
has_all_fmu_subdirs, missing_dirs = is_fmu_project(cwd)
106-
if not has_all_fmu_subdirs:
107-
dirs_table = Table("Directory")
108-
for dir_ in missing_dirs:
109-
dirs_table.add_row(dir_)
110-
111-
error(
112-
f"This directory ({cwd}) does not appear to be an FMU project. "
113-
"Expected the following directories:",
114-
dirs_table,
115-
)
116-
raise typer.Abort
117-
11873
global_config: GlobalConfiguration | None = None
119-
if not skip_config_import:
120-
try:
121-
global_config = find_global_config(cwd)
122-
except ValidationError as e:
123-
validation_warning(
124-
e,
125-
"Unable to import masterdata.",
126-
reason="Validation of the global config/global variables failed.",
127-
suggestion=(
128-
"You will need to establish valid SMDA masterdata in FMU "
129-
"Settings by running and opening 'fmu settings'."
130-
),
131-
)
132-
except InvalidGlobalConfigurationError as e:
133-
warning(
134-
"Unable to import masterdata.",
135-
reason=str(e),
136-
suggestion=(
137-
"You will need to establish valid SMDA masterdata in FMU "
138-
"Settings by running and opening 'fmu settings'."
139-
),
140-
)
74+
try:
75+
global_config = find_global_config(cwd)
76+
except ValidationError as e:
77+
validation_warning(
78+
e,
79+
"Unable to import masterdata.",
80+
reason="Validation of the global config/global variables failed.",
81+
suggestion=(
82+
"You will need to establish valid SMDA masterdata in FMU "
83+
"Settings by running and opening 'fmu settings'."
84+
),
85+
)
86+
except InvalidGlobalConfigurationError as e:
87+
warning(
88+
"Unable to import masterdata.",
89+
reason=str(e),
90+
suggestion=(
91+
"You will need to establish valid SMDA masterdata in FMU "
92+
"Settings by running and opening 'fmu settings'."
93+
),
94+
)
14195

14296
if global_config:
14397
imported_sections = ", ".join(
@@ -153,7 +107,13 @@ def init( # noqa: PLR0912
153107
success(f"Successfully imported {imported_sections}{source_suffix}.")
154108

155109
try:
156-
fmu_dir = init_fmu_directory(cwd, global_config=global_config)
110+
fmu_dir = init_fmu_directory(cwd, global_config=global_config, force=force)
111+
except InvalidFMUProjectPathError as e:
112+
error(
113+
"Unable to create .fmu directory.",
114+
reason=str(e),
115+
)
116+
raise typer.Abort from e
157117
except FileExistsError as e:
158118
error(
159119
"Unable to create .fmu directory.",

tests/conftest.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@
2727
StratigraphyElement,
2828
)
2929
from fmu.settings import ProjectFMUDirectory
30-
from fmu.settings._init import init_fmu_directory
30+
from fmu.settings._init import REQUIRED_FMU_PROJECT_SUBDIRS, init_fmu_directory
3131
from pytest import MonkeyPatch
3232

33-
from fmu_settings_cli.init.cli import REQUIRED_FMU_PROJECT_SUBDIRS
3433
from fmu_settings_cli.settings import constants
3534

3635

tests/test_init/test_init_main.py

Lines changed: 23 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,22 @@
99
import yaml
1010
from fmu.datamodels.fmu_results.global_configuration import GlobalConfiguration
1111
from fmu.settings import find_nearest_fmu_directory
12+
from fmu.settings._init import REQUIRED_FMU_PROJECT_SUBDIRS, is_fmu_project
1213
from pydantic import ValidationError
1314
from typer.testing import CliRunner
1415

1516
from fmu_settings_cli.__main__ import app
16-
from fmu_settings_cli.init.cli import REQUIRED_FMU_PROJECT_SUBDIRS, is_fmu_project
17+
from fmu_settings_cli.init.cli import _find_global_config_source
1718

1819
runner = CliRunner()
1920

2021

2122
@pytest.mark.parametrize(
2223
"dirs, expected",
2324
[
24-
(["foo"], (False, REQUIRED_FMU_PROJECT_SUBDIRS)),
25-
(["foo/ert"], (False, REQUIRED_FMU_PROJECT_SUBDIRS)),
26-
(["ertt"], (False, REQUIRED_FMU_PROJECT_SUBDIRS)),
25+
(["foo"], (False, list(REQUIRED_FMU_PROJECT_SUBDIRS))),
26+
(["foo/ert"], (False, list(REQUIRED_FMU_PROJECT_SUBDIRS))),
27+
(["ertt"], (False, list(REQUIRED_FMU_PROJECT_SUBDIRS))),
2728
(REQUIRED_FMU_PROJECT_SUBDIRS, (True, [])),
2829
],
2930
)
@@ -48,8 +49,11 @@ def test_init_creates_user_fmu_if_exist(in_tmp_path: Path) -> None:
4849

4950
assert result.exit_code == 1
5051
stderr = " ".join(result.stderr.split())
51-
assert "does not appear to be an FMU project" in stderr
52-
assert "ert" in stderr
52+
missing_dirs = ", ".join(
53+
f"'{dir_name}'" for dir_name in REQUIRED_FMU_PROJECT_SUBDIRS
54+
)
55+
assert "Failed initializing .fmu directory." in stderr
56+
assert f"Did not find: {missing_dirs}." in stderr
5357
assert (home / ".fmu").exists()
5458

5559

@@ -58,8 +62,11 @@ def test_init_checks_if_fmu_dir_fails(in_tmp_path: Path) -> None:
5862
result = runner.invoke(app, ["init"])
5963
assert result.exit_code == 1
6064
stderr = " ".join(result.stderr.split())
61-
assert "does not appear to be an FMU project" in stderr
62-
assert "ert" in stderr
65+
missing_dirs = ", ".join(
66+
f"'{dir_name}'" for dir_name in REQUIRED_FMU_PROJECT_SUBDIRS
67+
)
68+
assert "Failed initializing .fmu directory." in stderr
69+
assert f"Did not find: {missing_dirs}." in stderr
6370

6471

6572
def test_init_checks_if_fmu_dir_passes(in_tmp_path: Path) -> None:
@@ -148,10 +155,12 @@ def test_init_adds_global_variables_with_masterdata(
148155
assert result.exit_code == 0
149156
stdout = " ".join(result.stdout.split())
150157
assert "Success: Successfully imported access, masterdata, model from" in stdout
151-
assert "fmuconfig/output/global_variables.yml" in stdout
152158
assert "Success: All done!" in stdout
153159
assert "Info: Project stratigraphy was not imported by 'fmu init'." in stdout
154160
assert "Open 'fmu settings' to import stratigraphy from RMS" in stdout
161+
assert _find_global_config_source(tmp_path) == (
162+
fmuconfig_out / "global_variables.yml"
163+
)
155164

156165
fmu_dir = find_nearest_fmu_directory()
157166
fmu_dir_cfg = fmu_dir.config.load()
@@ -180,35 +189,8 @@ def test_init_adds_input_global_config_with_masterdata(
180189
assert result.exit_code == 0
181190
stdout = " ".join(result.stdout.split())
182191
assert "Success: Successfully imported access, masterdata, model from" in stdout
183-
assert "fmuconfig/input/global_master_config.yml" in stdout
184192
assert "Success: All done!" in stdout
185-
186-
187-
def test_init_skips_adding_global_variables_with_masterdata(
188-
in_fmu_project: Path,
189-
generate_strict_valid_globalconfiguration: Callable[[], GlobalConfiguration],
190-
) -> None:
191-
"""Tests that 'fmu init' skips adding masterdata with skip flag."""
192-
tmp_path = in_fmu_project
193-
194-
valid_global_cfg = generate_strict_valid_globalconfiguration()
195-
196-
fmuconfig_out = tmp_path / "fmuconfig/output"
197-
fmuconfig_out.mkdir(parents=True, exist_ok=True)
198-
199-
(fmuconfig_out / "global_variables.yml").write_text(
200-
yaml.dump(valid_global_cfg.model_dump(mode="json", by_alias=True))
201-
)
202-
203-
result = runner.invoke(app, ["init", "--skip-config-import"])
204-
assert result.exit_code == 0
205-
assert "Success: All done!" in result.stdout
206-
207-
fmu_dir = find_nearest_fmu_directory()
208-
fmu_dir_cfg = fmu_dir.config.load()
209-
assert fmu_dir_cfg.masterdata is None
210-
assert fmu_dir_cfg.access is None
211-
assert fmu_dir_cfg.model is None
193+
assert _find_global_config_source(tmp_path) == global_config_path
212194

213195

214196
def test_init_raises_when_import_drogon_masterdata(
@@ -230,26 +212,6 @@ def test_init_raises_when_import_drogon_masterdata(
230212
assert "Reason: Invalid name in 'model': Drogon" in result.stderr
231213
assert "Success: All done!" in result.stdout
232214

233-
234-
def test_init_skips_raising_when_import_drogon_masterdata_with_skip(
235-
in_fmu_project: Path, global_variables_with_masterdata: dict[str, Any]
236-
) -> None:
237-
"""Tests that 'fmu init' skips raising on Drogon masterdata with skip flag."""
238-
tmp_path = in_fmu_project
239-
240-
fmuconfig_out = tmp_path / "fmuconfig/output"
241-
fmuconfig_out.mkdir(parents=True, exist_ok=True)
242-
243-
(fmuconfig_out / "global_variables.yml").write_text(
244-
yaml.dump(global_variables_with_masterdata)
245-
)
246-
247-
result = runner.invoke(app, ["init", "--skip-config-import"])
248-
assert result.exit_code == 0
249-
# _not_ in
250-
assert "Reason: Invalid name in 'model': Drogon" not in result.stderr
251-
assert "Success: All done!" in result.stdout
252-
253215
fmu_dir = find_nearest_fmu_directory()
254216
fmu_dir_cfg = fmu_dir.config.load()
255217
assert fmu_dir_cfg.masterdata is None
@@ -262,7 +224,7 @@ def test_init_fmu_dir_exists_error(in_fmu_project: Path) -> None:
262224
fmu_dir = in_fmu_project / ".fmu"
263225
fmu_dir.mkdir()
264226

265-
result = runner.invoke(app, ["init", "--skip-config-import"])
227+
result = runner.invoke(app, ["init"])
266228
assert result.exit_code == 1
267229
assert "Error: Unable to create .fmu directory" in result.stderr
268230
assert ".fmu already exists" in result.stderr
@@ -275,7 +237,7 @@ def test_init_fmu_dir_no_permissions_error(in_fmu_project: Path) -> None:
275237
with patch(
276238
"fmu_settings_cli.init.cli.init_fmu_directory", side_effect=PermissionError
277239
):
278-
result = runner.invoke(app, ["init", "--skip-config-import"])
240+
result = runner.invoke(app, ["init"])
279241
assert result.exit_code == 1
280242
assert "Error: Unable to create .fmu directory" in result.stderr
281243
assert "lacking permissions to create" in result.stderr
@@ -291,7 +253,7 @@ def test_init_fmu_dir_validation_error(in_fmu_project: Path) -> None:
291253
"fmu_settings_cli.init.cli.init_fmu_directory",
292254
side_effect=ValidationError("Foo", []),
293255
):
294-
result = runner.invoke(app, ["init", "--skip-config-import"])
256+
result = runner.invoke(app, ["init"])
295257
assert result.exit_code == 1
296258

297259
assert "Error: Unable to create .fmu directory" in result.stderr
@@ -304,7 +266,7 @@ def test_init_fmu_dir_some_error(in_fmu_project: Path) -> None:
304266
"fmu_settings_cli.init.cli.init_fmu_directory",
305267
side_effect=ValueError("Foo"),
306268
):
307-
result = runner.invoke(app, ["init", "--skip-config-import"])
269+
result = runner.invoke(app, ["init"])
308270
assert result.exit_code == 1
309271

310272
assert "Error: Unable to create .fmu directory" in result.stderr

0 commit comments

Comments
 (0)