Skip to content

Commit 1b465f7

Browse files
authored
canonicalized extras names (#123)
1 parent acaed39 commit 1b465f7

File tree

5 files changed

+24
-9
lines changed

5 files changed

+24
-9
lines changed

src/poetry_plugin_export/command.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from pathlib import Path
44

55
from cleo.helpers import option
6+
from packaging.utils import canonicalize_name
67
from poetry.console.commands.group_command import GroupCommand
78
from poetry.core.packages.dependency_group import MAIN_GROUP
89

@@ -87,9 +88,13 @@ def handle(self) -> None:
8788

8889
# Checking extras
8990
extras = {
90-
extra for extra_opt in self.option("extras") for extra in extra_opt.split()
91+
canonicalize_name(extra)
92+
for extra_opt in self.option("extras")
93+
for extra in extra_opt.split()
94+
}
95+
invalid_extras = extras - {
96+
canonicalize_name(extra) for extra in self.poetry.package.extras
9197
}
92-
invalid_extras = extras - self.poetry.package.extras.keys()
9398
if invalid_extras:
9499
raise ValueError(
95100
f"Extra [{', '.join(sorted(invalid_extras))}] is not specified."

src/poetry_plugin_export/exporter.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
if TYPE_CHECKING:
1717
from pathlib import Path
1818

19+
from packaging.utils import NormalizedName
1920
from poetry.poetry import Poetry
2021

2122

@@ -38,14 +39,14 @@ def __init__(self, poetry: Poetry) -> None:
3839
self._with_hashes = True
3940
self._with_credentials = False
4041
self._with_urls = True
41-
self._extras: bool | list[str] | None = []
42+
self._extras: bool | list[NormalizedName] | None = []
4243
self._groups: Iterable[str] = [MAIN_GROUP]
4344

4445
@classmethod
4546
def is_format_supported(cls, fmt: str) -> bool:
4647
return fmt in cls.EXPORT_METHODS
4748

48-
def with_extras(self, extras: bool | list[str] | None) -> Exporter:
49+
def with_extras(self, extras: bool | list[NormalizedName] | None) -> Exporter:
4950
self._extras = extras
5051

5152
return self

src/poetry_plugin_export/walker.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import TYPE_CHECKING
44

5+
from packaging.utils import canonicalize_name
56
from poetry.core.semver.util import constraint_regions
67
from poetry.core.version.markers import AnyMarker
78
from poetry.core.version.markers import SingleMarker
@@ -14,6 +15,7 @@
1415
from collections.abc import Iterator
1516
from collections.abc import Sequence
1617

18+
from packaging.utils import NormalizedName
1719
from poetry.core.packages.dependency import Dependency
1820
from poetry.core.packages.package import Package
1921
from poetry.core.version.markers import BaseMarker
@@ -51,7 +53,7 @@ def get_project_dependency_packages(
5153
locker: Locker,
5254
project_requires: list[Dependency],
5355
project_python_marker: BaseMarker | None = None,
54-
extras: bool | Sequence[str] | None = None,
56+
extras: bool | Sequence[NormalizedName] | None = None,
5557
) -> Iterator[DependencyPackage]:
5658
# Apply the project python marker to all requirements.
5759
if project_python_marker is not None:
@@ -68,10 +70,16 @@ def get_project_dependency_packages(
6870
extra_package_names: set[str] | None = None
6971

7072
if extras is not True:
73+
locked_extras = {
74+
canonicalize_name(extra): [
75+
canonicalize_name(dependency) for dependency in dependencies
76+
]
77+
for extra, dependencies in locker.lock_data.get("extras", {}).items()
78+
}
7179
extra_package_names = set(
7280
get_extra_package_names(
7381
repository.packages,
74-
locker.lock_data.get("extras", {}),
82+
locked_extras, # type: ignore[arg-type]
7583
extras or (),
7684
)
7785
)

tests/command/test_command_export.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ def test_export_includes_extras_by_flag(
214214
def test_export_reports_invalid_extras(tester: CommandTester, do_lock: None) -> None:
215215
with pytest.raises(ValueError) as error:
216216
tester.execute("--format requirements.txt --extras 'SUS AMONGUS'")
217-
expected = "Extra [AMONGUS, SUS] is not specified."
217+
expected = "Extra [amongus, sus] is not specified."
218218
assert str(error.value) == expected
219219

220220

tests/test_exporter.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737

3838
if TYPE_CHECKING:
39+
from packaging.utils import NormalizedName
3940
from poetry.poetry import Poetry
4041

4142
from tests.conftest import Config
@@ -905,7 +906,7 @@ def test_exporter_exports_requirements_txt_without_optional_packages(
905906
],
906907
),
907908
(
908-
["feature_bar"],
909+
["feature-bar"],
909910
[
910911
f"bar==4.5.6 ; {MARKER_PY}",
911912
f"foo==1.2.3 ; {MARKER_PY}",
@@ -917,7 +918,7 @@ def test_exporter_exports_requirements_txt_without_optional_packages(
917918
def test_exporter_exports_requirements_txt_with_optional_packages(
918919
tmp_path: Path,
919920
poetry: Poetry,
920-
extras: bool | list[str] | None,
921+
extras: bool | list[NormalizedName] | None,
921922
lines: list[str],
922923
) -> None:
923924
poetry.locker.mock_lock_data( # type: ignore[attr-defined]

0 commit comments

Comments
 (0)