Skip to content

Commit a4d4e20

Browse files
committed
FIX: Handle root models in diff display
1 parent f4ec055 commit a4d4e20

File tree

4 files changed

+203
-205
lines changed

4 files changed

+203
-205
lines changed

src/fmu_settings_cli/sync/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def sync(
8585
)
8686
raise typer.Abort from e
8787

88-
changes = to_fmu.get_dir_diff(from_fmu.path.parent)
88+
changes = to_fmu.get_dir_diff(from_fmu)
8989

9090
if all(len(change_list) == 0 for change_list in changes.values()):
9191
success("No changes detected.")
@@ -106,5 +106,5 @@ def sync(
106106
if not confirmed:
107107
raise typer.Abort
108108

109-
to_fmu.sync_dir(from_fmu.path.parent)
109+
to_fmu.sync_dir(from_fmu)
110110
success(f"All done! {from_dir_abs} has been sync'd to {to_dir_abs}.")

src/fmu_settings_cli/sync/model_diff.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from typing import Any, Final
44

5-
from pydantic import BaseModel
5+
from pydantic import BaseModel, RootModel
66
from rich.console import Console
77
from rich.panel import Panel
88
from rich.table import Table
@@ -64,11 +64,32 @@ def is_complex_change(old_val: Any, new_val: Any) -> bool:
6464
return False
6565

6666

67-
def add_model_to_panel_content(model: BaseModel, indent: int = 0) -> list[str]:
68-
"""Recursively build panel content line for a BaseModel."""
67+
def _add_root_model_to_panel_content(
68+
model: RootModel[Any], indent: int = 0
69+
) -> list[str]:
70+
"""Build and return panel content for a RootModel."""
71+
if not isinstance(model, RootModel):
72+
raise ValueError(f"Received {type(model)}, but a RootModel is required")
73+
6974
lines = []
7075
indent_str = " " * indent
76+
root_value = model.model_dump()
77+
if isinstance(root_value, list) and is_list_of_models(model.root):
78+
for item in model.root:
79+
lines.append(f"{indent_str}[dim]- {type(item).__name__}[/dim]")
80+
lines.extend(add_model_to_panel_content(item, indent + 1))
81+
elif isinstance(root_value, dict):
82+
for k, v in root_value.items():
83+
lines.append(f"{indent_str}[bold]{k}:[/bold] {v}")
84+
else:
85+
lines.append(f"{indent_str}{root_value}")
86+
return lines
87+
7188

89+
def _add_base_model_to_panel_content(model: BaseModel, indent: int = 0) -> list[str]:
90+
"""Build and return panel content for a BaseModel."""
91+
lines = []
92+
indent_str = " " * indent
7293
for key, value in model.model_dump().items():
7394
actual_value = getattr(model, key)
7495

@@ -91,10 +112,16 @@ def add_model_to_panel_content(model: BaseModel, indent: int = 0) -> list[str]:
91112
lines.append(f"{indent_str} [dim]{k}:[/dim] {v}")
92113
else:
93114
lines.append(f"{indent_str}[bold]{key}:[/bold] {value}")
94-
95115
return lines
96116

97117

118+
def add_model_to_panel_content(model: BaseModel, indent: int = 0) -> list[str]:
119+
"""Recursively build panel content line for a BaseModel."""
120+
if isinstance(model, RootModel):
121+
return _add_root_model_to_panel_content(model, indent)
122+
return _add_base_model_to_panel_content(model, indent)
123+
124+
98125
def render_basemodel_panel(
99126
model: BaseModel, field_path: str, added: bool = True
100127
) -> Panel:

tests/test_sync/test_sync_cli.py

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
"""Tests for the 'fmu sync' commands."""
22

33
from collections.abc import Generator
4-
from datetime import UTC, datetime
54
from pathlib import Path
6-
from typing import Any
75
from uuid import uuid4
86

97
import pytest
@@ -13,7 +11,6 @@
1311
from typer.testing import CliRunner
1412

1513
from fmu_settings_cli.__main__ import app
16-
from fmu_settings_cli.sync.model_diff import IGNORED_FIELDS
1714

1815
# ruff: noqa: PLR2004
1916

@@ -133,31 +130,6 @@ def test_sync_no_changes_from_current_dir(
133130
assert result.exit_code == 0
134131

135132

136-
@pytest.mark.parametrize(
137-
"field, value",
138-
[
139-
("created_at", datetime.now(UTC)),
140-
("created_by", "foo"),
141-
],
142-
)
143-
def test_sync_disregards_ignored_fields(
144-
two_fmu_revisions: tuple[Path, ProjectFMUDirectory, ProjectFMUDirectory],
145-
monkeypatch: MonkeyPatch,
146-
field: str,
147-
value: Any,
148-
) -> None:
149-
"""Tests that 'fmu sync' does not see ignored fields as changes to sync."""
150-
tmp_path, project_a, project_b = two_fmu_revisions
151-
monkeypatch.chdir(project_a.path.parent)
152-
153-
assert field in IGNORED_FIELDS
154-
project_a.set_config_value(field, value)
155-
156-
result = runner.invoke(app, ["sync", "--to", str(project_b.path.parent)])
157-
assert "No changes detected" in result.stdout
158-
assert result.exit_code == 0
159-
160-
161133
def test_sync_finds_changed_value_field(
162134
two_fmu_revisions: tuple[Path, ProjectFMUDirectory, ProjectFMUDirectory],
163135
monkeypatch: MonkeyPatch,
@@ -202,7 +174,6 @@ def test_sync_finds_changed_value_field_and_saves_after_confirm(
202174
assert "Value Changes in config" in result.stdout
203175
assert "model.name" in result.stdout
204176
assert "foo" in result.stdout
205-
assert "Complex Changes" not in result.stdout # Not in
206177
assert "Success: All done!" in result.stdout
207178
assert str(project_a.path.parent.absolute()) in result.stdout.replace("\n", "")
208179
assert str(project_b.path.parent.absolute()) in result.stdout.replace("\n", "")

0 commit comments

Comments
 (0)