Skip to content

Commit

Permalink
feat: add confirmation step
Browse files Browse the repository at this point in the history
  • Loading branch information
finswimmer authored and abn committed Nov 18, 2024
1 parent 0b12771 commit 99ea24b
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 26 deletions.
24 changes: 19 additions & 5 deletions src/poetry/config/config_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,32 +39,46 @@ class ConfigSourceMigration:
new_key: str | None
value_migration: dict[Any, Any] = dataclasses.field(default_factory=dict)

def apply(self, config_source: ConfigSource, io: IO | None = None) -> None:
def dry_run(self, config_source: ConfigSource, io: IO | None = None) -> bool:
io = io or NullIO()

try:
old_value = config_source.get_property(self.old_key)
except PropertyNotFoundError:
return
return False

new_value = (
self.value_migration[old_value] if self.value_migration else old_value
)

config_source.remove_property(self.old_key)

msg = f"<c1>{self.old_key}</c1> = <c2>{json.dumps(old_value)}</c2>"

if self.new_key is not None and new_value is not UNSET:
msg += f" -> <c1>{self.new_key}</c1> = <c2>{json.dumps(new_value)}</c2>"
config_source.add_property(self.new_key, new_value)
elif self.new_key is None:
msg += " -> <c1>Removed from config</c1>"
elif self.new_key and new_value is UNSET:
msg += f" -> <c1>{self.new_key}</c1> = <c2>Not explicit set</c2>"

io.write_line(msg)

return True

def apply(self, config_source: ConfigSource) -> None:
try:
old_value = config_source.get_property(self.old_key)
except PropertyNotFoundError:
return

new_value = (
self.value_migration[old_value] if self.value_migration else old_value
)

config_source.remove_property(self.old_key)

if self.new_key is not None and new_value is not UNSET:
config_source.add_property(self.new_key, new_value)


def drop_empty_config_category(
keys: list[str], config: dict[Any, Any]
Expand Down
21 changes: 17 additions & 4 deletions src/poetry/console/commands/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,9 +357,22 @@ def _migrate(self) -> None:

config_source = FileConfigSource(config_file)

self.io.write_line("Starting config migration ...")
self.io.write_line("Checking for required migrations ...")

for migration in CONFIG_MIGRATIONS:
migration.apply(config_source, io=self.io)
required_migrations = [
migration
for migration in CONFIG_MIGRATIONS
if migration.dry_run(config_source, io=self.io)
]

self.io.write_line("Config migration successfully done.")
if not required_migrations:
self.io.write_line("Already up to date.")
return

if not self.io.is_interactive() or self.confirm(
"Proceed with migration?: ", False
):
for migration in required_migrations:
migration.apply(config_source)

self.io.write_line("Config migration successfully done.")
56 changes: 39 additions & 17 deletions tests/console/commands/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,32 +569,54 @@ def test_config_solver_lazy_wheel(
assert not repo._lazy_wheel


current_config = """\
[experimental]
system-git-client = true
[virtualenvs]
prefer-active-python = false
"""

config_migrated = """\
system-git-client = true
[virtualenvs]
use-poetry-python = true
"""


@pytest.mark.parametrize(
["proceed", "expected_config"],
[
("yes", config_migrated),
("no", current_config),
],
)
def test_config_migrate(
tester: CommandTester, mocker: MockerFixture, tmp_path: Path
proceed: str,
expected_config: str,
tester: CommandTester,
mocker: MockerFixture,
tmp_path: Path,
) -> None:
config_dir = tmp_path / "config"
mocker.patch("poetry.locations.CONFIG_DIR", config_dir)

config_file = Path(config_dir / "config.toml")
config_data = textwrap.dedent("""\
[experimental]
system-git-client = true
[virtualenvs]
prefer-active-python = false
""")
with config_file.open("w") as fh:
fh.write(config_data)

tester.execute("--migrate")
fh.write(current_config)

expected_config = textwrap.dedent("""\
system-git-client = true
tester.execute("--migrate", inputs=proceed)

[virtualenvs]
use-poetry-python = true
expected_output = textwrap.dedent("""\
Checking for required migrations ...
experimental.system-git-client = true -> system-git-client = true
virtualenvs.prefer-active-python = false -> virtualenvs.use-poetry-python = true
""")

output = tester.io.fetch_output()
assert output.startswith(expected_output)

with config_file.open("r") as fh:
assert fh.read() == expected_config

Expand All @@ -612,7 +634,7 @@ def test_config_migrate_local_config(tester: CommandTester, poetry: Poetry) -> N
with local_config.open("w") as fh:
fh.write(config_data)

tester.execute("--migrate --local")
tester.execute("--migrate --local", inputs="yes")

expected_config = textwrap.dedent("""\
system-git-client = true
Expand All @@ -629,4 +651,4 @@ def test_config_migrate_local_config_should_raise_if_not_found(
tester: CommandTester,
) -> None:
with pytest.raises(RuntimeError, match="No local config file found"):
tester.execute("--migrate --local")
tester.execute("--migrate --local", inputs="yes")

0 comments on commit 99ea24b

Please sign in to comment.