Commit 7585c375 by samypr100 Committed by GitHub

Error when invalid groups are referenced (#7529)

parent 6b3a6161
from __future__ import annotations from __future__ import annotations
from collections import defaultdict
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from cleo.helpers import option from cleo.helpers import option
from poetry.core.packages.dependency_group import MAIN_GROUP from poetry.core.packages.dependency_group import MAIN_GROUP
from poetry.console.commands.command import Command from poetry.console.commands.command import Command
from poetry.console.exceptions import GroupNotFound
if TYPE_CHECKING: if TYPE_CHECKING:
...@@ -78,6 +80,7 @@ class GroupCommand(Command): ...@@ -78,6 +80,7 @@ class GroupCommand(Command):
for groups in self.option(key, "") for groups in self.option(key, "")
for group in groups.split(",") for group in groups.split(",")
} }
self._validate_group_options(groups)
for opt, new, group in [ for opt, new, group in [
("no-dev", "only", MAIN_GROUP), ("no-dev", "only", MAIN_GROUP),
...@@ -107,3 +110,22 @@ class GroupCommand(Command): ...@@ -107,3 +110,22 @@ class GroupCommand(Command):
return self.poetry.package.with_dependency_groups( return self.poetry.package.with_dependency_groups(
list(self.activated_groups), only=True list(self.activated_groups), only=True
) )
def _validate_group_options(self, group_options: dict[str, set[str]]) -> None:
"""
Raises en error if it detects that a group is not part of pyproject.toml
"""
invalid_options = defaultdict(set)
for opt, groups in group_options.items():
for group in groups:
if not self.poetry.package.has_dependency_group(group):
invalid_options[group].add(opt)
if invalid_options:
message_parts = []
for group in sorted(invalid_options):
opts = ", ".join(
f"<fg=yellow;options=bold>--{opt}</>"
for opt in sorted(invalid_options[group])
)
message_parts.append(f"{group} (via {opts})")
raise GroupNotFound(f"Group(s) not found: {', '.join(message_parts)}")
...@@ -5,3 +5,7 @@ from cleo.exceptions import CleoError ...@@ -5,3 +5,7 @@ from cleo.exceptions import CleoError
class PoetryConsoleError(CleoError): class PoetryConsoleError(CleoError):
pass pass
class GroupNotFound(PoetryConsoleError):
pass
from __future__ import annotations from __future__ import annotations
import re
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import pytest import pytest
...@@ -7,6 +9,8 @@ import pytest ...@@ -7,6 +9,8 @@ import pytest
from poetry.core.masonry.utils.module import ModuleOrPackageNotFound from poetry.core.masonry.utils.module import ModuleOrPackageNotFound
from poetry.core.packages.dependency_group import MAIN_GROUP from poetry.core.packages.dependency_group import MAIN_GROUP
from poetry.console.exceptions import GroupNotFound
if TYPE_CHECKING: if TYPE_CHECKING:
from cleo.testers.command_tester import CommandTester from cleo.testers.command_tester import CommandTester
...@@ -257,6 +261,48 @@ def test_only_root_conflicts_with_without_only( ...@@ -257,6 +261,48 @@ def test_only_root_conflicts_with_without_only(
) )
@pytest.mark.parametrize(
("options", "valid_groups", "should_raise"),
[
({"--with": MAIN_GROUP}, {MAIN_GROUP}, False),
({"--with": "spam"}, set(), True),
({"--with": "spam,foo"}, {"foo"}, True),
({"--without": "spam"}, set(), True),
({"--without": "spam,bar"}, {"bar"}, True),
({"--with": "eggs,ham", "--without": "spam"}, set(), True),
({"--with": "eggs,ham", "--without": "spam,baz"}, {"baz"}, True),
({"--only": "spam"}, set(), True),
({"--only": "bim"}, {"bim"}, False),
({"--only": MAIN_GROUP}, {MAIN_GROUP}, False),
],
)
def test_invalid_groups_with_without_only(
tester: CommandTester,
mocker: MockerFixture,
options: dict[str, str],
valid_groups: set[str],
should_raise: bool,
):
mocker.patch.object(tester.command.installer, "run", return_value=0)
cmd_args = " ".join(f"{flag} {groups}" for (flag, groups) in options.items())
if not should_raise:
tester.execute(cmd_args)
assert tester.status_code == 0
else:
with pytest.raises(GroupNotFound, match=r"^Group\(s\) not found:") as e:
tester.execute(cmd_args)
assert tester.status_code is None
for opt, groups in options.items():
group_list = groups.split(",")
invalid_groups = sorted(set(group_list) - valid_groups)
for group in invalid_groups:
assert (
re.search(rf"{group} \(via .*{opt}.*\)", str(e.value)) is not None
)
def test_remove_untracked_outputs_deprecation_warning( def test_remove_untracked_outputs_deprecation_warning(
tester: CommandTester, tester: CommandTester,
mocker: MockerFixture, mocker: MockerFixture,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment