[Python-modules-commits] r32960 - in packages/wheel/trunk/debian (3 files)
barry at users.alioth.debian.org
barry at users.alioth.debian.org
Fri Jun 12 15:06:56 UTC 2015
Date: Friday, June 12, 2015 @ 15:06:55
Author: barry
Revision: 32960
d/patch/reproducible-whls.diff: Added based on initial contribution
from Reiner Herrmann, with further refinements by Barry Warsaw based
on upstream pull request review. (Closes: #776026)
Added:
packages/wheel/trunk/debian/patches/reproducible-whls.diff
packages/wheel/trunk/debian/patches/series
Modified:
packages/wheel/trunk/debian/changelog
Modified: packages/wheel/trunk/debian/changelog
===================================================================
--- packages/wheel/trunk/debian/changelog 2015-06-12 14:54:48 UTC (rev 32959)
+++ packages/wheel/trunk/debian/changelog 2015-06-12 15:06:55 UTC (rev 32960)
@@ -4,6 +4,9 @@
* d/rules:
- Add commented out DH_VERBOSE setting.
- Override the manpage date for reproducible builds. (Closes: #782405)
+ * d/patch/reproducible-whls.diff: Added based on initial contribution
+ from Reiner Herrmann, with further refinements by Barry Warsaw based
+ on upstream pull request review. (Closes: #776026)
* d/watch: Use the pypi.debian.net redirector.
-- Barry Warsaw <barry at debian.org> Wed, 04 Feb 2015 16:44:43 -0500
Added: packages/wheel/trunk/debian/patches/reproducible-whls.diff
===================================================================
--- packages/wheel/trunk/debian/patches/reproducible-whls.diff (rev 0)
+++ packages/wheel/trunk/debian/patches/reproducible-whls.diff 2015-06-12 15:06:55 UTC (rev 32960)
@@ -0,0 +1,172 @@
+Description: .whl files are zips, and as such they contain timestamps. As
+ part of https://wiki.debian.org/ReproducibleBuilds it was requested to be
+ able to build whl files reproducibly (i.e. with a predictable, stable
+ timestamp between builds). While this version of the patch has not yet been
+ merged into upstream, it has been reviewed favorably. The patch can be
+ updated after upstream merge if needed.
+Origin: https://bitbucket.org/pypa/wheel/pull-request/52/apply-the-debian-patch-for-reproducible/diff
+Bug: https://bitbucket.org/pypa/wheel/issue/143/reproducible-whl-files
+Author: Barry Warsaw <barry at debian.org>
+
+--- a/wheel/archive.py
++++ b/wheel/archive.py
+@@ -2,6 +2,8 @@
+ Archive tools for wheel.
+ """
+
++import os
++import time
+ import logging
+ import os.path
+ import zipfile
+@@ -31,6 +33,15 @@
+
+ log.info("creating '%s' and adding '%s' to it", zip_filename, base_dir)
+
++ # Some applications need reproducible .whl files, but they can't do this
++ # without forcing the timestamp of the individual ZipInfo objects. See
++ # issue #143.
++ timestamp = os.environ.get('WHEEL_FORCE_TIMESTAMP')
++ if timestamp is None:
++ date_time = None
++ else:
++ date_time = time.localtime(int(timestamp))[0:6]
++
+ # XXX support bz2, xz when available
+ zip = zipfile.ZipFile(open(zip_filename, "wb+"), "w",
+ compression=zipfile.ZIP_DEFLATED)
+@@ -38,8 +49,14 @@
+ score = {'WHEEL': 1, 'METADATA': 2, 'RECORD': 3}
+ deferred = []
+
+- def writefile(path):
+- zip.write(path, path)
++ def writefile(path, date_time):
++ if date_time is None:
++ st = os.stat(path)
++ mtime = time.localtime(st.st_mtime)
++ date_time = mtime[0:6]
++ zinfo = zipfile.ZipInfo(path, date_time)
++ with open(path, 'rb') as fp:
++ zip.writestr(zinfo, fp.read())
+ log.info("adding '%s'" % path)
+
+ for dirpath, dirnames, filenames in os.walk(base_dir):
+@@ -50,11 +67,11 @@
+ if dirpath.endswith('.dist-info'):
+ deferred.append((score.get(name, 0), path))
+ else:
+- writefile(path)
++ writefile(path, date_time)
+
+ deferred.sort()
+ for score, path in deferred:
+- writefile(path)
++ writefile(path, date_time)
+
+ zip.close()
+
+--- a/wheel/bdist_wheel.py
++++ b/wheel/bdist_wheel.py
+@@ -409,7 +409,7 @@
+ pymeta['extensions']['python.details']['document_names']['license'] = license_filename
+
+ with open(metadata_json_path, "w") as metadata_json:
+- json.dump(pymeta, metadata_json)
++ json.dump(pymeta, metadata_json, sort_keys=True)
+
+ adios(egginfo_path)
+
+--- a/wheel/metadata.py
++++ b/wheel/metadata.py
+@@ -69,7 +69,14 @@
+
+ if may_requires:
+ metadata['run_requires'] = []
+- for key, value in may_requires.items():
++ def sort_key(item):
++ # Both condition and extra could be None, which can't be compared
++ # against strings in Python 3.
++ key, value = item
++ if key.condition is None:
++ return ''
++ return key.condition
++ for key, value in sorted(may_requires.items(), key=sort_key):
+ may_requirement = {'requires':value}
+ if key.extra:
+ may_requirement['extra'] = key.extra
+--- a/wheel/test/test_wheelfile.py
++++ b/wheel/test/test_wheelfile.py
+@@ -1,11 +1,48 @@
++import os
+ import wheel.install
++import wheel.archive
+ import hashlib
+ try:
+ from StringIO import StringIO
+ except ImportError:
+ from io import BytesIO as StringIO
++import codecs
+ import zipfile
+ import pytest
++import shutil
++import tempfile
++from contextlib import contextmanager
++
++ at contextmanager
++def environ(key, value):
++ old_value = os.environ.get(key)
++ try:
++ os.environ[key] = value
++ yield
++ finally:
++ if old_value is None:
++ del os.environ[key]
++ else:
++ os.environ[key] = old_value
++
++ at contextmanager
++def temporary_directory():
++ # tempfile.TemporaryDirectory doesn't exist in Python 2.
++ tempdir = tempfile.mkdtemp()
++ try:
++ yield tempdir
++ finally:
++ shutil.rmtree(tempdir)
++
++ at contextmanager
++def readable_zipfile(path):
++ # zipfile.ZipFile() isn't a context manager under Python 2.
++ zf = zipfile.ZipFile(path, 'r')
++ try:
++ yield zf
++ finally:
++ zf.close()
++
+
+ def test_verifying_zipfile():
+ if not hasattr(zipfile.ZipExtFile, '_update_crc'):
+@@ -66,4 +103,21 @@
+
+ zf = wheel.install.VerifyingZipFile(sio, 'r')
+ assert len(zf.infolist()) == 1
+-
+\ No newline at end of file
++
++def test_zipfile_timestamp():
++ # An environment variable can be used to influence the timestamp on
++ # TarInfo objects inside the zip. See issue #143. TemporaryDirectory is
++ # not a context manager under Python 3.
++ with temporary_directory() as tempdir:
++ for filename in ('one', 'two', 'three'):
++ path = os.path.join(tempdir, filename)
++ with codecs.open(path, 'w', encoding='utf-8') as fp:
++ fp.write(filename + '\n')
++ zip_base_name = os.path.join(tempdir, 'dummy')
++ # The earliest date representable in TarInfos, 1980-01-01
++ with environ('WHEEL_FORCE_TIMESTAMP', '315576060'):
++ zip_filename = wheel.archive.make_wheelfile_inner(
++ zip_base_name, tempdir)
++ with readable_zipfile(zip_filename) as zf:
++ for info in zf.infolist():
++ assert info.date_time[:3] == (1980, 1, 1)
Added: packages/wheel/trunk/debian/patches/series
===================================================================
--- packages/wheel/trunk/debian/patches/series (rev 0)
+++ packages/wheel/trunk/debian/patches/series 2015-06-12 15:06:55 UTC (rev 32960)
@@ -0,0 +1,2 @@
+reproducible-whls.patch
+reproducible-whls.diff
More information about the Python-modules-commits
mailing list