Skip to content

Commit d08b4d9

Browse files
committed
Use packaging.version to check version equality
1 parent 5ee7caf commit d08b4d9

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

news/9083.bugfix.rst

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
New resolver: Check version equality with ``packaging.version`` to avoid edge
2+
cases if a wheel used different version normalization logic in its filename
3+
and metadata.

src/pip/_internal/resolution/resolvelib/candidates.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,10 @@ def __init__(
283283
)
284284
# Version may not be present for PEP 508 direct URLs
285285
if version is not None:
286-
assert str(version) == wheel.version, (
286+
wheel_version = Version(wheel.version)
287+
assert version == wheel_version, (
287288
"{!r} != {!r} for wheel {}".format(
288-
version, wheel.version, name
289+
version, wheel_version, name
289290
)
290291
)
291292

tests/functional/test_new_resolver.py

+43
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
create_basic_wheel_for_package,
1212
create_test_package_with_setup,
1313
)
14+
from tests.lib.wheel import make_wheel
1415

1516

1617
def assert_installed(script, **kwargs):
@@ -1089,3 +1090,45 @@ def test_new_resolver_presents_messages_when_backtracking_a_lot(script, N):
10891090
assert result.stdout.count("This could take a while.") >= 2
10901091
if N >= 13:
10911092
assert "press Ctrl + C" in result.stdout
1093+
1094+
1095+
@pytest.mark.parametrize(
1096+
"metadata_version",
1097+
[
1098+
"0.1.0+local.1", # Normalized form.
1099+
"0.1.0+local_1", # Non-normalized form containing an underscore.
1100+
1101+
# Non-normalized form containing a dash. This is allowed, installation
1102+
# works correctly, but assert_installed() fails because pkg_resources
1103+
# cannot handle it correctly. Nobody is complaining about it right now,
1104+
# we're probably dropping it for importlib.metadata soon(tm), so let's
1105+
# ignore it for the time being.
1106+
pytest.param("0.1.0+local-1", marks=pytest.mark.xfail),
1107+
],
1108+
ids=["meta_dot", "meta_underscore", "meta_dash"],
1109+
)
1110+
@pytest.mark.parametrize(
1111+
"filename_version",
1112+
[
1113+
("0.1.0+local.1"), # Tools are encouraged to use this.
1114+
("0.1.0+local_1"), # But this is allowed (version not normalized).
1115+
],
1116+
ids=["file_dot", "file_underscore"],
1117+
)
1118+
def test_new_resolver_check_wheel_version_normalized(
1119+
script,
1120+
metadata_version,
1121+
filename_version,
1122+
):
1123+
filename = "simple-{}-py2.py3-none-any.whl".format(filename_version)
1124+
1125+
wheel_builder = make_wheel(name="simple", version=metadata_version)
1126+
wheel_builder.save_to(script.scratch_path / filename)
1127+
1128+
script.pip(
1129+
"install",
1130+
"--no-cache-dir", "--no-index",
1131+
"--find-links", script.scratch_path,
1132+
"simple"
1133+
)
1134+
assert_installed(script, simple="0.1.0+local.1")

0 commit comments

Comments
 (0)