mirror of https://github.com/pypa/pip
Move tests for WheelBuilder and friends
This commit is contained in:
parent
647d30ec77
commit
9435050c2d
|
@ -5,10 +5,9 @@ import os
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from mock import Mock, patch
|
from mock import patch
|
||||||
from pip._vendor.packaging.requirements import Requirement
|
from pip._vendor.packaging.requirements import Requirement
|
||||||
|
|
||||||
import pip._internal.wheel_builder
|
|
||||||
from pip._internal import pep425tags, wheel
|
from pip._internal import pep425tags, wheel
|
||||||
from pip._internal.commands.wheel import WheelCommand
|
from pip._internal.commands.wheel import WheelCommand
|
||||||
from pip._internal.exceptions import InvalidWheelFilename, UnsupportedWheel
|
from pip._internal.exceptions import InvalidWheelFilename, UnsupportedWheel
|
||||||
|
@ -22,46 +21,8 @@ from pip._internal.wheel import (
|
||||||
MissingCallableSuffix,
|
MissingCallableSuffix,
|
||||||
_raise_for_invalid_entrypoint,
|
_raise_for_invalid_entrypoint,
|
||||||
)
|
)
|
||||||
from tests.lib import DATA_DIR, _create_test_package, assert_paths_equal
|
from pip._internal.wheel_builder import get_legacy_build_wheel_path
|
||||||
|
from tests.lib import DATA_DIR, assert_paths_equal
|
||||||
|
|
||||||
class ReqMock:
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
name="pendulum",
|
|
||||||
is_wheel=False,
|
|
||||||
editable=False,
|
|
||||||
link=None,
|
|
||||||
constraint=False,
|
|
||||||
source_dir="/tmp/pip-install-123/pendulum",
|
|
||||||
):
|
|
||||||
self.name = name
|
|
||||||
self.is_wheel = is_wheel
|
|
||||||
self.editable = editable
|
|
||||||
self.link = link
|
|
||||||
self.constraint = constraint
|
|
||||||
self.source_dir = source_dir
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"s, expected",
|
|
||||||
[
|
|
||||||
# Trivial.
|
|
||||||
("pip-18.0", True),
|
|
||||||
|
|
||||||
# Ambiguous.
|
|
||||||
("foo-2-2", True),
|
|
||||||
("im-valid", True),
|
|
||||||
|
|
||||||
# Invalid.
|
|
||||||
("invalid", False),
|
|
||||||
("im_invalid", False),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_contains_egg_info(s, expected):
|
|
||||||
result = pip._internal.wheel_builder._contains_egg_info(s)
|
|
||||||
assert result == expected
|
|
||||||
|
|
||||||
|
|
||||||
def make_test_install_req(base_name=None):
|
def make_test_install_req(base_name=None):
|
||||||
|
@ -103,138 +64,9 @@ def test_format_tag(file_tag, expected):
|
||||||
assert actual == expected
|
assert actual == expected
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"req, need_wheel, disallow_binaries, expected",
|
|
||||||
[
|
|
||||||
# pip wheel (need_wheel=True)
|
|
||||||
(ReqMock(), True, False, True),
|
|
||||||
(ReqMock(), True, True, True),
|
|
||||||
(ReqMock(constraint=True), True, False, False),
|
|
||||||
(ReqMock(is_wheel=True), True, False, False),
|
|
||||||
(ReqMock(editable=True), True, False, True),
|
|
||||||
(ReqMock(source_dir=None), True, False, True),
|
|
||||||
(ReqMock(link=Link("git+https://g.c/org/repo")), True, False, True),
|
|
||||||
(ReqMock(link=Link("git+https://g.c/org/repo")), True, True, True),
|
|
||||||
# pip install (need_wheel=False)
|
|
||||||
(ReqMock(), False, False, True),
|
|
||||||
(ReqMock(), False, True, False),
|
|
||||||
(ReqMock(constraint=True), False, False, False),
|
|
||||||
(ReqMock(is_wheel=True), False, False, False),
|
|
||||||
(ReqMock(editable=True), False, False, False),
|
|
||||||
(ReqMock(source_dir=None), False, False, False),
|
|
||||||
# By default (i.e. when binaries are allowed), VCS requirements
|
|
||||||
# should be built in install mode.
|
|
||||||
(ReqMock(link=Link("git+https://g.c/org/repo")), False, False, True),
|
|
||||||
# Disallowing binaries, however, should cause them not to be built.
|
|
||||||
(ReqMock(link=Link("git+https://g.c/org/repo")), False, True, False),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_should_build(req, need_wheel, disallow_binaries, expected):
|
|
||||||
should_build = pip._internal.wheel_builder.should_build(
|
|
||||||
req,
|
|
||||||
need_wheel,
|
|
||||||
check_binary_allowed=lambda req: not disallow_binaries,
|
|
||||||
)
|
|
||||||
assert should_build is expected
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"req, disallow_binaries, expected",
|
|
||||||
[
|
|
||||||
(ReqMock(editable=True), False, False),
|
|
||||||
(ReqMock(source_dir=None), False, False),
|
|
||||||
(ReqMock(link=Link("git+https://g.c/org/repo")), False, False),
|
|
||||||
(ReqMock(link=Link("https://g.c/dist.tgz")), False, False),
|
|
||||||
(ReqMock(link=Link("https://g.c/dist-2.0.4.tgz")), False, True),
|
|
||||||
(ReqMock(editable=True), True, False),
|
|
||||||
(ReqMock(source_dir=None), True, False),
|
|
||||||
(ReqMock(link=Link("git+https://g.c/org/repo")), True, False),
|
|
||||||
(ReqMock(link=Link("https://g.c/dist.tgz")), True, False),
|
|
||||||
(ReqMock(link=Link("https://g.c/dist-2.0.4.tgz")), True, False),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_should_cache(
|
|
||||||
req, disallow_binaries, expected
|
|
||||||
):
|
|
||||||
def check_binary_allowed(req):
|
|
||||||
return not disallow_binaries
|
|
||||||
|
|
||||||
should_cache = pip._internal.wheel_builder.should_cache(
|
|
||||||
req, check_binary_allowed
|
|
||||||
)
|
|
||||||
if not pip._internal.wheel_builder.should_build(
|
|
||||||
req, need_wheel=False, check_binary_allowed=check_binary_allowed
|
|
||||||
):
|
|
||||||
# never cache if pip install (need_wheel=False) would not have built)
|
|
||||||
assert not should_cache
|
|
||||||
assert should_cache is expected
|
|
||||||
|
|
||||||
|
|
||||||
def test_should_cache_git_sha(script, tmpdir):
|
|
||||||
repo_path = _create_test_package(script, name="mypkg")
|
|
||||||
commit = script.run(
|
|
||||||
"git", "rev-parse", "HEAD", cwd=repo_path
|
|
||||||
).stdout.strip()
|
|
||||||
# a link referencing a sha should be cached
|
|
||||||
url = "git+https://g.c/o/r@" + commit + "#egg=mypkg"
|
|
||||||
req = ReqMock(link=Link(url), source_dir=repo_path)
|
|
||||||
assert wheel.should_cache(req, check_binary_allowed=lambda r: True)
|
|
||||||
# a link not referencing a sha should not be cached
|
|
||||||
url = "git+https://g.c/o/r@master#egg=mypkg"
|
|
||||||
req = ReqMock(link=Link(url), source_dir=repo_path)
|
|
||||||
assert not wheel.should_cache(req, check_binary_allowed=lambda r: True)
|
|
||||||
|
|
||||||
|
|
||||||
def test_format_command_result__INFO(caplog):
|
|
||||||
caplog.set_level(logging.INFO)
|
|
||||||
actual = pip._internal.wheel_builder.format_command_result(
|
|
||||||
# Include an argument with a space to test argument quoting.
|
|
||||||
command_args=['arg1', 'second arg'],
|
|
||||||
command_output='output line 1\noutput line 2\n',
|
|
||||||
)
|
|
||||||
assert actual.splitlines() == [
|
|
||||||
"Command arguments: arg1 'second arg'",
|
|
||||||
'Command output: [use --verbose to show]',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('command_output', [
|
|
||||||
# Test trailing newline.
|
|
||||||
'output line 1\noutput line 2\n',
|
|
||||||
# Test no trailing newline.
|
|
||||||
'output line 1\noutput line 2',
|
|
||||||
])
|
|
||||||
def test_format_command_result__DEBUG(caplog, command_output):
|
|
||||||
caplog.set_level(logging.DEBUG)
|
|
||||||
actual = pip._internal.wheel_builder.format_command_result(
|
|
||||||
command_args=['arg1', 'arg2'],
|
|
||||||
command_output=command_output,
|
|
||||||
)
|
|
||||||
assert actual.splitlines() == [
|
|
||||||
"Command arguments: arg1 arg2",
|
|
||||||
'Command output:',
|
|
||||||
'output line 1',
|
|
||||||
'output line 2',
|
|
||||||
'----------------------------------------',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('log_level', ['DEBUG', 'INFO'])
|
|
||||||
def test_format_command_result__empty_output(caplog, log_level):
|
|
||||||
caplog.set_level(log_level)
|
|
||||||
actual = pip._internal.wheel_builder.format_command_result(
|
|
||||||
command_args=['arg1', 'arg2'],
|
|
||||||
command_output='',
|
|
||||||
)
|
|
||||||
assert actual.splitlines() == [
|
|
||||||
"Command arguments: arg1 arg2",
|
|
||||||
'Command output: None',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def call_get_legacy_build_wheel_path(caplog, names):
|
def call_get_legacy_build_wheel_path(caplog, names):
|
||||||
req = make_test_install_req()
|
req = make_test_install_req()
|
||||||
wheel_path = pip._internal.wheel_builder.get_legacy_build_wheel_path(
|
wheel_path = get_legacy_build_wheel_path(
|
||||||
names=names,
|
names=names,
|
||||||
temp_dir='/tmp/abcd',
|
temp_dir='/tmp/abcd',
|
||||||
req=req,
|
req=req,
|
||||||
|
@ -409,22 +241,6 @@ def test_wheel_version(tmpdir, data):
|
||||||
assert not wheel.wheel_version(tmpdir + 'broken')
|
assert not wheel.wheel_version(tmpdir + 'broken')
|
||||||
|
|
||||||
|
|
||||||
def test_python_tag():
|
|
||||||
wheelnames = [
|
|
||||||
'simplewheel-1.0-py2.py3-none-any.whl',
|
|
||||||
'simplewheel-1.0-py27-none-any.whl',
|
|
||||||
'simplewheel-2.0-1-py2.py3-none-any.whl',
|
|
||||||
]
|
|
||||||
newnames = [
|
|
||||||
'simplewheel-1.0-py37-none-any.whl',
|
|
||||||
'simplewheel-1.0-py37-none-any.whl',
|
|
||||||
'simplewheel-2.0-1-py37-none-any.whl',
|
|
||||||
]
|
|
||||||
for name, expected in zip(wheelnames, newnames):
|
|
||||||
result = pip._internal.wheel_builder.replace_python_tag(name, 'py37')
|
|
||||||
assert result == expected
|
|
||||||
|
|
||||||
|
|
||||||
def test_check_compatibility():
|
def test_check_compatibility():
|
||||||
name = 'test'
|
name = 'test'
|
||||||
vc = wheel.VERSION_COMPATIBLE
|
vc = wheel.VERSION_COMPATIBLE
|
||||||
|
@ -744,22 +560,6 @@ class TestInstallUnpackedWheel(object):
|
||||||
os.path.join(self.dest_dist_info, 'empty_dir'))
|
os.path.join(self.dest_dist_info, 'empty_dir'))
|
||||||
|
|
||||||
|
|
||||||
class TestWheelBuilder(object):
|
|
||||||
|
|
||||||
def test_skip_building_wheels(self, caplog):
|
|
||||||
with patch('pip._internal.wheel.WheelBuilder._build_one') \
|
|
||||||
as mock_build_one:
|
|
||||||
wheel_req = Mock(is_wheel=True, editable=False, constraint=False)
|
|
||||||
wb = pip._internal.wheel_builder.WheelBuilder(
|
|
||||||
preparer=Mock(),
|
|
||||||
wheel_cache=Mock(cache_dir=None),
|
|
||||||
)
|
|
||||||
with caplog.at_level(logging.INFO):
|
|
||||||
wb.build([wheel_req])
|
|
||||||
assert "due to already being wheel" in caplog.text
|
|
||||||
assert mock_build_one.mock_calls == []
|
|
||||||
|
|
||||||
|
|
||||||
class TestMessageAboutScriptsNotOnPATH(object):
|
class TestMessageAboutScriptsNotOnPATH(object):
|
||||||
|
|
||||||
def _template(self, paths, scripts):
|
def _template(self, paths, scripts):
|
||||||
|
|
|
@ -0,0 +1,209 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from mock import Mock
|
||||||
|
|
||||||
|
from pip._internal import wheel_builder
|
||||||
|
from pip._internal.models.link import Link
|
||||||
|
from tests.lib import _create_test_package
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"s, expected",
|
||||||
|
[
|
||||||
|
# Trivial.
|
||||||
|
("pip-18.0", True),
|
||||||
|
|
||||||
|
# Ambiguous.
|
||||||
|
("foo-2-2", True),
|
||||||
|
("im-valid", True),
|
||||||
|
|
||||||
|
# Invalid.
|
||||||
|
("invalid", False),
|
||||||
|
("im_invalid", False),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_contains_egg_info(s, expected):
|
||||||
|
result = wheel_builder._contains_egg_info(s)
|
||||||
|
assert result == expected
|
||||||
|
|
||||||
|
|
||||||
|
class ReqMock:
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name="pendulum",
|
||||||
|
is_wheel=False,
|
||||||
|
editable=False,
|
||||||
|
link=None,
|
||||||
|
constraint=False,
|
||||||
|
source_dir="/tmp/pip-install-123/pendulum",
|
||||||
|
):
|
||||||
|
self.name = name
|
||||||
|
self.is_wheel = is_wheel
|
||||||
|
self.editable = editable
|
||||||
|
self.link = link
|
||||||
|
self.constraint = constraint
|
||||||
|
self.source_dir = source_dir
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"req, need_wheel, disallow_binaries, expected",
|
||||||
|
[
|
||||||
|
# pip wheel (need_wheel=True)
|
||||||
|
(ReqMock(), True, False, True),
|
||||||
|
(ReqMock(), True, True, True),
|
||||||
|
(ReqMock(constraint=True), True, False, False),
|
||||||
|
(ReqMock(is_wheel=True), True, False, False),
|
||||||
|
(ReqMock(editable=True), True, False, True),
|
||||||
|
(ReqMock(source_dir=None), True, False, True),
|
||||||
|
(ReqMock(link=Link("git+https://g.c/org/repo")), True, False, True),
|
||||||
|
(ReqMock(link=Link("git+https://g.c/org/repo")), True, True, True),
|
||||||
|
# pip install (need_wheel=False)
|
||||||
|
(ReqMock(), False, False, True),
|
||||||
|
(ReqMock(), False, True, False),
|
||||||
|
(ReqMock(constraint=True), False, False, False),
|
||||||
|
(ReqMock(is_wheel=True), False, False, False),
|
||||||
|
(ReqMock(editable=True), False, False, False),
|
||||||
|
(ReqMock(source_dir=None), False, False, False),
|
||||||
|
# By default (i.e. when binaries are allowed), VCS requirements
|
||||||
|
# should be built in install mode.
|
||||||
|
(ReqMock(link=Link("git+https://g.c/org/repo")), False, False, True),
|
||||||
|
# Disallowing binaries, however, should cause them not to be built.
|
||||||
|
(ReqMock(link=Link("git+https://g.c/org/repo")), False, True, False),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_should_build(req, need_wheel, disallow_binaries, expected):
|
||||||
|
should_build = wheel_builder.should_build(
|
||||||
|
req,
|
||||||
|
need_wheel,
|
||||||
|
check_binary_allowed=lambda req: not disallow_binaries,
|
||||||
|
)
|
||||||
|
assert should_build is expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"req, disallow_binaries, expected",
|
||||||
|
[
|
||||||
|
(ReqMock(editable=True), False, False),
|
||||||
|
(ReqMock(source_dir=None), False, False),
|
||||||
|
(ReqMock(link=Link("git+https://g.c/org/repo")), False, False),
|
||||||
|
(ReqMock(link=Link("https://g.c/dist.tgz")), False, False),
|
||||||
|
(ReqMock(link=Link("https://g.c/dist-2.0.4.tgz")), False, True),
|
||||||
|
(ReqMock(editable=True), True, False),
|
||||||
|
(ReqMock(source_dir=None), True, False),
|
||||||
|
(ReqMock(link=Link("git+https://g.c/org/repo")), True, False),
|
||||||
|
(ReqMock(link=Link("https://g.c/dist.tgz")), True, False),
|
||||||
|
(ReqMock(link=Link("https://g.c/dist-2.0.4.tgz")), True, False),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_should_cache(
|
||||||
|
req, disallow_binaries, expected
|
||||||
|
):
|
||||||
|
def check_binary_allowed(req):
|
||||||
|
return not disallow_binaries
|
||||||
|
|
||||||
|
should_cache = wheel_builder.should_cache(
|
||||||
|
req, check_binary_allowed
|
||||||
|
)
|
||||||
|
if not wheel_builder.should_build(
|
||||||
|
req, need_wheel=False, check_binary_allowed=check_binary_allowed
|
||||||
|
):
|
||||||
|
# never cache if pip install (need_wheel=False) would not have built)
|
||||||
|
assert not should_cache
|
||||||
|
assert should_cache is expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_should_cache_git_sha(script, tmpdir):
|
||||||
|
repo_path = _create_test_package(script, name="mypkg")
|
||||||
|
commit = script.run(
|
||||||
|
"git", "rev-parse", "HEAD", cwd=repo_path
|
||||||
|
).stdout.strip()
|
||||||
|
# a link referencing a sha should be cached
|
||||||
|
url = "git+https://g.c/o/r@" + commit + "#egg=mypkg"
|
||||||
|
req = ReqMock(link=Link(url), source_dir=repo_path)
|
||||||
|
assert wheel_builder.should_cache(req, check_binary_allowed=lambda r: True)
|
||||||
|
# a link not referencing a sha should not be cached
|
||||||
|
url = "git+https://g.c/o/r@master#egg=mypkg"
|
||||||
|
req = ReqMock(link=Link(url), source_dir=repo_path)
|
||||||
|
assert not wheel_builder.should_cache(req, check_binary_allowed=lambda r: True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_format_command_result__INFO(caplog):
|
||||||
|
caplog.set_level(logging.INFO)
|
||||||
|
actual = wheel_builder.format_command_result(
|
||||||
|
# Include an argument with a space to test argument quoting.
|
||||||
|
command_args=['arg1', 'second arg'],
|
||||||
|
command_output='output line 1\noutput line 2\n',
|
||||||
|
)
|
||||||
|
assert actual.splitlines() == [
|
||||||
|
"Command arguments: arg1 'second arg'",
|
||||||
|
'Command output: [use --verbose to show]',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('command_output', [
|
||||||
|
# Test trailing newline.
|
||||||
|
'output line 1\noutput line 2\n',
|
||||||
|
# Test no trailing newline.
|
||||||
|
'output line 1\noutput line 2',
|
||||||
|
])
|
||||||
|
def test_format_command_result__DEBUG(caplog, command_output):
|
||||||
|
caplog.set_level(logging.DEBUG)
|
||||||
|
actual = wheel_builder.format_command_result(
|
||||||
|
command_args=['arg1', 'arg2'],
|
||||||
|
command_output=command_output,
|
||||||
|
)
|
||||||
|
assert actual.splitlines() == [
|
||||||
|
"Command arguments: arg1 arg2",
|
||||||
|
'Command output:',
|
||||||
|
'output line 1',
|
||||||
|
'output line 2',
|
||||||
|
'----------------------------------------',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('log_level', ['DEBUG', 'INFO'])
|
||||||
|
def test_format_command_result__empty_output(caplog, log_level):
|
||||||
|
caplog.set_level(log_level)
|
||||||
|
actual = wheel_builder.format_command_result(
|
||||||
|
command_args=['arg1', 'arg2'],
|
||||||
|
command_output='',
|
||||||
|
)
|
||||||
|
assert actual.splitlines() == [
|
||||||
|
"Command arguments: arg1 arg2",
|
||||||
|
'Command output: None',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_python_tag():
|
||||||
|
wheelnames = [
|
||||||
|
'simplewheel-1.0-py2.py3-none-any.whl',
|
||||||
|
'simplewheel-1.0-py27-none-any.whl',
|
||||||
|
'simplewheel-2.0-1-py2.py3-none-any.whl',
|
||||||
|
]
|
||||||
|
newnames = [
|
||||||
|
'simplewheel-1.0-py37-none-any.whl',
|
||||||
|
'simplewheel-1.0-py37-none-any.whl',
|
||||||
|
'simplewheel-2.0-1-py37-none-any.whl',
|
||||||
|
]
|
||||||
|
for name, expected in zip(wheelnames, newnames):
|
||||||
|
result = wheel_builder.replace_python_tag(name, 'py37')
|
||||||
|
assert result == expected
|
||||||
|
|
||||||
|
|
||||||
|
class TestWheelBuilder(object):
|
||||||
|
|
||||||
|
def test_skip_building_wheels(self, caplog):
|
||||||
|
wb = wheel_builder.WheelBuilder(
|
||||||
|
preparer=Mock(),
|
||||||
|
wheel_cache=Mock(cache_dir=None),
|
||||||
|
)
|
||||||
|
wb._build_one = mock_build_one = Mock()
|
||||||
|
|
||||||
|
wheel_req = Mock(is_wheel=True, editable=False, constraint=False)
|
||||||
|
with caplog.at_level(logging.INFO):
|
||||||
|
wb.build([wheel_req])
|
||||||
|
|
||||||
|
assert "due to already being wheel" in caplog.text
|
||||||
|
assert mock_build_one.mock_calls == []
|
Loading…
Reference in New Issue