import hashlib import zipfile from io import BytesIO import pytest import wheel.archive import wheel.install def test_verifying_zipfile(): if not hasattr(zipfile.ZipExtFile, '_update_crc'): pytest.skip('No ZIP verification. Missing ZipExtFile._update_crc.') bio = BytesIO() zf = zipfile.ZipFile(bio, 'w') zf.writestr("one", b"first file") zf.writestr("two", b"second file") zf.writestr("three", b"third file") zf.close() # In default mode, VerifyingZipFile checks the hash of any read file # mentioned with set_expected_hash(). Files not mentioned with # set_expected_hash() are not checked. vzf = wheel.install.VerifyingZipFile(bio, 'r') vzf.set_expected_hash("one", hashlib.sha256(b"first file").digest()) vzf.set_expected_hash("three", "blurble") vzf.open("one").read() vzf.open("two").read() pytest.raises(wheel.install.BadWheelFile, vzf.open("three").read) # In strict mode, VerifyingZipFile requires every read file to be # mentioned with set_expected_hash(). vzf.strict = True pytest.raises(wheel.install.BadWheelFile, vzf.open, "two") vzf.set_expected_hash("two", None) vzf.open("two").read() def test_pop_zipfile(): bio = BytesIO() zf = wheel.install.VerifyingZipFile(bio, 'w') zf.writestr("one", b"first file") zf.writestr("two", b"second file") zf.close() pytest.raises(RuntimeError, zf.pop) zf = wheel.install.VerifyingZipFile(bio, 'a') zf.pop() zf.close() zf = wheel.install.VerifyingZipFile(bio, 'r') assert len(zf.infolist()) == 1 def test_zipfile_timestamp(tmpdir, monkeypatch): # An environment variable can be used to influence the timestamp on # TarInfo objects inside the zip. See issue #143. for filename in ('one', 'two', 'three'): tmpdir.join(filename).write(filename + '\n') # The earliest date representable in TarInfos, 1980-01-01 monkeypatch.setenv('SOURCE_DATE_EPOCH', '315576060') zip_base_name = str(tmpdir.join('dummy')) zip_filename = wheel.archive.make_wheelfile_inner(zip_base_name, str(tmpdir)) with zipfile.ZipFile(zip_filename, 'r') as zf: for info in zf.infolist(): assert info.date_time[:3] == (1980, 1, 1) def test_zipfile_attributes(tmpdir): # With the change from ZipFile.write() to .writestr(), we need to manually # set member attributes. files = (('foo', 0o644), ('bar', 0o755)) for filename, mode in files: path = tmpdir.join(filename) path.write(filename + '\n') path.chmod(mode) zip_base_name = str(tmpdir.join('dummy')) zip_filename = wheel.archive.make_wheelfile_inner(zip_base_name, str(tmpdir)) with zipfile.ZipFile(zip_filename, 'r') as zf: for filename, mode in files: info = zf.getinfo(str(tmpdir.join(filename))) assert info.external_attr == (mode | 0o100000) << 16 assert info.compress_type == zipfile.ZIP_DEFLATED