Skip to content
Open
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
16 changes: 15 additions & 1 deletion src/poetry/console/commands/group_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,18 @@ def activated_groups(self) -> set[NormalizedName]:
key: {canonicalize_name(group) for group in key_groups}
for key, key_groups in groups.items()
}
# Warn if any group name was normalized (deduplicate warnings)
warned: set[str] = set()
for key_groups in groups.values():
for group in key_groups:
normalized = canonicalize_name(group)
if normalized != group and group not in warned:
warned.add(group)
self.line_error(
f"<warning>Group '{group}' was normalized to '{normalized}'."
" Consider updating your command to use the normalized name.</warning>"
)

norm_default_groups = {canonicalize_name(name) for name in self.default_groups}

return norm_groups["only"] or norm_default_groups.union(
Expand All @@ -121,7 +133,9 @@ def _validate_group_options(self, group_options: dict[str, set[str]]) -> None:
invalid_options = defaultdict(set)
for opt, groups in group_options.items():
for group in groups:
if not self.poetry.package.has_dependency_group(group):
if not self.poetry.package.has_dependency_group(
canonicalize_name(group)
):
invalid_options[group].add(opt)
if invalid_options:
message_parts = []
Expand Down
57 changes: 57 additions & 0 deletions tests/console/commands/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,63 @@ def test_invalid_groups_with_without_only(
)


@pytest.mark.parametrize(
("option", "group_input", "normalized"),
[
("--with", "Foo", "foo"),
("--without", "Foo", "foo"),
("--only", "Foo", "foo"),
("--with", "FOO", "foo"),
("--with", "bim", "bim"),
],
)
def test_non_normalized_group_name_emits_warning(
tester: CommandTester,
mocker: MockerFixture,
option: str,
group_input: str,
normalized: str,
) -> None:
"""
A warning is emitted when a group name passed via --with/--without/--only
differs from its normalized form (e.g. 'Foo' instead of 'foo').
"""
assert isinstance(tester.command, InstallerCommand)
mocker.patch.object(tester.command.installer, "run", return_value=0)

tester.execute(f"{option} {group_input}")
error_output = tester.io.fetch_error()

if group_input != normalized:
assert "was normalized to" in error_output
assert f"'{group_input}'" in error_output
assert f"'{normalized}'" in error_output
else:
assert "was normalized to" not in error_output


def test_normalized_group_name_does_not_raise(
tester: CommandTester,
mocker: MockerFixture,
) -> None:
"""
Passing a non-normalized but valid group name (e.g. 'Foo' for group 'foo')
should not raise a GroupNotFoundError.
"""
assert isinstance(tester.command, InstallerCommand)
mocker.patch.object(tester.command.installer, "run", return_value=0)

# Should not raise even though 'Foo' != 'foo', because they normalize to the same name
# Use --no-root to avoid editable build failure in the test project fixture
tester.execute("--with Foo --no-root")
error_output = tester.io.fetch_error()
assert tester.status_code == 0
assert "GroupNotFoundError" not in error_output
assert "not found" not in error_output
assert "was normalized to" in error_output
assert "'Foo'" in error_output


def test_dry_run_populates_installer(
tester: CommandTester, mocker: MockerFixture
) -> None:
Expand Down