Commit 7585c375 by samypr100 Committed by GitHub

Error when invalid groups are referenced (#7529)

parent 6b3a6161
...@@ -163,7 +163,7 @@ poetry install --only docs ...@@ -163,7 +163,7 @@ poetry install --only docs
``` ```
{{% note %}} {{% note %}}
If you only want to install the project's runtime dependencies, you can do so with the If you only want to install the project's runtime dependencies, you can do so with the
`--only main` notation: `--only main` notation:
```bash ```bash
......
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