Skip to content

Commit

Permalink
normalize extras per PEP685
Browse files Browse the repository at this point in the history
  • Loading branch information
dimbleby committed Sep 16, 2022
1 parent 9124679 commit 5d3c436
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 40 deletions.
3 changes: 3 additions & 0 deletions src/poetry/core/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from typing import cast
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 @@ -175,6 +177,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.packages.constraints import (
parse_constraint as parse_generic_constraint,
)
Expand Down Expand Up @@ -88,7 +90,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 @@ -185,7 +187,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 @@ -220,12 +222,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 @@ -91,7 +91,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.packages.dependency import Dependency
from poetry.core.semver.exceptions import ParseConstraintError
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
14 changes: 7 additions & 7 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 @@ -37,10 +39,8 @@
),
(
{"branch": "main", "directory": "sub"},
(
"poetry @ git+https://github.com/python-poetry/poetry.git"
"@main#subdirectory=sub"
),
"poetry @ git+https://github.com/python-poetry/poetry.git"
"@main#subdirectory=sub",
),
],
)
Expand All @@ -64,7 +64,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 +74,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 +85,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
34 changes: 13 additions & 21 deletions 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.factory import Factory
from poetry.core.packages.url_dependency import URLDependency
from poetry.core.packages.vcs_dependency import VCSDependency
Expand Down Expand Up @@ -229,24 +231,16 @@ def test_validate_strict_fails_strict_and_non_strict() -> None:
"'version' is a required property",
"'description' is a required property",
"'authors' is a required property",
(
'Script "a_script_with_unknown_extra" requires extra "foo" which is not'
" defined."
),
(
"Declared README files must be of same type: found text/markdown,"
" text/x-rst"
),
'Script "a_script_with_unknown_extra" requires extra "foo" which is not'
" defined.",
"Declared README files must be of same type: found text/markdown,"
" text/x-rst",
],
"warnings": [
(
"A wildcard Python dependency is ambiguous. Consider specifying a more"
" explicit one."
),
(
'The "pathlib2" dependency specifies the "allows-prereleases" property,'
' which is deprecated. Use "allow-prereleases" instead.'
),
"A wildcard Python dependency is ambiguous. Consider specifying a more"
" explicit one.",
'The "pathlib2" dependency specifies the "allows-prereleases" property,'
' which is deprecated. Use "allow-prereleases" instead.',
],
}

Expand Down Expand Up @@ -342,7 +336,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 Expand Up @@ -381,10 +375,8 @@ def test_create_poetry_with_markers_and_extras() -> None:
"markers": 'platform_machine == "x86_64"',
},
"~3.7",
(
'platform_machine == "x86_64" and python_version == "3.7" and'
' sys_platform == "linux"'
),
'platform_machine == "x86_64" and python_version == "3.7" and'
' sys_platform == "linux"',
),
(
{"python": ">=3.7", "markers": 'python_version < "4.0"'},
Expand Down

0 comments on commit 5d3c436

Please sign in to comment.