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
16 changes: 10 additions & 6 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "2.1.3"
description = "Python dependency management and packaging made easy."
requires-python = ">=3.9,<4.0"
dependencies = [
"poetry-core (==2.1.3)",
"poetry-core @ git+https://github.com/python-poetry/poetry-core.git",
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
"build (>=1.2.1,<2.0.0)",
"cachecontrol[filecache] (>=0.14.0,<0.15.0)",
"cleo (>=2.1.0,<3.0.0)",
Expand Down
18 changes: 14 additions & 4 deletions src/poetry/console/commands/group_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from typing import TYPE_CHECKING

from cleo.helpers import option
from packaging.utils import NormalizedName
from packaging.utils import canonicalize_name

from poetry.console.commands.command import Command
from poetry.console.exceptions import GroupNotFoundError
Expand Down Expand Up @@ -70,7 +72,7 @@ def default_groups(self) -> set[str]:
return self.non_optional_groups

@property
def activated_groups(self) -> set[str]:
def activated_groups(self) -> set[NormalizedName]:
groups = {}

for key in {"with", "without", "only"}:
Expand All @@ -95,9 +97,17 @@ def activated_groups(self) -> set[str]:
"</warning>"
)

return groups["only"] or self.default_groups.union(groups["with"]).difference(
groups["without"]
)
# Normalize after validating so that original names are printed
# in case of an error.
norm_groups = {
key: {canonicalize_name(group) for group in key_groups}
for key, key_groups in groups.items()
}
norm_default_groups = {canonicalize_name(name) for name in self.default_groups}

return norm_groups["only"] or norm_default_groups.union(
norm_groups["with"]
).difference(norm_groups["without"])

def project_with_activated_groups_only(self) -> ProjectPackage:
return self.poetry.package.with_dependency_groups(
Expand Down
3 changes: 2 additions & 1 deletion src/poetry/console/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

if TYPE_CHECKING:
from cleo.io.inputs.option import Option
from packaging.utils import NormalizedName


class InstallCommand(InstallerCommand):
Expand Down Expand Up @@ -83,7 +84,7 @@ class InstallCommand(InstallerCommand):
]

@property
def activated_groups(self) -> set[str]:
def activated_groups(self) -> set[NormalizedName]:
if self.option("only-root"):
return set()
else:
Expand Down
6 changes: 4 additions & 2 deletions src/poetry/console/commands/self/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from typing import TYPE_CHECKING
from typing import ClassVar

from packaging.utils import NormalizedName
from packaging.utils import canonicalize_name
from poetry.core.packages.dependency_group import MAIN_GROUP

from poetry.console.commands.install import InstallCommand
Expand Down Expand Up @@ -33,8 +35,8 @@ class SelfInstallCommand(SelfCommand, InstallCommand):
"""

@property
def activated_groups(self) -> set[str]:
return {MAIN_GROUP, self.default_group}
def activated_groups(self) -> set[NormalizedName]:
return {MAIN_GROUP, canonicalize_name(self.default_group)}

@property
def _alternative_sync_command(self) -> str:
Expand Down
9 changes: 6 additions & 3 deletions src/poetry/console/commands/self/self_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from pathlib import Path
from typing import TYPE_CHECKING

from packaging.utils import canonicalize_name
from poetry.core.packages.dependency import Dependency
from poetry.core.packages.project_package import ProjectPackage

Expand All @@ -16,12 +17,14 @@


if TYPE_CHECKING:
from packaging.utils import NormalizedName

from poetry.poetry import Poetry
from poetry.utils.env import Env


class SelfCommand(InstallerCommand):
ADDITIONAL_PACKAGE_GROUP = "additional"
ADDITIONAL_PACKAGE_GROUP = canonicalize_name("additional")

@staticmethod
def get_default_system_pyproject_file() -> Path:
Expand Down Expand Up @@ -54,8 +57,8 @@ def default_group(self) -> str:
return self.ADDITIONAL_PACKAGE_GROUP

@property
def activated_groups(self) -> set[str]:
return {self.default_group}
def activated_groups(self) -> set[NormalizedName]:
return {canonicalize_name(self.default_group)}

def generate_system_pyproject(self) -> None:
preserved = {}
Expand Down
6 changes: 3 additions & 3 deletions src/poetry/console/commands/self/show/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

if TYPE_CHECKING:
from cleo.io.inputs.option import Option
from packaging.utils import NormalizedName


class SelfShowCommand(SelfCommand, ShowCommand):
Expand All @@ -33,9 +34,8 @@ class SelfShowCommand(SelfCommand, ShowCommand):
"""

@property
def activated_groups(self) -> set[str]:
def activated_groups(self) -> set[NormalizedName]:
if self.option("addons", False):
return {SelfCommand.ADDITIONAL_PACKAGE_GROUP}

groups: set[str] = super(ShowCommand, self).activated_groups
return groups
return super(ShowCommand, self).activated_groups
4 changes: 2 additions & 2 deletions src/poetry/installation/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def __init__(
self._requires_synchronization = False
self._update = False
self._verbose = False
self._groups: Iterable[str] | None = None
self._groups: Iterable[NormalizedName] | None = None
self._skip_directory = False
self._lock = False

Expand Down Expand Up @@ -127,7 +127,7 @@ def verbose(self, verbose: bool = True) -> Installer:
def is_verbose(self) -> bool:
return self._verbose

def only_groups(self, groups: Iterable[str]) -> Installer:
def only_groups(self, groups: Iterable[NormalizedName]) -> Installer:
self._groups = groups

return self
Expand Down
27 changes: 17 additions & 10 deletions src/poetry/packages/locker.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,20 @@ def locked_packages(self) -> dict[Package, TransitivePackageInfo]:
groups = set(info["groups"])
locked_marker = info.get("markers", "*")
if isinstance(locked_marker, str):
markers = {group: parse_marker(locked_marker) for group in groups}
markers = {
canonicalize_name(group): parse_marker(locked_marker)
for group in groups
}
else:
markers = {
group: parse_marker(locked_marker.get(group, "*"))
canonicalize_name(group): parse_marker(
locked_marker.get(group, "*")
)
for group in groups
}
locked_packages[package] = TransitivePackageInfo(0, groups, markers)
locked_packages[package] = TransitivePackageInfo(
0, {canonicalize_name(g) for g in groups}, markers
)

return locked_packages

Expand Down Expand Up @@ -553,23 +560,23 @@ def _dump_package(
data["markers"] = str(marker)
else:
data["markers"] = inline_table()
for k, v in sorted(
for group, marker in sorted(
transitive_info.markers.items(),
key=lambda x: (x[0] != "main", x[0]),
):
if not v.is_any():
data["markers"][k] = str(v)
if not marker.is_any():
data["markers"][group] = str(marker)
data["files"] = sorted(package.files, key=lambda x: x["file"])

if dependencies:
data["dependencies"] = table()
for k, constraints in dependencies.items():
for dep_name, constraints in dependencies.items():
if len(constraints) == 1:
data["dependencies"][k] = constraints[0]
data["dependencies"][dep_name] = constraints[0]
else:
data["dependencies"][k] = array().multiline(True)
data["dependencies"][dep_name] = array().multiline(True)
for constraint in constraints:
data["dependencies"][k].append(constraint)
data["dependencies"][dep_name].append(constraint)

if package.extras:
extras = {}
Expand Down
8 changes: 5 additions & 3 deletions src/poetry/packages/transitive_package_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@
if TYPE_CHECKING:
from collections.abc import Iterable

from packaging.utils import NormalizedName


@dataclass
class TransitivePackageInfo:
depth: int # max depth in the dependency tree
groups: set[str]
markers: dict[str, BaseMarker] # group -> marker
groups: set[NormalizedName]
markers: dict[NormalizedName, BaseMarker] # group -> marker

def get_marker(self, groups: Iterable[str]) -> BaseMarker:
def get_marker(self, groups: Iterable[NormalizedName]) -> BaseMarker:
marker: BaseMarker = EmptyMarker()
for group in groups:
if group_marker := self.markers.get(group):
Expand Down
6 changes: 3 additions & 3 deletions src/poetry/puzzle/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def __init__(
self.depth = -1

if not previous:
self.groups: frozenset[str] = frozenset()
self.groups: frozenset[NormalizedName] = frozenset()
self.optional = True
elif dep:
self.groups = dep.groups
Expand Down Expand Up @@ -361,7 +361,7 @@ def aggregate_package_nodes(
) -> tuple[Package, TransitivePackageInfo]:
package = nodes[0].package
depth = max(node.depth for node in nodes)
groups: set[str] = set()
groups: set[NormalizedName] = set()
for node in nodes:
groups.update(node.groups)

Expand Down Expand Up @@ -395,7 +395,7 @@ def calculate_markers(
for depth in range(max_depth + 1):
for package in packages_by_depth[depth]:
transitive_info = packages[package]
transitive_marker: dict[str, BaseMarker] = {
transitive_marker: dict[NormalizedName, BaseMarker] = {
group: EmptyMarker() for group in transitive_info.groups
}
for parent, m in markers[package].items():
Expand Down
2 changes: 1 addition & 1 deletion src/poetry/puzzle/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(
installed_packages: list[Package] | None = None,
root_package: Package | None = None,
marker_env: dict[str, Any] | None = None,
groups: set[str] | None = None,
groups: set[NormalizedName] | None = None,
) -> None:
self._current_packages = current_packages
self._result_packages = result_packages
Expand Down
2 changes: 1 addition & 1 deletion tests/installation/test_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ def test_run_install_with_dependency_groups(
)

if groups is not None:
installer.only_groups(groups)
installer.only_groups({canonicalize_name(g) for g in groups})

installer.update(update)
installer.requires_synchronization(requires_synchronization)
Expand Down
Loading