Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 5 additions & 1 deletion src/poetry/puzzle/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from poetry.puzzle.exceptions import OverrideNeeded
from poetry.repositories.exceptions import PackageNotFound
from poetry.utils.helpers import download_file
from poetry.utils.helpers import safe_extra
from poetry.vcs.git import Git


Expand Down Expand Up @@ -563,6 +564,7 @@ def complete_package(self, package: DependencyPackage) -> DependencyPackage:
# to the current package
if package.dependency.extras:
for extra in package.dependency.extras:
extra = safe_extra(extra)
if extra not in package.extras:
continue

Expand All @@ -585,7 +587,9 @@ def complete_package(self, package: DependencyPackage) -> DependencyPackage:
(dep.is_optional() and dep.name not in optional_dependencies)
or (
dep.in_extras
and not set(dep.in_extras).intersection(package.dependency.extras)
and not set(dep.in_extras).intersection(
{safe_extra(extra) for extra in package.dependency.extras}
)
)
):
continue
Expand Down
12 changes: 12 additions & 0 deletions src/poetry/utils/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,15 @@ def pluralize(count: int, word: str = "") -> str:
if count == 1:
return word
return word + "s"


def safe_extra(extra: str) -> str:
"""Convert an arbitrary string to a standard 'extra' name

Any runs of non-alphanumeric characters are replaced with a single '_',
and the result is always lowercased.

See
https://github.com/pypa/setuptools/blob/452e13c/pkg_resources/__init__.py#L1423-L1431.
"""
return re.sub("[^A-Za-z0-9.-]+", "_", extra).lower()
52 changes: 36 additions & 16 deletions tests/console/commands/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,12 @@ def test_add_greater_constraint(
assert tester.command.installer.executor.installations_count == 1


@pytest.mark.parametrize("extra_name", ["msgpack", "MsgPack"])
def test_add_constraint_with_extras(
app: PoetryTestApplication, repo: TestRepository, tester: CommandTester
app: PoetryTestApplication,
repo: TestRepository,
tester: CommandTester,
extra_name: str,
):
cachy1 = get_package("cachy", "0.1.0")
cachy1.extras = {"msgpack": [get_dependency("msgpack-python")]}
Expand All @@ -212,7 +216,7 @@ def test_add_constraint_with_extras(
repo.add_package(cachy1)
repo.add_package(get_package("msgpack-python", "0.5.3"))

tester.execute("cachy[msgpack]>=0.1.0,<0.2.0")
tester.execute(f"cachy[{extra_name}]>=0.1.0,<0.2.0")

expected = """\

Expand Down Expand Up @@ -327,19 +331,21 @@ def test_add_git_constraint_with_poetry(
assert tester.command.installer.executor.installations_count == 2


@pytest.mark.parametrize("extra_name", ["foo", "FOO"])
def test_add_git_constraint_with_extras(
app: PoetryTestApplication,
repo: TestRepository,
tester: CommandTester,
tmp_venv: VirtualEnv,
extra_name: str,
):
tester.command.set_env(tmp_venv)

repo.add_package(get_package("pendulum", "1.4.4"))
repo.add_package(get_package("cleo", "0.6.5"))
repo.add_package(get_package("tomlkit", "0.5.5"))

tester.execute("git+https://github.com/demo/demo.git[foo,bar]")
tester.execute(f"git+https://github.com/demo/demo.git[{extra_name},bar]")

expected = """\

Expand All @@ -364,7 +370,7 @@ def test_add_git_constraint_with_extras(
assert "demo" in content["dependencies"]
assert content["dependencies"]["demo"] == {
"git": "https://github.com/demo/demo.git",
"extras": ["foo", "bar"],
"extras": [extra_name, "bar"],
}


Expand Down Expand Up @@ -562,8 +568,12 @@ def test_add_file_constraint_sdist(
assert content["dependencies"]["demo"] == {"path": path}


@pytest.mark.parametrize("extra_name", ["msgpack", "MsgPack"])
def test_add_constraint_with_extras_option(
app: PoetryTestApplication, repo: TestRepository, tester: CommandTester
app: PoetryTestApplication,
repo: TestRepository,
tester: CommandTester,
extra_name: str,
):
cachy2 = get_package("cachy", "0.2.0")
cachy2.extras = {"msgpack": [get_dependency("msgpack-python")]}
Expand All @@ -574,7 +584,7 @@ def test_add_constraint_with_extras_option(
repo.add_package(cachy2)
repo.add_package(get_package("msgpack-python", "0.5.3"))

tester.execute("cachy=0.2.0 --extras msgpack")
tester.execute(f"cachy=0.2.0 --extras {extra_name}")

expected = """\

Expand All @@ -597,7 +607,7 @@ def test_add_constraint_with_extras_option(
assert "cachy" in content["dependencies"]
assert content["dependencies"]["cachy"] == {
"version": "0.2.0",
"extras": ["msgpack"],
"extras": [extra_name],
}


Expand Down Expand Up @@ -641,10 +651,12 @@ def test_add_url_constraint_wheel(
}


@pytest.mark.parametrize("extra_name", ["foo", "FOO"])
def test_add_url_constraint_wheel_with_extras(
app: PoetryTestApplication,
repo: TestRepository,
tester: CommandTester,
extra_name: str,
mocker: MockerFixture,
):
repo.add_package(get_package("pendulum", "1.4.4"))
Expand All @@ -653,7 +665,7 @@ def test_add_url_constraint_wheel_with_extras(

tester.execute(
"https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl"
"[foo,bar]"
f"[{extra_name},bar]"
)

expected = """\
Expand Down Expand Up @@ -684,7 +696,7 @@ def test_add_url_constraint_wheel_with_extras(
"url": (
"https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl"
),
"extras": ["foo", "bar"],
"extras": [extra_name, "bar"],
}


Expand Down Expand Up @@ -1165,11 +1177,13 @@ def test_add_greater_constraint_old_installer(
assert len(installer.installs) == 1


@pytest.mark.parametrize("extra_name", ["msgpack", "MsgPack"])
def test_add_constraint_with_extras_old_installer(
app: PoetryTestApplication,
repo: TestRepository,
installer: NoopInstaller,
old_tester: CommandTester,
extra_name: str,
):
cachy1 = get_package("cachy", "0.1.0")
cachy1.extras = {"msgpack": [get_dependency("msgpack-python")]}
Expand All @@ -1180,7 +1194,7 @@ def test_add_constraint_with_extras_old_installer(
repo.add_package(cachy1)
repo.add_package(get_package("msgpack-python", "0.5.3"))

old_tester.execute("cachy[msgpack]>=0.1.0,<0.2.0")
old_tester.execute(f"cachy[{extra_name}]>=0.1.0,<0.2.0")

expected = """\

Expand Down Expand Up @@ -1298,17 +1312,19 @@ def test_add_git_constraint_with_poetry_old_installer(
assert len(installer.installs) == 2


@pytest.mark.parametrize("extra_name", ["foo", "FOO"])
def test_add_git_constraint_with_extras_old_installer(
app: PoetryTestApplication,
repo: TestRepository,
installer: NoopInstaller,
old_tester: CommandTester,
extra_name: str,
):
repo.add_package(get_package("pendulum", "1.4.4"))
repo.add_package(get_package("cleo", "0.6.5"))
repo.add_package(get_package("tomlkit", "0.5.5"))

old_tester.execute("git+https://github.com/demo/demo.git[foo,bar]")
old_tester.execute(f"git+https://github.com/demo/demo.git[{extra_name},bar]")

expected = """\

Expand All @@ -1334,7 +1350,7 @@ def test_add_git_constraint_with_extras_old_installer(
assert "demo" in content["dependencies"]
assert content["dependencies"]["demo"] == {
"git": "https://github.com/demo/demo.git",
"extras": ["foo", "bar"],
"extras": [extra_name, "bar"],
}


Expand Down Expand Up @@ -1523,11 +1539,13 @@ def test_add_file_constraint_sdist_old_installer(
assert content["dependencies"]["demo"] == {"path": path}


@pytest.mark.parametrize("extra_name", ["msgpack", "MsgPack"])
def test_add_constraint_with_extras_option_old_installer(
app: PoetryTestApplication,
repo: TestRepository,
installer: NoopInstaller,
old_tester: CommandTester,
extra_name: str,
):
cachy2 = get_package("cachy", "0.2.0")
cachy2.extras = {"msgpack": [get_dependency("msgpack-python")]}
Expand All @@ -1538,7 +1556,7 @@ def test_add_constraint_with_extras_option_old_installer(
repo.add_package(cachy2)
repo.add_package(get_package("msgpack-python", "0.5.3"))

old_tester.execute("cachy=0.2.0 --extras msgpack")
old_tester.execute(f"cachy=0.2.0 --extras {extra_name}")

expected = """\

Expand All @@ -1562,7 +1580,7 @@ def test_add_constraint_with_extras_option_old_installer(
assert "cachy" in content["dependencies"]
assert content["dependencies"]["cachy"] == {
"version": "0.2.0",
"extras": ["msgpack"],
"extras": [extra_name],
}


Expand Down Expand Up @@ -1608,19 +1626,21 @@ def test_add_url_constraint_wheel_old_installer(
}


@pytest.mark.parametrize("extra_name", ["foo", "FOO"])
def test_add_url_constraint_wheel_with_extras_old_installer(
app: PoetryTestApplication,
repo: TestRepository,
installer: NoopInstaller,
old_tester: CommandTester,
extra_name: str,
):
repo.add_package(get_package("pendulum", "1.4.4"))
repo.add_package(get_package("cleo", "0.6.5"))
repo.add_package(get_package("tomlkit", "0.5.5"))

old_tester.execute(
"https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl"
"[foo,bar]"
f"[{extra_name},bar]"
)

expected = """\
Expand Down Expand Up @@ -1650,7 +1670,7 @@ def test_add_url_constraint_wheel_with_extras_old_installer(
"url": (
"https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl"
),
"extras": ["foo", "bar"],
"extras": [extra_name, "bar"],
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ python-versions = "*"
B = {version = "^1.0", optional = true, extras = ["C"]}

[package.extras]
B = ["B[C] (>=1.0,<2.0)"]
b = ["B[C] (>=1.0,<2.0)"]

[[package]]
name = "B"
Expand All @@ -24,7 +24,7 @@ python-versions = "*"
C = {version = "^1.0", optional = true}

[package.extras]
C = ["C (>=1.0,<2.0)"]
c = ["C (>=1.0,<2.0)"]

[[package]]
name = "C"
Expand Down
4 changes: 2 additions & 2 deletions tests/installation/test_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1001,11 +1001,11 @@ def test_run_with_dependencies_nested_extras(
)
dependency_a = Factory.create_dependency("A", {"version": "^1.0", "extras": ["B"]})

package_b.extras = {"C": [dependency_c]}
package_b.extras = {"c": [dependency_c]}
package_b.add_dependency(dependency_c)

package_a.add_dependency(dependency_b)
package_a.extras = {"B": [dependency_b]}
package_a.extras = {"b": [dependency_b]}

repo.add_package(package_a)
repo.add_package(package_b)
Expand Down
8 changes: 8 additions & 0 deletions tests/utils/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from poetry.core.utils.helpers import parse_requires

from poetry.utils.helpers import canonicalize_name
from poetry.utils.helpers import safe_extra


def test_parse_requires():
Expand Down Expand Up @@ -77,3 +78,10 @@ def test_parse_requires():
def test_canonicalize_name(test: str, expected: str):
canonicalized_name = canonicalize_name(test)
assert canonicalized_name == expected


def test_safe_extra():
extra = "pandas.CSVDataSet"
result = safe_extra(extra)
expected = "pandas.csvdataset"
assert result == expected