1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00
pip/tests/unit/test_wheel.py

525 lines
17 KiB
Python
Raw Normal View History

2013-05-28 23:58:08 +02:00
"""Tests for wheel binary packages and .dist-info."""
2019-01-24 03:44:54 +01:00
import csv
2018-06-23 23:07:39 +02:00
import logging
2018-06-23 23:10:40 +02:00
import os
2019-01-24 03:44:54 +01:00
import textwrap
2019-12-31 18:32:11 +01:00
from email import message_from_string
2014-04-25 23:42:14 +02:00
2017-05-16 12:16:30 +02:00
import pytest
from mock import patch
from pip._vendor.packaging.requirements import Requirement
from pip._internal.locations import get_scheme
2020-02-01 13:40:20 +01:00
from pip._internal.models.direct_url import (
DIRECT_URL_METADATA_NAME,
ArchiveInfo,
DirectUrl,
)
from pip._internal.models.scheme import Scheme
2019-12-25 13:07:58 +01:00
from pip._internal.operations.build.wheel_legacy import (
get_legacy_build_wheel_path,
)
from pip._internal.operations.install import wheel
from pip._internal.operations.install.wheel import (
2019-09-07 15:59:41 +02:00
MissingCallableSuffix,
_raise_for_invalid_entrypoint,
)
from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.misc import hash_file
from pip._internal.utils.unpacking import unpack_file
from tests.lib import DATA_DIR, assert_paths_equal
def call_get_legacy_build_wheel_path(caplog, names):
wheel_path = get_legacy_build_wheel_path(
names=names,
temp_dir='/tmp/abcd',
name='pendulum',
command_args=['arg1', 'arg2'],
command_output='output line 1\noutput line 2\n',
)
return wheel_path
def test_get_legacy_build_wheel_path(caplog):
actual = call_get_legacy_build_wheel_path(caplog, names=['name'])
assert_paths_equal(actual, '/tmp/abcd/name')
assert not caplog.records
def test_get_legacy_build_wheel_path__no_names(caplog):
caplog.set_level(logging.INFO)
actual = call_get_legacy_build_wheel_path(caplog, names=[])
assert actual is None
assert len(caplog.records) == 1
record = caplog.records[0]
assert record.levelname == 'WARNING'
assert record.message.splitlines() == [
"Legacy build of wheel for 'pendulum' created no files.",
"Command arguments: arg1 arg2",
'Command output: [use --verbose to show]',
]
def test_get_legacy_build_wheel_path__multiple_names(caplog):
caplog.set_level(logging.INFO)
# Deliberately pass the names in non-sorted order.
actual = call_get_legacy_build_wheel_path(
caplog, names=['name2', 'name1'],
)
assert_paths_equal(actual, '/tmp/abcd/name1')
assert len(caplog.records) == 1
record = caplog.records[0]
assert record.levelname == 'WARNING'
assert record.message.splitlines() == [
"Legacy build of wheel for 'pendulum' created more than one file.",
"Filenames (choosing first): ['name1', 'name2']",
"Command arguments: arg1 arg2",
'Command output: [use --verbose to show]',
]
@pytest.mark.parametrize("console_scripts",
["pip = pip._internal.main:pip",
"pip:pip = pip._internal.main:pip"])
def test_get_entrypoints(tmpdir, console_scripts):
entry_points = tmpdir.joinpath("entry_points.txt")
with open(str(entry_points), "w") as fp:
2013-11-19 14:32:58 +01:00
fp.write("""
[console_scripts]
{}
[section]
common:one = module:func
common:two = module:other_func
""".format(console_scripts))
2013-11-19 14:32:58 +01:00
assert wheel.get_entrypoints(str(entry_points)) == (
dict([console_scripts.split(' = ')]),
2013-11-19 14:32:58 +01:00
{},
)
2019-09-07 15:59:41 +02:00
def test_raise_for_invalid_entrypoint_ok():
_raise_for_invalid_entrypoint("hello = hello:main")
@pytest.mark.parametrize("entrypoint", [
"hello = hello",
"hello = hello:",
])
2019-09-07 15:59:41 +02:00
def test_raise_for_invalid_entrypoint_fail(entrypoint):
with pytest.raises(MissingCallableSuffix):
2019-09-07 15:59:41 +02:00
_raise_for_invalid_entrypoint(entrypoint)
@pytest.mark.parametrize("outrows, expected", [
([
('', '', 'a'),
('', '', ''),
], [
('', '', ''),
('', '', 'a'),
]),
([
# Include an int to check avoiding the following error:
# > TypeError: '<' not supported between instances of 'str' and 'int'
('', '', 1),
('', '', ''),
], [
('', '', ''),
('', '', 1),
]),
])
def test_sorted_outrows(outrows, expected):
actual = wheel.sorted_outrows(outrows)
assert actual == expected
2019-01-24 03:44:54 +01:00
def call_get_csv_rows_for_installed(tmpdir, text):
path = tmpdir.joinpath('temp.txt')
path.write_text(text)
2019-01-24 03:44:54 +01:00
# Test that an installed file appearing in RECORD has its filename
# updated in the new RECORD file.
installed = {'a': 'z'}
2019-01-24 03:44:54 +01:00
changed = set()
generated = []
lib_dir = '/lib/dir'
2020-03-29 12:19:34 +02:00
with open(path, **wheel.csv_io_kwargs('r')) as f:
2019-01-24 03:44:54 +01:00
reader = csv.reader(f)
outrows = wheel.get_csv_rows_for_installed(
reader, installed=installed, changed=changed,
generated=generated, lib_dir=lib_dir,
)
return outrows
def test_get_csv_rows_for_installed(tmpdir, caplog):
2019-01-24 03:44:54 +01:00
text = textwrap.dedent("""\
a,b,c
d,e,f
""")
outrows = call_get_csv_rows_for_installed(tmpdir, text)
expected = [
('z', 'b', 'c'),
2019-01-24 03:44:54 +01:00
('d', 'e', 'f'),
]
assert outrows == expected
# Check there were no warnings.
assert len(caplog.records) == 0
2019-01-24 03:44:54 +01:00
def test_get_csv_rows_for_installed__long_lines(tmpdir, caplog):
2019-01-24 03:44:54 +01:00
text = textwrap.dedent("""\
a,b,c,d
e,f,g
h,i,j,k
2019-01-24 03:44:54 +01:00
""")
outrows = call_get_csv_rows_for_installed(tmpdir, text)
expected = [
('z', 'b', 'c', 'd'),
('e', 'f', 'g'),
('h', 'i', 'j', 'k'),
]
assert outrows == expected
messages = [rec.message for rec in caplog.records]
expected = [
"RECORD line has more than three elements: ['a', 'b', 'c', 'd']",
"RECORD line has more than three elements: ['h', 'i', 'j', 'k']"
]
assert messages == expected
2019-01-24 03:44:54 +01:00
@pytest.mark.parametrize("text,expected", [
("Root-Is-Purelib: true", True),
("Root-Is-Purelib: false", False),
("Root-Is-Purelib: hello", False),
("", False),
("root-is-purelib: true", True),
("root-is-purelib: True", True),
])
def test_wheel_root_is_purelib(text, expected):
assert wheel.wheel_root_is_purelib(message_from_string(text)) == expected
2013-05-28 23:58:08 +02:00
class TestWheelFile(object):
2019-09-18 02:18:52 +02:00
def test_unpack_wheel_no_flatten(self, tmpdir):
filepath = os.path.join(DATA_DIR, 'packages',
'meta-1.0-py2.py3-none-any.whl')
unpack_file(filepath, tmpdir)
2019-09-18 02:18:52 +02:00
assert os.path.isdir(os.path.join(tmpdir, 'meta-1.0.dist-info'))
2019-10-12 03:31:35 +02:00
class TestInstallUnpackedWheel(object):
"""
Tests for moving files from wheel src to scheme paths
"""
def prep(self, data, tmpdir):
self.name = 'sample'
self.wheelpath = data.packages.joinpath(
2014-04-25 23:42:14 +02:00
'sample-1.2.0-py2.py3-none-any.whl')
self.req = Requirement('sample')
2014-04-25 23:42:14 +02:00
self.src = os.path.join(tmpdir, 'src')
self.dest = os.path.join(tmpdir, 'dest')
self.scheme = Scheme(
purelib=os.path.join(self.dest, 'lib'),
platlib=os.path.join(self.dest, 'lib'),
headers=os.path.join(self.dest, 'headers'),
scripts=os.path.join(self.dest, 'bin'),
data=os.path.join(self.dest, 'data'),
)
self.src_dist_info = os.path.join(
self.src, 'sample-1.2.0.dist-info')
self.dest_dist_info = os.path.join(
self.scheme.purelib, 'sample-1.2.0.dist-info')
def assert_installed(self):
# lib
assert os.path.isdir(
os.path.join(self.scheme.purelib, 'sample'))
# dist-info
metadata = os.path.join(self.dest_dist_info, 'METADATA')
assert os.path.isfile(metadata)
# data files
data_file = os.path.join(self.scheme.data, 'my_data', 'data_file')
assert os.path.isfile(data_file)
# package data
2014-04-25 23:42:14 +02:00
pkg_data = os.path.join(
self.scheme.purelib, 'sample', 'package_data.dat')
2014-04-25 23:42:14 +02:00
assert os.path.isfile(pkg_data)
def test_std_install(self, data, tmpdir):
self.prep(data, tmpdir)
wheel.install_wheel(
2019-10-12 04:24:50 +02:00
self.name,
self.wheelpath,
2019-10-12 04:24:50 +02:00
scheme=self.scheme,
req_description=str(self.req),
)
self.assert_installed()
2020-02-01 13:40:20 +01:00
def test_std_install_with_direct_url(self, data, tmpdir):
"""Test that install_wheel creates direct_url.json metadata when
provided with a direct_url argument. Also test that the RECORDS
file contains an entry for direct_url.json in that case.
Note direct_url.url is intentionally different from wheelpath,
because wheelpath is typically the result of a local build.
"""
self.prep(data, tmpdir)
direct_url = DirectUrl(
url="file:///home/user/archive.tgz",
info=ArchiveInfo(),
)
wheel.install_wheel(
self.name,
self.wheelpath,
scheme=self.scheme,
req_description=str(self.req),
direct_url=direct_url,
)
direct_url_path = os.path.join(
self.dest_dist_info, DIRECT_URL_METADATA_NAME
)
assert os.path.isfile(direct_url_path)
with open(direct_url_path, 'rb') as f:
expected_direct_url_json = direct_url.to_json()
direct_url_json = f.read().decode("utf-8")
assert direct_url_json == expected_direct_url_json
# check that the direc_url file is part of RECORDS
with open(os.path.join(self.dest_dist_info, "RECORD")) as f:
assert DIRECT_URL_METADATA_NAME in f.read()
def test_install_prefix(self, data, tmpdir):
prefix = os.path.join(os.path.sep, 'some', 'path')
self.prep(data, tmpdir)
scheme = get_scheme(
self.name,
user=False,
home=None,
root=tmpdir,
isolated=False,
prefix=prefix,
)
wheel.install_wheel(
self.name,
self.wheelpath,
scheme=scheme,
2019-10-12 04:24:50 +02:00
req_description=str(self.req),
)
2015-12-05 18:13:31 +01:00
bin_dir = 'Scripts' if WINDOWS else 'bin'
assert os.path.exists(os.path.join(tmpdir, 'some', 'path', bin_dir))
assert os.path.exists(os.path.join(tmpdir, 'some', 'path', 'my_data'))
def test_dist_info_contains_empty_dir(self, data, tmpdir):
"""
Test that empty dirs are not installed
"""
# e.g. https://github.com/pypa/pip/issues/1632#issuecomment-38027275
self.prep(data, tmpdir)
2014-04-25 23:42:14 +02:00
src_empty_dir = os.path.join(
self.src_dist_info, 'empty_dir', 'empty_dir')
os.makedirs(src_empty_dir)
assert os.path.isdir(src_empty_dir)
wheel.install_wheel(
2019-10-12 04:24:50 +02:00
self.name,
self.wheelpath,
2019-10-12 04:24:50 +02:00
scheme=self.scheme,
req_description=str(self.req),
_temp_dir_for_testing=self.src,
2019-10-12 04:24:50 +02:00
)
self.assert_installed()
2014-04-25 23:42:14 +02:00
assert not os.path.isdir(
os.path.join(self.dest_dist_info, 'empty_dir'))
class TestMessageAboutScriptsNotOnPATH(object):
tilde_warning_msg = (
"NOTE: The current PATH contains path(s) starting with `~`, "
"which may not be expanded by all applications."
)
def _template(self, paths, scripts):
with patch.dict('os.environ', {'PATH': os.pathsep.join(paths)}):
return wheel.message_about_scripts_not_on_PATH(scripts)
def test_no_script(self):
retval = self._template(
paths=['/a/b', '/c/d/bin'],
scripts=[]
)
assert retval is None
def test_single_script__single_dir_not_on_PATH(self):
retval = self._template(
paths=['/a/b', '/c/d/bin'],
scripts=['/c/d/foo']
)
assert retval is not None
assert "--no-warn-script-location" in retval
assert "foo is installed in '/c/d'" in retval
assert self.tilde_warning_msg not in retval
def test_two_script__single_dir_not_on_PATH(self):
retval = self._template(
paths=['/a/b', '/c/d/bin'],
scripts=['/c/d/foo', '/c/d/baz']
)
assert retval is not None
assert "--no-warn-script-location" in retval
assert "baz and foo are installed in '/c/d'" in retval
assert self.tilde_warning_msg not in retval
def test_multi_script__multi_dir_not_on_PATH(self):
retval = self._template(
paths=['/a/b', '/c/d/bin'],
scripts=['/c/d/foo', '/c/d/bar', '/c/d/baz', '/a/b/c/spam']
)
assert retval is not None
assert "--no-warn-script-location" in retval
assert "bar, baz and foo are installed in '/c/d'" in retval
assert "spam is installed in '/a/b/c'" in retval
assert self.tilde_warning_msg not in retval
def test_multi_script_all__multi_dir_not_on_PATH(self):
retval = self._template(
paths=['/a/b', '/c/d/bin'],
scripts=[
'/c/d/foo', '/c/d/bar', '/c/d/baz',
'/a/b/c/spam', '/a/b/c/eggs'
]
)
assert retval is not None
assert "--no-warn-script-location" in retval
assert "bar, baz and foo are installed in '/c/d'" in retval
assert "eggs and spam are installed in '/a/b/c'" in retval
assert self.tilde_warning_msg not in retval
def test_two_script__single_dir_on_PATH(self):
retval = self._template(
paths=['/a/b', '/c/d/bin'],
scripts=['/a/b/foo', '/a/b/baz']
)
assert retval is None
def test_multi_script__multi_dir_on_PATH(self):
retval = self._template(
paths=['/a/b', '/c/d/bin'],
scripts=['/a/b/foo', '/a/b/bar', '/a/b/baz', '/c/d/bin/spam']
)
assert retval is None
def test_multi_script__single_dir_on_PATH(self):
retval = self._template(
paths=['/a/b', '/c/d/bin'],
scripts=['/a/b/foo', '/a/b/bar', '/a/b/baz']
)
assert retval is None
def test_single_script__single_dir_on_PATH(self):
retval = self._template(
paths=['/a/b', '/c/d/bin'],
scripts=['/a/b/foo']
)
assert retval is None
def test_PATH_check_case_insensitive_on_windows(self):
retval = self._template(
paths=['C:\\A\\b'],
scripts=['c:\\a\\b\\c', 'C:/A/b/d']
)
if WINDOWS:
assert retval is None
else:
assert retval is not None
assert self.tilde_warning_msg not in retval
def test_trailing_ossep_removal(self):
retval = self._template(
paths=[os.path.join('a', 'b', '')],
scripts=[os.path.join('a', 'b', 'c')]
)
assert retval is None
def test_missing_PATH_env_treated_as_empty_PATH_env(self):
scripts = ['a/b/foo']
env = os.environ.copy()
del env['PATH']
with patch.dict('os.environ', env, clear=True):
retval_missing = wheel.message_about_scripts_not_on_PATH(scripts)
with patch.dict('os.environ', {'PATH': ''}):
retval_empty = wheel.message_about_scripts_not_on_PATH(scripts)
assert retval_missing == retval_empty
Add SHA256 hash of .whl as info output (#5908) * Add SHA256 hash of .whl as info output Currently I'm trying to debug some issues with what appear to be corrupt wheels. It would be very useful to see what pip thought the state of things was as it wrote the wheel output; if a final corrupt distributed file is then different to what pip has saved in its build logs, you know the problem is somewhere after pip but before distribution. Currently we get a log of the initial creation, then the stamp when it gets moved in the final output location, e.g.: creating '/tmp/pip-wheel-71CpBe/foo-1.2.3-py2.py3-none-any.whl ... Stored in directory: /opt/wheel/workspace A lot happens in between this, so my suggestion is we add the final output file and it's hash before the "Stored in directory:", e.g. you now see: Building wheels for collected packages: simple Running setup.py bdist_wheel for simple: started Running setup.py bdist_wheel for simple: finished with status 'done' Finished: simple-3.0-py3-none-any.whl sha256=39005a57a6327972575072af82e11d0817439fe6a069381f6f2a123a8c0bf1cf Stored in directory: /tmp/pytest-of-iwienand/pytest-18/test_pip_wheel_success0/workspace/scratch Successfully built simple Despite the hash being fairly important for things like --require-hashes, AFAICS the final hash is not put in the logs at all currently, so I think this is generically helpful. * Reword wheel hash details output This rewords the output to be more like the form of the preceding messages. Additionally the size is added, since we have calculated it anyway. The output will now look like: Collecting simple==3.0 Building wheels for collected packages: simple Building wheel for simple (setup.py): started Building wheel for simple (setup.py): finished with status 'done' Created wheel for simple: filename=simple-3.0-py3-none-any.whl size=1138 sha256=2a980a802c9d38a24d29aded2dc2df2b080e58370902e5fdf950090ff67aec10 Stored in directory: /tmp/pytest-of-iwienand/pytest-0/test_pip_wheel_success0/workspace/scratch Successfully built simple
2019-06-26 11:44:43 +02:00
def test_no_script_tilde_in_path(self):
retval = self._template(
paths=['/a/b', '/c/d/bin', '~/e', '/f/g~g'],
scripts=[]
)
assert retval is None
def test_multi_script_all_tilde__multi_dir_not_on_PATH(self):
retval = self._template(
paths=['/a/b', '/c/d/bin', '~e/f'],
scripts=[
'/c/d/foo', '/c/d/bar', '/c/d/baz',
'/a/b/c/spam', '/a/b/c/eggs', '/e/f/tilde'
]
)
assert retval is not None
assert "--no-warn-script-location" in retval
assert "bar, baz and foo are installed in '/c/d'" in retval
assert "eggs and spam are installed in '/a/b/c'" in retval
assert "tilde is installed in '/e/f'" in retval
assert self.tilde_warning_msg in retval
def test_multi_script_all_tilde_not_at_start__multi_dir_not_on_PATH(self):
retval = self._template(
paths=['/e/f~f', '/c/d/bin'],
scripts=[
'/c/d/foo', '/c/d/bar', '/c/d/baz',
'/e/f~f/c/spam', '/e/f~f/c/eggs'
]
)
assert retval is not None
assert "--no-warn-script-location" in retval
assert "bar, baz and foo are installed in '/c/d'" in retval
assert "eggs and spam are installed in '/e/f~f/c'" in retval
assert self.tilde_warning_msg not in retval
Add SHA256 hash of .whl as info output (#5908) * Add SHA256 hash of .whl as info output Currently I'm trying to debug some issues with what appear to be corrupt wheels. It would be very useful to see what pip thought the state of things was as it wrote the wheel output; if a final corrupt distributed file is then different to what pip has saved in its build logs, you know the problem is somewhere after pip but before distribution. Currently we get a log of the initial creation, then the stamp when it gets moved in the final output location, e.g.: creating '/tmp/pip-wheel-71CpBe/foo-1.2.3-py2.py3-none-any.whl ... Stored in directory: /opt/wheel/workspace A lot happens in between this, so my suggestion is we add the final output file and it's hash before the "Stored in directory:", e.g. you now see: Building wheels for collected packages: simple Running setup.py bdist_wheel for simple: started Running setup.py bdist_wheel for simple: finished with status 'done' Finished: simple-3.0-py3-none-any.whl sha256=39005a57a6327972575072af82e11d0817439fe6a069381f6f2a123a8c0bf1cf Stored in directory: /tmp/pytest-of-iwienand/pytest-18/test_pip_wheel_success0/workspace/scratch Successfully built simple Despite the hash being fairly important for things like --require-hashes, AFAICS the final hash is not put in the logs at all currently, so I think this is generically helpful. * Reword wheel hash details output This rewords the output to be more like the form of the preceding messages. Additionally the size is added, since we have calculated it anyway. The output will now look like: Collecting simple==3.0 Building wheels for collected packages: simple Building wheel for simple (setup.py): started Building wheel for simple (setup.py): finished with status 'done' Created wheel for simple: filename=simple-3.0-py3-none-any.whl size=1138 sha256=2a980a802c9d38a24d29aded2dc2df2b080e58370902e5fdf950090ff67aec10 Stored in directory: /tmp/pytest-of-iwienand/pytest-0/test_pip_wheel_success0/workspace/scratch Successfully built simple
2019-06-26 11:44:43 +02:00
class TestWheelHashCalculators(object):
def prep(self, tmpdir):
self.test_file = tmpdir.joinpath("hash.file")
Add SHA256 hash of .whl as info output (#5908) * Add SHA256 hash of .whl as info output Currently I'm trying to debug some issues with what appear to be corrupt wheels. It would be very useful to see what pip thought the state of things was as it wrote the wheel output; if a final corrupt distributed file is then different to what pip has saved in its build logs, you know the problem is somewhere after pip but before distribution. Currently we get a log of the initial creation, then the stamp when it gets moved in the final output location, e.g.: creating '/tmp/pip-wheel-71CpBe/foo-1.2.3-py2.py3-none-any.whl ... Stored in directory: /opt/wheel/workspace A lot happens in between this, so my suggestion is we add the final output file and it's hash before the "Stored in directory:", e.g. you now see: Building wheels for collected packages: simple Running setup.py bdist_wheel for simple: started Running setup.py bdist_wheel for simple: finished with status 'done' Finished: simple-3.0-py3-none-any.whl sha256=39005a57a6327972575072af82e11d0817439fe6a069381f6f2a123a8c0bf1cf Stored in directory: /tmp/pytest-of-iwienand/pytest-18/test_pip_wheel_success0/workspace/scratch Successfully built simple Despite the hash being fairly important for things like --require-hashes, AFAICS the final hash is not put in the logs at all currently, so I think this is generically helpful. * Reword wheel hash details output This rewords the output to be more like the form of the preceding messages. Additionally the size is added, since we have calculated it anyway. The output will now look like: Collecting simple==3.0 Building wheels for collected packages: simple Building wheel for simple (setup.py): started Building wheel for simple (setup.py): finished with status 'done' Created wheel for simple: filename=simple-3.0-py3-none-any.whl size=1138 sha256=2a980a802c9d38a24d29aded2dc2df2b080e58370902e5fdf950090ff67aec10 Stored in directory: /tmp/pytest-of-iwienand/pytest-0/test_pip_wheel_success0/workspace/scratch Successfully built simple
2019-06-26 11:44:43 +02:00
# Want this big enough to trigger the internal read loops.
self.test_file_len = 2 * 1024 * 1024
with open(str(self.test_file), "w") as fp:
fp.truncate(self.test_file_len)
self.test_file_hash = \
'5647f05ec18958947d32874eeb788fa396a05d0bab7c1b71f112ceb7e9b31eee'
self.test_file_hash_encoded = \
'sha256=VkfwXsGJWJR9ModO63iPo5agXQurfBtx8RLOt-mzHu4'
def test_hash_file(self, tmpdir):
self.prep(tmpdir)
h, length = hash_file(self.test_file)
Add SHA256 hash of .whl as info output (#5908) * Add SHA256 hash of .whl as info output Currently I'm trying to debug some issues with what appear to be corrupt wheels. It would be very useful to see what pip thought the state of things was as it wrote the wheel output; if a final corrupt distributed file is then different to what pip has saved in its build logs, you know the problem is somewhere after pip but before distribution. Currently we get a log of the initial creation, then the stamp when it gets moved in the final output location, e.g.: creating '/tmp/pip-wheel-71CpBe/foo-1.2.3-py2.py3-none-any.whl ... Stored in directory: /opt/wheel/workspace A lot happens in between this, so my suggestion is we add the final output file and it's hash before the "Stored in directory:", e.g. you now see: Building wheels for collected packages: simple Running setup.py bdist_wheel for simple: started Running setup.py bdist_wheel for simple: finished with status 'done' Finished: simple-3.0-py3-none-any.whl sha256=39005a57a6327972575072af82e11d0817439fe6a069381f6f2a123a8c0bf1cf Stored in directory: /tmp/pytest-of-iwienand/pytest-18/test_pip_wheel_success0/workspace/scratch Successfully built simple Despite the hash being fairly important for things like --require-hashes, AFAICS the final hash is not put in the logs at all currently, so I think this is generically helpful. * Reword wheel hash details output This rewords the output to be more like the form of the preceding messages. Additionally the size is added, since we have calculated it anyway. The output will now look like: Collecting simple==3.0 Building wheels for collected packages: simple Building wheel for simple (setup.py): started Building wheel for simple (setup.py): finished with status 'done' Created wheel for simple: filename=simple-3.0-py3-none-any.whl size=1138 sha256=2a980a802c9d38a24d29aded2dc2df2b080e58370902e5fdf950090ff67aec10 Stored in directory: /tmp/pytest-of-iwienand/pytest-0/test_pip_wheel_success0/workspace/scratch Successfully built simple
2019-06-26 11:44:43 +02:00
assert length == self.test_file_len
assert h.hexdigest() == self.test_file_hash
def test_rehash(self, tmpdir):
self.prep(tmpdir)
h, length = wheel.rehash(self.test_file)
assert length == str(self.test_file_len)
assert h == self.test_file_hash_encoded