Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

normalize extras per PEP685 #476

Merged
merged 2 commits into from
Oct 3, 2022
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
3 changes: 3 additions & 0 deletions src/poetry/core/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from typing import Union
from warnings import warn

from packaging.utils import canonicalize_name

from poetry.core.utils.helpers import combine_unicode
from poetry.core.utils.helpers import readme_content_type

Expand Down Expand Up @@ -176,6 +178,7 @@ def configure_package(

extras = config.get("extras", {})
for extra_name, requirements in extras.items():
extra_name = canonicalize_name(extra_name)
package.extras[extra_name] = []

# Checking for dependency
Expand Down
10 changes: 6 additions & 4 deletions src/poetry/core/packages/dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
from typing import Iterable
from typing import TypeVar

from packaging.utils import canonicalize_name

from poetry.core.constraints.generic import parse_constraint as parse_generic_constraint
from poetry.core.constraints.version import VersionRangeConstraint
from poetry.core.constraints.version import parse_constraint
Expand Down Expand Up @@ -86,7 +88,7 @@ def __init__(
self._transitive_python_constraint: VersionConstraint | None = None
self._transitive_marker: BaseMarker | None = None

self._in_extras: list[str] = []
self._in_extras: list[NormalizedName] = []

self._activated = not self._optional

Expand Down Expand Up @@ -183,7 +185,7 @@ def marker(self, marker: str | BaseMarker) -> None:

for or_ in markers["extra"]:
for _, extra in or_:
self.in_extras.append(extra)
self.in_extras.append(canonicalize_name(extra))

# Recalculate python versions.
self._python_versions = "*"
Expand Down Expand Up @@ -218,12 +220,12 @@ def transitive_python_constraint(self) -> VersionConstraint:
return self._transitive_python_constraint

@property
def extras(self) -> frozenset[str]:
def extras(self) -> frozenset[NormalizedName]:
# extras activated in a dependency is the same as features
return self._features

@property
def in_extras(self) -> list[str]:
def in_extras(self) -> list[NormalizedName]:
return self._in_extras

@property
Expand Down
2 changes: 1 addition & 1 deletion src/poetry/core/packages/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def __init__(
self._license: License | None = None
self.readmes: tuple[Path, ...] = ()

self.extras: dict[str, list[Dependency]] = {}
self.extras: dict[NormalizedName, list[Dependency]] = {}

self._dependency_groups: dict[str, DependencyGroup] = {}

Expand Down
10 changes: 7 additions & 3 deletions src/poetry/core/packages/specification.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from typing import Iterable
from typing import TypeVar

from packaging.utils import canonicalize_name


if TYPE_CHECKING:
from packaging.utils import NormalizedName
Expand Down Expand Up @@ -37,7 +39,7 @@ def __init__(
if not features:
features = []

self._features = frozenset(features)
self._features = frozenset(canonicalize_name(feature) for feature in features)

@property
def name(self) -> NormalizedName:
Expand Down Expand Up @@ -78,7 +80,7 @@ def source_subdirectory(self) -> str | None:
return self._source_subdirectory

@property
def features(self) -> frozenset[str]:
def features(self) -> frozenset[NormalizedName]:
return self._features

def is_direct_origin(self) -> bool:
Expand Down Expand Up @@ -167,7 +169,9 @@ def clone(self: T) -> T:
def with_features(self: T, features: Iterable[str]) -> T:
package = self.clone()

package._features = frozenset(features)
package._features = frozenset(
canonicalize_name(feature) for feature in features
)

return package

Expand Down
6 changes: 4 additions & 2 deletions tests/masonry/builders/test_sdist.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import pytest

from packaging.utils import canonicalize_name

from poetry.core.factory import Factory
from poetry.core.masonry.builders.sdist import SdistBuilder
from poetry.core.masonry.utils.package_include import PackageInclude
Expand Down Expand Up @@ -73,7 +75,7 @@ def test_convert_dependencies() -> None:
assert result == (main, extras)

package = ProjectPackage("foo", "1.2.3")
package.extras = {"bar": [Dependency("A", "*")]}
package.extras = {canonicalize_name("bar"): [Dependency("A", "*")]}

result = SdistBuilder.convert_dependencies(
package,
Expand All @@ -93,7 +95,7 @@ def test_convert_dependencies() -> None:
d = Dependency("D", "3.4.5", optional=True)
d.python_versions = "~2.7 || ^3.4"

package.extras = {"baz": [Dependency("D", "*")]}
package.extras = {canonicalize_name("baz"): [Dependency("D", "*")]}

result = SdistBuilder.convert_dependencies(
package,
Expand Down
6 changes: 4 additions & 2 deletions tests/packages/test_dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import pytest

from packaging.utils import canonicalize_name

from poetry.core.constraints.version.exceptions import ParseConstraintError
from poetry.core.packages.dependency import Dependency
from poetry.core.version.markers import parse_marker
Expand Down Expand Up @@ -51,15 +53,15 @@ def test_to_pep_508_wilcard() -> None:

def test_to_pep_508_in_extras() -> None:
dependency = Dependency("Django", "^1.23")
dependency.in_extras.append("foo")
dependency.in_extras.append(canonicalize_name("foo"))

result = dependency.to_pep_508()
assert result == 'Django (>=1.23,<2.0); extra == "foo"'

result = dependency.to_pep_508(with_extras=False)
assert result == "Django (>=1.23,<2.0)"

dependency.in_extras.append("bar")
dependency.in_extras.append(canonicalize_name("bar"))

result = dependency.to_pep_508()
assert result == 'Django (>=1.23,<2.0); extra == "foo" or extra == "bar"'
Expand Down
8 changes: 5 additions & 3 deletions tests/packages/test_vcs_dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import pytest

from packaging.utils import canonicalize_name

from poetry.core.packages.vcs_dependency import VCSDependency


Expand Down Expand Up @@ -64,7 +66,7 @@ def test_to_pep_508_in_extras() -> None:
dependency = VCSDependency(
"poetry", "git", "https://github.com/python-poetry/poetry.git"
)
dependency.in_extras.append("foo")
dependency.in_extras.append(canonicalize_name("foo"))

expected = (
'poetry @ git+https://github.com/python-poetry/poetry.git ; extra == "foo"'
Expand All @@ -74,7 +76,7 @@ def test_to_pep_508_in_extras() -> None:
dependency = VCSDependency(
"poetry", "git", "https://github.com/python-poetry/poetry.git", extras=["bar"]
)
dependency.in_extras.append("foo")
dependency.in_extras.append(canonicalize_name("foo"))

expected = (
'poetry[bar] @ git+https://github.com/python-poetry/poetry.git ; extra == "foo"'
Expand All @@ -85,7 +87,7 @@ def test_to_pep_508_in_extras() -> None:
dependency = VCSDependency(
"poetry", "git", "https://github.com/python-poetry/poetry.git", "b;ar;"
)
dependency.in_extras.append("foo;")
dependency.in_extras.append(canonicalize_name("foo;"))

expected = (
"poetry @ git+https://github.com/python-poetry/poetry.git@b;ar; ; extra =="
Expand Down
4 changes: 3 additions & 1 deletion tests/test_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import pytest

from packaging.utils import canonicalize_name

from poetry.core.constraints.version import parse_constraint
from poetry.core.factory import Factory
from poetry.core.packages.url_dependency import URLDependency
Expand Down Expand Up @@ -342,7 +344,7 @@ def test_create_poetry_with_markers_and_extras() -> None:

assert len(dependencies) == 2
assert {dependency.name for dependency in dependencies} == {"orjson"}
assert set(extras["all"]) == set(dependencies)
assert set(extras[canonicalize_name("all")]) == set(dependencies)
for dependency in dependencies:
assert dependency.in_extras == ["all"]
assert isinstance(dependency, URLDependency)
Expand Down