mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
851 lines
26 KiB
Python
851 lines
26 KiB
Python
import os.path
|
|
import shutil
|
|
import textwrap
|
|
from hashlib import sha256
|
|
|
|
import pytest
|
|
from pip._vendor.six import PY2
|
|
|
|
from pip._internal.cli.status_codes import ERROR
|
|
from pip._internal.utils.urls import path_to_url
|
|
from tests.lib import create_really_basic_wheel
|
|
from tests.lib.path import Path
|
|
from tests.lib.server import file_response
|
|
|
|
|
|
def fake_wheel(data, wheel_path):
|
|
wheel_name = os.path.basename(wheel_path)
|
|
name, version, rest = wheel_name.split("-", 2)
|
|
wheel_data = create_really_basic_wheel(name, version)
|
|
data.packages.joinpath(wheel_path).write_bytes(wheel_data)
|
|
|
|
|
|
@pytest.mark.network
|
|
def test_download_if_requested(script):
|
|
"""
|
|
It should download (in the scratch path) and not install if requested.
|
|
"""
|
|
result = script.pip(
|
|
'download', '-d', 'pip_downloads', 'INITools==0.1'
|
|
)
|
|
result.did_create(
|
|
Path('scratch') / 'pip_downloads' / 'INITools-0.1.tar.gz'
|
|
)
|
|
result.did_not_create(script.site_packages / 'initools')
|
|
|
|
|
|
@pytest.mark.network
|
|
def test_basic_download_setuptools(script):
|
|
"""
|
|
It should download (in the scratch path) and not install if requested.
|
|
"""
|
|
result = script.pip('download', 'setuptools')
|
|
setuptools_prefix = str(Path('scratch') / 'setuptools')
|
|
assert any(
|
|
path.startswith(setuptools_prefix) for path in result.files_created
|
|
)
|
|
|
|
|
|
def test_download_wheel(script, data):
|
|
"""
|
|
Test using "pip download" to download a *.whl archive.
|
|
"""
|
|
result = script.pip(
|
|
'download',
|
|
'--no-index',
|
|
'-f', data.packages,
|
|
'-d', '.', 'meta'
|
|
)
|
|
result.did_create(Path('scratch') / 'meta-1.0-py2.py3-none-any.whl')
|
|
result.did_not_create(script.site_packages / 'piptestpackage')
|
|
|
|
|
|
@pytest.mark.network
|
|
def test_single_download_from_requirements_file(script):
|
|
"""
|
|
It should support download (in the scratch path) from PyPI from a
|
|
requirements file
|
|
"""
|
|
script.scratch_path.joinpath("test-req.txt").write_text(textwrap.dedent("""
|
|
INITools==0.1
|
|
"""))
|
|
result = script.pip(
|
|
'download', '-r', script.scratch_path / 'test-req.txt', '-d', '.',
|
|
)
|
|
result.did_create(Path('scratch') / 'INITools-0.1.tar.gz')
|
|
result.did_not_create(script.site_packages / 'initools')
|
|
|
|
|
|
@pytest.mark.network
|
|
def test_basic_download_should_download_dependencies(script):
|
|
"""
|
|
It should download dependencies (in the scratch path)
|
|
"""
|
|
result = script.pip(
|
|
'download', 'Paste[openid]==1.7.5.1', '-d', '.'
|
|
)
|
|
result.did_create(Path('scratch') / 'Paste-1.7.5.1.tar.gz')
|
|
openid_tarball_prefix = str(Path('scratch') / 'python-openid-')
|
|
assert any(
|
|
path.startswith(openid_tarball_prefix) for path in result.files_created
|
|
)
|
|
result.did_not_create(script.site_packages / 'openid')
|
|
|
|
|
|
def test_download_wheel_archive(script, data):
|
|
"""
|
|
It should download a wheel archive path
|
|
"""
|
|
wheel_filename = 'colander-0.9.9-py2.py3-none-any.whl'
|
|
wheel_path = '/'.join((data.find_links, wheel_filename))
|
|
result = script.pip(
|
|
'download', wheel_path,
|
|
'-d', '.', '--no-deps'
|
|
)
|
|
result.did_create(Path('scratch') / wheel_filename)
|
|
|
|
|
|
def test_download_should_download_wheel_deps(script, data):
|
|
"""
|
|
It should download dependencies for wheels(in the scratch path)
|
|
"""
|
|
wheel_filename = 'colander-0.9.9-py2.py3-none-any.whl'
|
|
dep_filename = 'translationstring-1.1.tar.gz'
|
|
wheel_path = '/'.join((data.find_links, wheel_filename))
|
|
result = script.pip(
|
|
'download', wheel_path,
|
|
'-d', '.', '--find-links', data.find_links, '--no-index'
|
|
)
|
|
result.did_create(Path('scratch') / wheel_filename)
|
|
result.did_create(Path('scratch') / dep_filename)
|
|
|
|
|
|
@pytest.mark.network
|
|
def test_download_should_skip_existing_files(script):
|
|
"""
|
|
It should not download files already existing in the scratch dir
|
|
"""
|
|
script.scratch_path.joinpath("test-req.txt").write_text(textwrap.dedent("""
|
|
INITools==0.1
|
|
"""))
|
|
|
|
result = script.pip(
|
|
'download', '-r', script.scratch_path / 'test-req.txt', '-d', '.',
|
|
)
|
|
result.did_create(Path('scratch') / 'INITools-0.1.tar.gz')
|
|
result.did_not_create(script.site_packages / 'initools')
|
|
|
|
# adding second package to test-req.txt
|
|
script.scratch_path.joinpath("test-req.txt").write_text(textwrap.dedent("""
|
|
INITools==0.1
|
|
python-openid==2.2.5
|
|
"""))
|
|
|
|
# only the second package should be downloaded
|
|
result = script.pip(
|
|
'download', '-r', script.scratch_path / 'test-req.txt', '-d', '.',
|
|
)
|
|
openid_tarball_prefix = str(Path('scratch') / 'python-openid-')
|
|
assert any(
|
|
path.startswith(openid_tarball_prefix) for path in result.files_created
|
|
)
|
|
result.did_not_create(Path('scratch') / 'INITools-0.1.tar.gz')
|
|
result.did_not_create(script.site_packages / 'initools')
|
|
result.did_not_create(script.site_packages / 'openid')
|
|
|
|
|
|
@pytest.mark.network
|
|
def test_download_vcs_link(script):
|
|
"""
|
|
It should allow -d flag for vcs links, regression test for issue #798.
|
|
"""
|
|
result = script.pip(
|
|
'download', '-d', '.', 'git+git://github.com/pypa/pip-test-package.git'
|
|
)
|
|
result.did_create(Path('scratch') / 'pip-test-package-0.1.1.zip')
|
|
result.did_not_create(script.site_packages / 'piptestpackage')
|
|
|
|
|
|
def test_only_binary_set_then_download_specific_platform(script, data):
|
|
"""
|
|
Confirm that specifying an interpreter/platform constraint
|
|
is allowed when ``--only-binary=:all:`` is set.
|
|
"""
|
|
fake_wheel(data, 'fake-1.0-py2.py3-none-any.whl')
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--platform', 'linux_x86_64',
|
|
'fake'
|
|
)
|
|
result.did_create(Path('scratch') / 'fake-1.0-py2.py3-none-any.whl')
|
|
|
|
|
|
def test_no_deps_set_then_download_specific_platform(script, data):
|
|
"""
|
|
Confirm that specifying an interpreter/platform constraint
|
|
is allowed when ``--no-deps`` is set.
|
|
"""
|
|
fake_wheel(data, 'fake-1.0-py2.py3-none-any.whl')
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--no-deps',
|
|
'--dest', '.',
|
|
'--platform', 'linux_x86_64',
|
|
'fake'
|
|
)
|
|
result.did_create(Path('scratch') / 'fake-1.0-py2.py3-none-any.whl')
|
|
|
|
|
|
def test_download_specific_platform_fails(script, data):
|
|
"""
|
|
Confirm that specifying an interpreter/platform constraint
|
|
enforces that ``--no-deps`` or ``--only-binary=:all:`` is set.
|
|
"""
|
|
fake_wheel(data, 'fake-1.0-py2.py3-none-any.whl')
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--dest', '.',
|
|
'--platform', 'linux_x86_64',
|
|
'fake',
|
|
expect_error=True,
|
|
)
|
|
assert '--only-binary=:all:' in result.stderr
|
|
|
|
|
|
def test_no_binary_set_then_download_specific_platform_fails(script, data):
|
|
"""
|
|
Confirm that specifying an interpreter/platform constraint
|
|
enforces that ``--only-binary=:all:`` is set without ``--no-binary``.
|
|
"""
|
|
fake_wheel(data, 'fake-1.0-py2.py3-none-any.whl')
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--no-binary=fake',
|
|
'--dest', '.',
|
|
'--platform', 'linux_x86_64',
|
|
'fake',
|
|
expect_error=True,
|
|
)
|
|
assert '--only-binary=:all:' in result.stderr
|
|
|
|
|
|
def test_download_specify_platform(script, data):
|
|
"""
|
|
Test using "pip download --platform" to download a .whl archive
|
|
supported for a specific platform
|
|
"""
|
|
fake_wheel(data, 'fake-1.0-py2.py3-none-any.whl')
|
|
|
|
# Confirm that universal wheels are returned even for specific
|
|
# platforms.
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--platform', 'linux_x86_64',
|
|
'fake'
|
|
)
|
|
result.did_create(Path('scratch') / 'fake-1.0-py2.py3-none-any.whl')
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--platform', 'macosx_10_9_x86_64',
|
|
'fake'
|
|
)
|
|
|
|
data.reset()
|
|
fake_wheel(data, 'fake-1.0-py2.py3-none-macosx_10_9_x86_64.whl')
|
|
fake_wheel(data, 'fake-2.0-py2.py3-none-linux_x86_64.whl')
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--platform', 'macosx_10_10_x86_64',
|
|
'fake'
|
|
)
|
|
result.did_create(
|
|
Path('scratch') /
|
|
'fake-1.0-py2.py3-none-macosx_10_9_x86_64.whl'
|
|
)
|
|
|
|
# OSX platform wheels are not backward-compatible.
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--platform', 'macosx_10_8_x86_64',
|
|
'fake',
|
|
expect_error=True,
|
|
)
|
|
|
|
# No linux wheel provided for this version.
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--platform', 'linux_x86_64',
|
|
'fake==1',
|
|
expect_error=True,
|
|
)
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--platform', 'linux_x86_64',
|
|
'fake==2'
|
|
)
|
|
result.did_create(
|
|
Path('scratch') / 'fake-2.0-py2.py3-none-linux_x86_64.whl'
|
|
)
|
|
|
|
# Test with multiple supported platforms specified.
|
|
data.reset()
|
|
fake_wheel(data, 'fake-3.0-py2.py3-none-linux_x86_64.whl')
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--platform', 'manylinux1_x86_64', '--platform', 'linux_x86_64',
|
|
'--platform', 'any',
|
|
'fake==3'
|
|
)
|
|
result.did_create(
|
|
Path('scratch') / 'fake-3.0-py2.py3-none-linux_x86_64.whl'
|
|
)
|
|
|
|
|
|
class TestDownloadPlatformManylinuxes(object):
|
|
"""
|
|
"pip download --platform" downloads a .whl archive supported for
|
|
manylinux platforms.
|
|
"""
|
|
|
|
@pytest.mark.parametrize("platform", [
|
|
"linux_x86_64",
|
|
"manylinux1_x86_64",
|
|
"manylinux2010_x86_64",
|
|
"manylinux2014_x86_64",
|
|
])
|
|
def test_download_universal(self, platform, script, data):
|
|
"""
|
|
Universal wheels are returned even for specific platforms.
|
|
"""
|
|
fake_wheel(data, 'fake-1.0-py2.py3-none-any.whl')
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--platform', platform,
|
|
'fake',
|
|
)
|
|
result.did_create(Path('scratch') / 'fake-1.0-py2.py3-none-any.whl')
|
|
|
|
@pytest.mark.parametrize("wheel_abi,platform", [
|
|
("manylinux1_x86_64", "manylinux1_x86_64"),
|
|
("manylinux1_x86_64", "manylinux2010_x86_64"),
|
|
("manylinux2010_x86_64", "manylinux2010_x86_64"),
|
|
("manylinux1_x86_64", "manylinux2014_x86_64"),
|
|
("manylinux2010_x86_64", "manylinux2014_x86_64"),
|
|
("manylinux2014_x86_64", "manylinux2014_x86_64"),
|
|
])
|
|
def test_download_compatible_manylinuxes(
|
|
self, wheel_abi, platform, script, data,
|
|
):
|
|
"""
|
|
Earlier manylinuxes are compatible with later manylinuxes.
|
|
"""
|
|
wheel = 'fake-1.0-py2.py3-none-{}.whl'.format(wheel_abi)
|
|
fake_wheel(data, wheel)
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--platform', platform,
|
|
'fake',
|
|
)
|
|
result.did_create(Path('scratch') / wheel)
|
|
|
|
def test_explicit_platform_only(self, data, script):
|
|
"""
|
|
When specifying the platform, manylinux1 needs to be the
|
|
explicit platform--it won't ever be added to the compatible
|
|
tags.
|
|
"""
|
|
fake_wheel(data, 'fake-1.0-py2.py3-none-linux_x86_64.whl')
|
|
script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--platform', 'linux_x86_64',
|
|
'fake',
|
|
)
|
|
|
|
|
|
def test_download__python_version(script, data):
|
|
"""
|
|
Test using "pip download --python-version" to download a .whl archive
|
|
supported for a specific interpreter
|
|
"""
|
|
fake_wheel(data, 'fake-1.0-py2.py3-none-any.whl')
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--python-version', '2',
|
|
'fake'
|
|
)
|
|
result.did_create(Path('scratch') / 'fake-1.0-py2.py3-none-any.whl')
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--python-version', '3',
|
|
'fake'
|
|
)
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--python-version', '27',
|
|
'fake'
|
|
)
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--python-version', '33',
|
|
'fake'
|
|
)
|
|
|
|
data.reset()
|
|
fake_wheel(data, 'fake-1.0-py2-none-any.whl')
|
|
fake_wheel(data, 'fake-2.0-py3-none-any.whl')
|
|
|
|
# No py3 provided for version 1.
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--python-version', '3',
|
|
'fake==1.0',
|
|
expect_error=True,
|
|
)
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--python-version', '2',
|
|
'fake'
|
|
)
|
|
result.did_create(Path('scratch') / 'fake-1.0-py2-none-any.whl')
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--python-version', '26',
|
|
'fake'
|
|
)
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--python-version', '3',
|
|
'fake'
|
|
)
|
|
result.did_create(Path('scratch') / 'fake-2.0-py3-none-any.whl')
|
|
|
|
|
|
def make_wheel_with_python_requires(script, package_name, python_requires):
|
|
"""
|
|
Create a wheel using the given python_requires.
|
|
|
|
:return: the path to the wheel file.
|
|
"""
|
|
package_dir = script.scratch_path / package_name
|
|
package_dir.mkdir()
|
|
|
|
text = textwrap.dedent("""\
|
|
from setuptools import setup
|
|
setup(name='{}',
|
|
python_requires='{}',
|
|
version='1.0')
|
|
""").format(package_name, python_requires)
|
|
package_dir.joinpath('setup.py').write_text(text)
|
|
script.run(
|
|
'python', 'setup.py', 'bdist_wheel', '--universal', cwd=package_dir,
|
|
allow_stderr_warning=PY2,
|
|
)
|
|
|
|
file_name = '{}-1.0-py2.py3-none-any.whl'.format(package_name)
|
|
return package_dir / 'dist' / file_name
|
|
|
|
|
|
def test_download__python_version_used_for_python_requires(
|
|
script, data, with_wheel,
|
|
):
|
|
"""
|
|
Test that --python-version is used for the Requires-Python check.
|
|
"""
|
|
wheel_path = make_wheel_with_python_requires(
|
|
script, 'mypackage', python_requires='==3.2',
|
|
)
|
|
wheel_dir = os.path.dirname(wheel_path)
|
|
|
|
def make_args(python_version):
|
|
return [
|
|
'download', '--no-index', '--find-links', wheel_dir,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--python-version', python_version,
|
|
'mypackage==1.0',
|
|
]
|
|
|
|
args = make_args('33')
|
|
result = script.pip(*args, expect_error=True)
|
|
expected_err = (
|
|
"ERROR: Package 'mypackage' requires a different Python: "
|
|
"3.3.0 not in '==3.2'"
|
|
)
|
|
assert expected_err in result.stderr, 'stderr: {}'.format(result.stderr)
|
|
|
|
# Now try with a --python-version that satisfies the Requires-Python.
|
|
args = make_args('32')
|
|
script.pip(*args) # no exception
|
|
|
|
|
|
def test_download_specify_abi(script, data):
|
|
"""
|
|
Test using "pip download --abi" to download a .whl archive
|
|
supported for a specific abi
|
|
"""
|
|
fake_wheel(data, 'fake-1.0-py2.py3-none-any.whl')
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--implementation', 'fk',
|
|
'--abi', 'fake_abi',
|
|
'fake'
|
|
)
|
|
result.did_create(Path('scratch') / 'fake-1.0-py2.py3-none-any.whl')
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--implementation', 'fk',
|
|
'--abi', 'none',
|
|
'fake'
|
|
)
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--abi', 'cp27m',
|
|
'fake',
|
|
)
|
|
|
|
data.reset()
|
|
fake_wheel(data, 'fake-1.0-fk2-fakeabi-fake_platform.whl')
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--python-version', '2',
|
|
'--implementation', 'fk',
|
|
'--platform', 'fake_platform',
|
|
'--abi', 'fakeabi',
|
|
'fake'
|
|
)
|
|
result.did_create(
|
|
Path('scratch') / 'fake-1.0-fk2-fakeabi-fake_platform.whl'
|
|
)
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--implementation', 'fk',
|
|
'--platform', 'fake_platform',
|
|
'--abi', 'none',
|
|
'fake',
|
|
expect_error=True,
|
|
)
|
|
|
|
data.reset()
|
|
fake_wheel(data, 'fake-1.0-fk2-otherabi-fake_platform.whl')
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--python-version', '2',
|
|
'--implementation', 'fk',
|
|
'--platform', 'fake_platform',
|
|
'--abi', 'fakeabi', '--abi', 'otherabi', '--abi', 'none',
|
|
'fake'
|
|
)
|
|
result.did_create(
|
|
Path('scratch') / 'fake-1.0-fk2-otherabi-fake_platform.whl'
|
|
)
|
|
|
|
|
|
def test_download_specify_implementation(script, data):
|
|
"""
|
|
Test using "pip download --abi" to download a .whl archive
|
|
supported for a specific abi
|
|
"""
|
|
fake_wheel(data, 'fake-1.0-py2.py3-none-any.whl')
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--implementation', 'fk',
|
|
'fake'
|
|
)
|
|
result.did_create(Path('scratch') / 'fake-1.0-py2.py3-none-any.whl')
|
|
|
|
data.reset()
|
|
fake_wheel(data, 'fake-1.0-fk3-none-any.whl')
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--implementation', 'fk',
|
|
'--python-version', '3',
|
|
'fake'
|
|
)
|
|
result.did_create(Path('scratch') / 'fake-1.0-fk3-none-any.whl')
|
|
|
|
result = script.pip(
|
|
'download', '--no-index', '--find-links', data.find_links,
|
|
'--only-binary=:all:',
|
|
'--dest', '.',
|
|
'--implementation', 'fk',
|
|
'--python-version', '2',
|
|
'fake',
|
|
expect_error=True,
|
|
)
|
|
|
|
|
|
def test_download_exit_status_code_when_no_requirements(script):
|
|
"""
|
|
Test download exit status code when no requirements specified
|
|
"""
|
|
result = script.pip('download', expect_error=True)
|
|
assert (
|
|
"You must give at least one requirement to download" in result.stderr
|
|
)
|
|
assert result.returncode == ERROR
|
|
|
|
|
|
def test_download_exit_status_code_when_blank_requirements_file(script):
|
|
"""
|
|
Test download exit status code when blank requirements file specified
|
|
"""
|
|
script.scratch_path.joinpath("blank.txt").write_text("\n")
|
|
script.pip('download', '-r', 'blank.txt')
|
|
|
|
|
|
def test_download_prefer_binary_when_tarball_higher_than_wheel(script, data):
|
|
fake_wheel(data, 'source-0.8-py2.py3-none-any.whl')
|
|
result = script.pip(
|
|
'download',
|
|
'--prefer-binary',
|
|
'--no-index',
|
|
'-f', data.packages,
|
|
'-d', '.', 'source'
|
|
)
|
|
result.did_create(Path('scratch') / 'source-0.8-py2.py3-none-any.whl')
|
|
result.did_not_create(Path('scratch') / 'source-1.0.tar.gz')
|
|
|
|
|
|
def test_prefer_binary_tarball_higher_than_wheel_req_file(script, data):
|
|
fake_wheel(data, 'source-0.8-py2.py3-none-any.whl')
|
|
script.scratch_path.joinpath("test-req.txt").write_text(textwrap.dedent("""
|
|
--prefer-binary
|
|
source
|
|
"""))
|
|
result = script.pip(
|
|
'download',
|
|
'-r', script.scratch_path / 'test-req.txt',
|
|
'--no-index',
|
|
'-f', data.packages,
|
|
'-d', '.'
|
|
)
|
|
|
|
result.did_create(Path('scratch') / 'source-0.8-py2.py3-none-any.whl')
|
|
result.did_not_create(Path('scratch') / 'source-1.0.tar.gz')
|
|
|
|
|
|
def test_download_prefer_binary_when_wheel_doesnt_satisfy_req(script, data):
|
|
fake_wheel(data, 'source-0.8-py2.py3-none-any.whl')
|
|
script.scratch_path.joinpath("test-req.txt").write_text(textwrap.dedent("""
|
|
source>0.9
|
|
"""))
|
|
|
|
result = script.pip(
|
|
'download',
|
|
'--prefer-binary',
|
|
'--no-index',
|
|
'-f', data.packages,
|
|
'-d', '.',
|
|
'-r', script.scratch_path / 'test-req.txt'
|
|
)
|
|
result.did_create(Path('scratch') / 'source-1.0.tar.gz')
|
|
result.did_not_create(Path('scratch') / 'source-0.8-py2.py3-none-any.whl')
|
|
|
|
|
|
def test_prefer_binary_when_wheel_doesnt_satisfy_req_req_file(script, data):
|
|
fake_wheel(data, 'source-0.8-py2.py3-none-any.whl')
|
|
script.scratch_path.joinpath("test-req.txt").write_text(textwrap.dedent("""
|
|
--prefer-binary
|
|
source>0.9
|
|
"""))
|
|
|
|
result = script.pip(
|
|
'download',
|
|
'--no-index',
|
|
'-f', data.packages,
|
|
'-d', '.',
|
|
'-r', script.scratch_path / 'test-req.txt'
|
|
)
|
|
result.did_create(Path('scratch') / 'source-1.0.tar.gz')
|
|
result.did_not_create(Path('scratch') / 'source-0.8-py2.py3-none-any.whl')
|
|
|
|
|
|
def test_download_prefer_binary_when_only_tarball_exists(script, data):
|
|
result = script.pip(
|
|
'download',
|
|
'--prefer-binary',
|
|
'--no-index',
|
|
'-f', data.packages,
|
|
'-d', '.', 'source'
|
|
)
|
|
result.did_create(Path('scratch') / 'source-1.0.tar.gz')
|
|
|
|
|
|
def test_prefer_binary_when_only_tarball_exists_req_file(script, data):
|
|
script.scratch_path.joinpath("test-req.txt").write_text(textwrap.dedent("""
|
|
--prefer-binary
|
|
source
|
|
"""))
|
|
result = script.pip(
|
|
'download',
|
|
'--no-index',
|
|
'-f', data.packages,
|
|
'-d', '.',
|
|
'-r', script.scratch_path / 'test-req.txt'
|
|
)
|
|
result.did_create(Path('scratch') / 'source-1.0.tar.gz')
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def shared_script(tmpdir_factory, script_factory):
|
|
tmpdir = Path(str(tmpdir_factory.mktemp("download_shared_script")))
|
|
script = script_factory(tmpdir.joinpath("workspace"))
|
|
return script
|
|
|
|
|
|
def test_download_file_url(shared_script, shared_data, tmpdir):
|
|
download_dir = tmpdir / 'download'
|
|
download_dir.mkdir()
|
|
downloaded_path = download_dir / 'simple-1.0.tar.gz'
|
|
|
|
simple_pkg = shared_data.packages / 'simple-1.0.tar.gz'
|
|
|
|
shared_script.pip(
|
|
'download',
|
|
'-d',
|
|
str(download_dir),
|
|
'--no-index',
|
|
path_to_url(str(simple_pkg)),
|
|
)
|
|
|
|
assert downloaded_path.exists()
|
|
assert simple_pkg.read_bytes() == downloaded_path.read_bytes()
|
|
|
|
|
|
def test_download_file_url_existing_ok_download(
|
|
shared_script, shared_data, tmpdir
|
|
):
|
|
download_dir = tmpdir / 'download'
|
|
download_dir.mkdir()
|
|
downloaded_path = download_dir / 'simple-1.0.tar.gz'
|
|
fake_existing_package = shared_data.packages / 'simple-2.0.tar.gz'
|
|
shutil.copy(str(fake_existing_package), str(downloaded_path))
|
|
downloaded_path_bytes = downloaded_path.read_bytes()
|
|
digest = sha256(downloaded_path_bytes).hexdigest()
|
|
|
|
simple_pkg = shared_data.packages / 'simple-1.0.tar.gz'
|
|
url = "{}#sha256={}".format(path_to_url(simple_pkg), digest)
|
|
|
|
shared_script.pip('download', '-d', str(download_dir), url)
|
|
|
|
assert downloaded_path_bytes == downloaded_path.read_bytes()
|
|
|
|
|
|
def test_download_file_url_existing_bad_download(
|
|
shared_script, shared_data, tmpdir
|
|
):
|
|
download_dir = tmpdir / 'download'
|
|
download_dir.mkdir()
|
|
downloaded_path = download_dir / 'simple-1.0.tar.gz'
|
|
fake_existing_package = shared_data.packages / 'simple-2.0.tar.gz'
|
|
shutil.copy(str(fake_existing_package), str(downloaded_path))
|
|
|
|
simple_pkg = shared_data.packages / 'simple-1.0.tar.gz'
|
|
simple_pkg_bytes = simple_pkg.read_bytes()
|
|
digest = sha256(simple_pkg_bytes).hexdigest()
|
|
url = "{}#sha256={}".format(path_to_url(simple_pkg), digest)
|
|
|
|
shared_script.pip('download', '-d', str(download_dir), url)
|
|
|
|
assert simple_pkg_bytes == downloaded_path.read_bytes()
|
|
|
|
|
|
def test_download_http_url_bad_hash(
|
|
shared_script, shared_data, tmpdir, mock_server
|
|
):
|
|
download_dir = tmpdir / 'download'
|
|
download_dir.mkdir()
|
|
downloaded_path = download_dir / 'simple-1.0.tar.gz'
|
|
fake_existing_package = shared_data.packages / 'simple-2.0.tar.gz'
|
|
shutil.copy(str(fake_existing_package), str(downloaded_path))
|
|
|
|
simple_pkg = shared_data.packages / 'simple-1.0.tar.gz'
|
|
simple_pkg_bytes = simple_pkg.read_bytes()
|
|
digest = sha256(simple_pkg_bytes).hexdigest()
|
|
mock_server.set_responses([
|
|
file_response(simple_pkg)
|
|
])
|
|
mock_server.start()
|
|
base_address = 'http://{}:{}'.format(mock_server.host, mock_server.port)
|
|
url = "{}/simple-1.0.tar.gz#sha256={}".format(base_address, digest)
|
|
|
|
shared_script.pip('download', '-d', str(download_dir), url)
|
|
|
|
assert simple_pkg_bytes == downloaded_path.read_bytes()
|
|
|
|
mock_server.stop()
|
|
requests = mock_server.get_requests()
|
|
assert len(requests) == 1
|
|
assert requests[0]['PATH_INFO'] == '/simple-1.0.tar.gz'
|
|
assert requests[0]['HTTP_ACCEPT_ENCODING'] == 'identity'
|