Skip to content

Commit

Permalink
fix: dependency group with non-normalized name does not work in pdm 2…
Browse files Browse the repository at this point in the history
….20.0 (#3250)

* fix: dependency group with non-normalized name does not work in pdm 2.20.0
Fixes #3247

Signed-off-by: Frost Ming <me@frostming.com>

* fix tests

Signed-off-by: Frost Ming <me@frostming.com>
  • Loading branch information
frostming authored Nov 4, 2024
1 parent 5d3779f commit acb40b0
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 7 deletions.
1 change: 1 addition & 0 deletions news/3247.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix group name normalization when comparing groups.
2 changes: 1 addition & 1 deletion src/pdm/cli/commands/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def do_add(
if project.enable_write_lockfile:
project.core.ui.info(f"Adding group [success]{group}[/] to lockfile")
lock_groups.append(group)
if group == "default" or not selection.dev and group not in project.pyproject.dev_dependencies:
if group == "default" or not selection.dev and normalize_name(group) not in project.pyproject.dev_dependencies:
if editables:
raise PdmUsageError("Cannot add editables to the default or optional dependency group")
for r in [parse_requirement(line, True) for line in editables] + [parse_requirement(line) for line in packages]:
Expand Down
9 changes: 5 additions & 4 deletions src/pdm/cli/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import TYPE_CHECKING

from pdm.exceptions import PdmUsageError
from pdm.utils import normalize_name

if TYPE_CHECKING:
from typing import Iterator, Sequence
Expand Down Expand Up @@ -78,9 +79,9 @@ def _translated_groups(self) -> list[str]:
if dev is None: # --prod is not set, include dev-dependencies
dev = True
project = self.project
optional_groups = set(project.pyproject.metadata.get("optional-dependencies", {}))
optional_groups = {normalize_name(g) for g in project.pyproject.metadata.get("optional-dependencies", {})}
dev_groups = set(project.pyproject.dev_dependencies)
groups_set = set(groups)
groups_set = {normalize_name(g) if g != ":all" else g for g in groups}
if groups_set & dev_groups:
if not dev:
raise PdmUsageError("--prod is not allowed with dev groups and should be left")
Expand All @@ -91,9 +92,9 @@ def _translated_groups(self) -> list[str]:
groups_set.update(optional_groups)
if default:
groups_set.add("default")
groups_set -= set(self.excluded_groups)
groups_set -= {normalize_name(g) for g in self.excluded_groups}

invalid_groups = groups_set - set(project.iter_groups())
invalid_groups = groups_set - {normalize_name(g) for g in project.iter_groups()}
if invalid_groups:
project.core.ui.echo(
"[d]Ignoring non-existing groups: [success]" f"{', '.join(invalid_groups)}[/]",
Expand Down
11 changes: 9 additions & 2 deletions src/pdm/project/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,8 @@ def iter_groups(self) -> Iterable[str]:
groups = {"default"}
if self.pyproject.metadata.get("optional-dependencies"):
groups.update(self.pyproject.metadata["optional-dependencies"].keys())
groups.update(self.pyproject.dev_dependencies.keys())
groups.update(self.pyproject._data.get("dependency-groups", {}).keys())
groups.update(self.pyproject.settings.get("dev-dependencies", {}).keys())
return groups

@property
Expand Down Expand Up @@ -662,18 +663,24 @@ def update_dev_dependencies(deps: list[str]) -> None:
metadata, settings = self.pyproject.metadata, self.pyproject.settings
if group == "default":
return metadata.get("dependencies", tomlkit.array()), lambda x: metadata.__setitem__("dependencies", x)
dev_dependencies = self.pyproject._data.get("dependency-groups", {})
dev_dependencies.update(self.pyproject.settings.get("dev-dependencies", {}))
deps_setter = [
(
metadata.get("optional-dependencies", {}),
lambda x: metadata.setdefault("optional-dependencies", {}).__setitem__(group, x)
if x
else metadata.setdefault("optional-dependencies", {}).pop(group, None),
),
(self.pyproject.dev_dependencies, update_dev_dependencies),
(dev_dependencies, update_dev_dependencies),
]
normalized_group = normalize_name(group)
for deps, setter in deps_setter:
normalized_groups = {normalize_name(g) for g in deps}
if group in deps:
return make_array(deps[group], True), setter
if normalized_group in normalized_groups:
raise PdmUsageError(f"Group {group} already exists in another non-normalized form")
# If not found, return an empty list and a setter to add the group
return tomlkit.array(), deps_setter[int(dev)][1]

Expand Down
12 changes: 12 additions & 0 deletions tests/cli/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,15 @@ def test_add_dependency_with_direct_minimal_versions(project, pdm, repository):
assert "django>=1.11.8" in project.pyproject.metadata["dependencies"]
assert all_candidates["django"].version == "1.11.8"
assert all_candidates["pytz"].version == "2019.6"


def test_add_group_with_normalized_name(project, pdm, working_set):
project.pyproject.dependency_groups.update({"foo_bar": ["requests"]})
project.pyproject.write()
pdm(["lock"], obj=project, strict=True)
assert "foo-bar" in project.lockfile.groups
pdm(["sync", "-G", "foo.bar"], obj=project, strict=True)
assert "requests" in working_set
result = pdm(["add", "-G", "foo-bar", "pytz"], obj=project)
assert result.exit_code != 0
assert "Group foo-bar already exists in another non-normalized form" in result.stderr

0 comments on commit acb40b0

Please sign in to comment.