Skip to content

Commit e2bbd12

Browse files
committed
PR feedback and tests
1 parent 62a7ecc commit e2bbd12

File tree

3 files changed

+66
-12
lines changed

3 files changed

+66
-12
lines changed

src/pip/_internal/req/constructors.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,8 @@ def install_req_from_req_string(
335335
)
336336

337337
if req.url:
338+
# Create an InstallRequirement for a PEP 508 URL with the same behavior
339+
# as 'pip install req.url'
338340
return install_req_from_line(
339341
req.url, comes_from=comes_from, isolated=isolated,
340342
wheel_cache=wheel_cache, use_pep517=use_pep517

tests/functional/test_install.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,17 +1391,25 @@ def test_install_pep508_with_url_in_install_requires(script):
13911391
assert "Successfully installed packaging-15.3" in str(res), str(res)
13921392

13931393

1394-
def test_install_pep508_with_url_in_install_requires_url_change(script):
1395-
dep_v1_path = create_basic_wheel_for_package(
1396-
script, name='dep', version='1.0',
1397-
)
1398-
dep_v2_path = create_basic_wheel_for_package(
1399-
script, name='dep', version='2.0',
1400-
)
1394+
@pytest.mark.parametrize('create_dep, format', [
1395+
(create_test_package_with_setup, 'directory'),
1396+
(create_basic_wheel_for_package, 'wheel'),
1397+
])
1398+
def test_install_pep508_with_url_in_install_requires_url_change(
1399+
create_dep, format, script):
1400+
dep_v1_path = create_dep(script, name='dep', version='1.0')
1401+
1402+
if format == 'directory':
1403+
# Rename the package directory so it doesn't get overwritten when
1404+
# creating the package for dep_v2
1405+
dep_v1_path.move(dep_v1_path.folder / 'dep_v1')
1406+
dep_v1_path = dep_v1_path.folder / 'dep_v1'
1407+
1408+
dep_v2_path = create_dep(script, name='dep', version='2.0')
14011409

14021410
pkga_path = create_basic_wheel_for_package(
14031411
script, name='pkga', version='1.0',
1404-
depends=['dep @ file://%s' % dep_v1_path],
1412+
depends=['dep @ ' + path_to_url(dep_v1_path)],
14051413
)
14061414
res = script.pip('install', pkga_path)
14071415
assert "Successfully installed dep-1.0" in str(res), str(res)
@@ -1411,14 +1419,20 @@ def test_install_pep508_with_url_in_install_requires_url_change(script):
14111419
# Updating the URL to the dependency installs the updated dependency
14121420
pkga_path = create_basic_wheel_for_package(
14131421
script, name='pkga', version='2.0',
1414-
depends=['dep @ file://%s' % dep_v2_path],
1422+
depends=['dep @ ' + path_to_url(dep_v2_path)],
14151423
)
14161424
res = script.pip('install', pkga_path)
14171425
assert "Successfully installed dep-2.0" in str(res), str(res)
14181426

1419-
# The dependency is not reinstalled if the URL doesn't change
14201427
res = script.pip('install', pkga_path)
1421-
assert "Requirement already satisfied: dep==2.0" in str(res), str(res)
1428+
if format == 'directory':
1429+
# pip can't determine versions from a directory name, so it will always
1430+
# reinstall the dependency
1431+
assert "Successfully installed dep-2.0" in str(res), str(res)
1432+
else:
1433+
# pip can determine the version from a wheel's filename, so the
1434+
# dependency is not reinstalled if the URL doesn't change
1435+
assert "Requirement already satisfied: dep==2.0" in str(res), str(res)
14221436

14231437

14241438
@pytest.mark.network

tests/unit/test_req_install.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pip._vendor.packaging.requirements import Requirement
66

77
from pip._internal.req.constructors import (
8-
install_req_from_line, install_req_from_req_string,
8+
install_req_from_line, install_req_from_req_string, path_to_url,
99
)
1010
from pip._internal.req.req_install import InstallRequirement
1111

@@ -92,3 +92,41 @@ def test_install_req_from_string_with_comes_from_without_link(self):
9292
assert install_req.link.url == wheel_url
9393
assert install_req.req.url is None
9494
assert install_req.is_wheel
95+
96+
@pytest.mark.parametrize("use_pep517", [None, True, False])
97+
def test_install_req_from_string_pep508_url_wheel(self, use_pep517):
98+
"""
99+
install_req_from_string parses the version from PEP 508 URLs that point
100+
to wheels so that updating the URL reinstalls the package.
101+
"""
102+
wheel_url = ("https://download.pytorch.org/whl/cu90/"
103+
"torch-1.0.0-cp36-cp36m-win_amd64.whl")
104+
install_str = "torch@ " + wheel_url
105+
install_req = install_req_from_req_string(
106+
install_str, use_pep517=use_pep517
107+
)
108+
109+
assert isinstance(install_req, InstallRequirement)
110+
assert str(install_req.req) == "torch==1.0.0"
111+
assert install_req.link.url == wheel_url
112+
assert install_req.is_wheel
113+
assert install_req.use_pep517 == use_pep517
114+
115+
@pytest.mark.parametrize("use_pep517", [None, True, False])
116+
def test_install_req_from_string_pep508_url_not_a_wheel(
117+
self, use_pep517, tmpdir):
118+
"""
119+
install_req_from_string returns an InstallRequirement() with
120+
``.req = None`` so that the package is always reinstalled.
121+
"""
122+
file_url = path_to_url(tmpdir / "fake_torch_package")
123+
install_str = "torch@ " + file_url
124+
install_req = install_req_from_req_string(
125+
install_str, use_pep517=use_pep517
126+
)
127+
128+
assert isinstance(install_req, InstallRequirement)
129+
assert install_req.req is None
130+
assert install_req.link.url == file_url
131+
assert not install_req.is_wheel
132+
assert install_req.use_pep517 == use_pep517

0 commit comments

Comments
 (0)