Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add --lock option to remove command #7917

Merged
merged 3 commits into from
May 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ about dependency groups.
* `--group (-G)`: The group to remove the dependency from.
* `--dev (-D)`: Removes a package from the development dependencies. (**Deprecated**, use `-G dev` instead)
* `--dry-run` : Outputs the operations but will not execute anything (implicitly enables --verbose).
* `--lock`: Do not perform operations (only update the lockfile).


## show
Expand Down
7 changes: 3 additions & 4 deletions src/poetry/console/commands/remove.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class RemoveCommand(InstallerCommand):
"(implicitly enables --verbose)."
),
),
option("lock", None, "Do not perform operations (only update the lockfile)."),
]

help = """The <info>remove</info> command removes a package from the current
Expand Down Expand Up @@ -108,15 +109,13 @@ def handle(self) -> int:
)

# Refresh the locker
self.poetry.set_locker(
self.poetry.locker.__class__(self.poetry.locker.lock, poetry_content)
radoering marked this conversation as resolved.
Show resolved Hide resolved
)
self.poetry.locker.set_local_config(poetry_content)
self.installer.set_locker(self.poetry.locker)

self.installer.set_package(self.poetry.package)
self.installer.dry_run(self.option("dry-run", False))
self.installer.verbose(self.io.is_verbose())
self.installer.update(True)
self.installer.execute_operations(not self.option("lock"))
self.installer.whitelist(removed_set)

status = self.installer.run()
Expand Down
4 changes: 4 additions & 0 deletions src/poetry/packages/locker.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ def is_fresh(self) -> bool:

return False

def set_local_config(self, local_config: dict[str, Any]) -> None:
self._local_config = local_config
self._content_hash = self._get_content_hash()

def locked_repository(self) -> LockfileRepository:
"""
Searches and returns a repository of locked packages.
Expand Down
55 changes: 50 additions & 5 deletions tests/console/commands/test_remove.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from poetry.core.packages.package import Package

from poetry.factory import Factory
from tests.helpers import TestLocker
from tests.helpers import get_package


Expand All @@ -33,12 +34,16 @@ def poetry_with_up_to_date_lockfile(
) -> Poetry:
source = fixture_dir("up_to_date_lock")

return project_factory(
poetry = project_factory(
name="foobar",
pyproject_content=(source / "pyproject.toml").read_text(encoding="utf-8"),
poetry_lock_content=(source / "poetry.lock").read_text(encoding="utf-8"),
)

assert isinstance(poetry.locker, TestLocker)
poetry.locker.locked(True)
return poetry


@pytest.fixture()
def tester(command_tester_factory: CommandTesterFactory) -> CommandTester:
Expand All @@ -49,7 +54,6 @@ def test_remove_without_specific_group_removes_from_all_groups(
tester: CommandTester,
app: PoetryTestApplication,
repo: TestRepository,
command_tester_factory: CommandTesterFactory,
installed: Repository,
) -> None:
"""
Expand Down Expand Up @@ -108,7 +112,6 @@ def test_remove_without_specific_group_removes_from_specific_groups(
tester: CommandTester,
app: PoetryTestApplication,
repo: TestRepository,
command_tester_factory: CommandTesterFactory,
installed: Repository,
) -> None:
"""
Expand Down Expand Up @@ -166,7 +169,6 @@ def test_remove_does_not_live_empty_groups(
tester: CommandTester,
app: PoetryTestApplication,
repo: TestRepository,
command_tester_factory: CommandTesterFactory,
installed: Repository,
) -> None:
"""
Expand Down Expand Up @@ -213,7 +215,6 @@ def test_remove_canonicalized_named_removes_dependency_correctly(
tester: CommandTester,
app: PoetryTestApplication,
repo: TestRepository,
command_tester_factory: CommandTesterFactory,
installed: Repository,
) -> None:
"""
Expand Down Expand Up @@ -308,3 +309,47 @@ def test_remove_with_dry_run_keep_files_intact(
assert (
poetry_with_up_to_date_lockfile._locker.lock_data == original_lockfile_content
)


def test_remove_performs_uninstall_op(
poetry_with_up_to_date_lockfile: Poetry,
command_tester_factory: CommandTesterFactory,
installed: Repository,
) -> None:
installed.add_package(get_package("docker", "4.3.1"))
tester = command_tester_factory("remove", poetry=poetry_with_up_to_date_lockfile)

tester.execute("docker")

expected = """\
Updating dependencies
Resolving dependencies...

Package operations: 0 installs, 0 updates, 1 removal

• Removing docker (4.3.1)

Writing lock file
"""

assert tester.io.fetch_output() == expected


def test_remove_with_lock_does_not_perform_uninstall_op(
poetry_with_up_to_date_lockfile: Poetry,
command_tester_factory: CommandTesterFactory,
installed: Repository,
) -> None:
installed.add_package(get_package("docker", "4.3.1"))
tester = command_tester_factory("remove", poetry=poetry_with_up_to_date_lockfile)

tester.execute("docker --lock")

expected = """\
Updating dependencies
Resolving dependencies...

Writing lock file
"""

assert tester.io.fetch_output() == expected
6 changes: 1 addition & 5 deletions tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,8 @@ class TestLocker(Locker):
__test__ = False

def __init__(self, lock: Path, local_config: dict[str, Any]) -> None:
self._lock = lock
self._local_config = local_config
self._lock_data = None
self._content_hash = self._get_content_hash()
super().__init__(lock, local_config)
self._locked = False
self._lock_data = None
self._write = False

def write(self, write: bool = True) -> None:
Expand Down