Skip to content
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)
)
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