[Python-modules-commits] [wheel] 01/04: Import wheel_0.29.0.orig.tar.gz

Barry Warsaw barry at moszumanska.debian.org
Wed Feb 24 19:43:41 UTC 2016


This is an automated email from the git hooks/post-receive script.

barry pushed a commit to branch master
in repository wheel.

commit 8129a9da2ea1f3143cff05356a11867da78f22bb
Author: Barry Warsaw <barry at python.org>
Date:   Wed Feb 24 14:31:24 2016 -0500

    Import wheel_0.29.0.orig.tar.gz
---
 CHANGES.txt                  | 28 +++++++++++++
 PKG-INFO                     | 39 +++++++++++++++++-
 README.txt                   |  9 ++++
 setup.py                     |  3 +-
 wheel.egg-info/PKG-INFO      | 39 +++++++++++++++++-
 wheel.egg-info/requires.txt  |  4 ++
 wheel/__init__.py            |  2 +-
 wheel/archive.py             | 27 ++++++++++--
 wheel/bdist_wheel.py         | 45 +++++++++++---------
 wheel/metadata.py            |  9 +++-
 wheel/pep425tags.py          | 97 +++++++++++++++++++++++++++++++++++++-------
 wheel/test/test_tagopt.py    | 74 ++++++++++++++++++++++++++++++---
 wheel/test/test_tool.py      | 15 +++----
 wheel/test/test_wheelfile.py | 75 +++++++++++++++++++++++++++++++++-
 wheel/tool/__init__.py       | 28 ++++++-------
 15 files changed, 421 insertions(+), 73 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index afee416..f53b572 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,31 @@
+0.29.0
+======
+- Fix compression type of files in archive (Issue #155, Pull Request #62,
+  thanks Xavier Fernandez)
+
+0.28.0
+======
+- Fix file modes in archive (Issue #154)
+
+0.27.0
+======
+- Support forcing a platform tag using `--plat-name` on pure-Python wheels, as
+  well as nonstandard platform tags on non-pure wheels (Pull Request #60, Issue
+  #144, thanks Andrés Díaz)
+- Add SOABI tags to platform-specific wheels built for Python 2.X (Pull Request
+  #55, Issue #63, Issue #101)
+- Support reproducible wheel files, wheels that can be rebuilt and will hash to
+  the same values as previous builds (Pull Request #52, Issue #143, thanks
+  Barry Warsaw)
+- Support for changes in keyring >= 8.0 (Pull Request #61, thanks Jason R.
+  Coombs)
+- Use the file context manager when checking if dependency_links.txt is empty,
+  fixes problems building wheels under PyPy on Windows  (Issue #150, thanks
+  Cosimo Lupo)
+- Don't attempt to (recursively) create a build directory ending with `..`
+  (invalid on all platforms, but code was only executed on Windows) (Issue #91)
+- Added the PyPA Code of Conduct (Pull Request #56)
+
 0.26.0
 ======
 - Fix multiple entrypoint comparison failure on Python 3 (Issue #148)
diff --git a/PKG-INFO b/PKG-INFO
index dc5fdc0..dace53f 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: wheel
-Version: 0.26.0
+Version: 0.29.0
 Summary: A built-package format for Python.
 Home-page: https://bitbucket.org/pypa/wheel/
 Author: Daniel Holth
@@ -48,6 +48,43 @@ Description: Wheel
         reference implementation.
         
         
+        Code of Conduct
+        ---------------
+        
+        Everyone interacting in the wheel project's codebases, issue trackers, chat
+        rooms, and mailing lists is expected to follow the `PyPA Code of Conduct`_.
+        
+        .. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/
+        
+        
+        
+        0.29.0
+        ======
+        - Fix compression type of files in archive (Issue #155, Pull Request #62,
+          thanks Xavier Fernandez)
+        
+        0.28.0
+        ======
+        - Fix file modes in archive (Issue #154)
+        
+        0.27.0
+        ======
+        - Support forcing a platform tag using `--plat-name` on pure-Python wheels, as
+          well as nonstandard platform tags on non-pure wheels (Pull Request #60, Issue
+          #144, thanks Andrés Díaz)
+        - Add SOABI tags to platform-specific wheels built for Python 2.X (Pull Request
+          #55, Issue #63, Issue #101)
+        - Support reproducible wheel files, wheels that can be rebuilt and will hash to
+          the same values as previous builds (Pull Request #52, Issue #143, thanks
+          Barry Warsaw)
+        - Support for changes in keyring >= 8.0 (Pull Request #61, thanks Jason R.
+          Coombs)
+        - Use the file context manager when checking if dependency_links.txt is empty,
+          fixes problems building wheels under PyPy on Windows  (Issue #150, thanks
+          Cosimo Lupo)
+        - Don't attempt to (recursively) create a build directory ending with `..`
+          (invalid on all platforms, but code was only executed on Windows) (Issue #91)
+        - Added the PyPA Code of Conduct (Pull Request #56)
         
         0.26.0
         ======
diff --git a/README.txt b/README.txt
index 4b14821..7b37ad9 100644
--- a/README.txt
+++ b/README.txt
@@ -39,3 +39,12 @@ Unlike .egg, wheel will be a fully-documented standard at the binary
 level that is truly easy to install even if you do not want to use the
 reference implementation.
 
+
+Code of Conduct
+---------------
+
+Everyone interacting in the wheel project's codebases, issue trackers, chat
+rooms, and mailing lists is expected to follow the `PyPA Code of Conduct`_.
+
+.. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/
+
diff --git a/setup.py b/setup.py
index 62cd584..fc27b85 100644
--- a/setup.py
+++ b/setup.py
@@ -39,8 +39,9 @@ setup(name='wheel',
           ],
       extras_require={
           ':python_version=="2.6"': ['argparse'],
-          'signatures': ['keyring'],
+          'signatures': ['keyring', 'keyrings.alt'],
           'signatures:sys_platform!="win32"': ['pyxdg'],
+          'signatures:python_version=="2.6"': ['importlib'],
           'faster-signatures': ['ed25519ll'],
           'tool': []
           },
diff --git a/wheel.egg-info/PKG-INFO b/wheel.egg-info/PKG-INFO
index dc5fdc0..dace53f 100644
--- a/wheel.egg-info/PKG-INFO
+++ b/wheel.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: wheel
-Version: 0.26.0
+Version: 0.29.0
 Summary: A built-package format for Python.
 Home-page: https://bitbucket.org/pypa/wheel/
 Author: Daniel Holth
@@ -48,6 +48,43 @@ Description: Wheel
         reference implementation.
         
         
+        Code of Conduct
+        ---------------
+        
+        Everyone interacting in the wheel project's codebases, issue trackers, chat
+        rooms, and mailing lists is expected to follow the `PyPA Code of Conduct`_.
+        
+        .. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/
+        
+        
+        
+        0.29.0
+        ======
+        - Fix compression type of files in archive (Issue #155, Pull Request #62,
+          thanks Xavier Fernandez)
+        
+        0.28.0
+        ======
+        - Fix file modes in archive (Issue #154)
+        
+        0.27.0
+        ======
+        - Support forcing a platform tag using `--plat-name` on pure-Python wheels, as
+          well as nonstandard platform tags on non-pure wheels (Pull Request #60, Issue
+          #144, thanks Andrés Díaz)
+        - Add SOABI tags to platform-specific wheels built for Python 2.X (Pull Request
+          #55, Issue #63, Issue #101)
+        - Support reproducible wheel files, wheels that can be rebuilt and will hash to
+          the same values as previous builds (Pull Request #52, Issue #143, thanks
+          Barry Warsaw)
+        - Support for changes in keyring >= 8.0 (Pull Request #61, thanks Jason R.
+          Coombs)
+        - Use the file context manager when checking if dependency_links.txt is empty,
+          fixes problems building wheels under PyPy on Windows  (Issue #150, thanks
+          Cosimo Lupo)
+        - Don't attempt to (recursively) create a build directory ending with `..`
+          (invalid on all platforms, but code was only executed on Windows) (Issue #91)
+        - Added the PyPA Code of Conduct (Pull Request #56)
         
         0.26.0
         ======
diff --git a/wheel.egg-info/requires.txt b/wheel.egg-info/requires.txt
index a497e93..8856ec8 100644
--- a/wheel.egg-info/requires.txt
+++ b/wheel.egg-info/requires.txt
@@ -7,6 +7,10 @@ ed25519ll
 
 [signatures]
 keyring
+keyrings.alt
+
+[signatures:python_version=="2.6"]
+importlib
 
 [signatures:sys_platform!="win32"]
 pyxdg
diff --git a/wheel/__init__.py b/wheel/__init__.py
index 5a57ba7..be2453a 100644
--- a/wheel/__init__.py
+++ b/wheel/__init__.py
@@ -1,2 +1,2 @@
 # __variables__ with double-quoted values will be available in setup.py:
-__version__ = "0.26.0"
+__version__ = "0.29.0"
diff --git a/wheel/archive.py b/wheel/archive.py
index 225d295..f928e6a 100644
--- 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 @@ def make_wheelfile_inner(base_name, base_dir='.'):
 
     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('SOURCE_DATE_EPOCH')
+    if timestamp is None:
+        date_time = None
+    else:
+        date_time = time.gmtime(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,16 @@ def make_wheelfile_inner(base_name, base_dir='.'):
     score = {'WHEEL': 1, 'METADATA': 2, 'RECORD': 3}
     deferred = []
 
-    def writefile(path):
-        zip.write(path, path)
+    def writefile(path, date_time):
+        st = os.stat(path)
+        if date_time is None:
+            mtime = time.gmtime(st.st_mtime)
+            date_time = mtime[0:6]
+        zinfo = zipfile.ZipInfo(path, date_time)
+        zinfo.external_attr = st.st_mode << 16
+        zinfo.compress_type = zipfile.ZIP_DEFLATED
+        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 +69,11 @@ def make_wheelfile_inner(base_name, base_dir='.'):
                 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()
 
diff --git a/wheel/bdist_wheel.py b/wheel/bdist_wheel.py
index aa7c0c7..90db748 100644
--- a/wheel/bdist_wheel.py
+++ b/wheel/bdist_wheel.py
@@ -33,7 +33,7 @@ from distutils.sysconfig import get_python_version
 
 from distutils import log as logger
 
-from .pep425tags import get_abbr_impl, get_impl_ver
+from .pep425tags import get_abbr_impl, get_impl_ver, get_abi_tag
 from .util import native, open_for_csv
 from .archive import archive_wheelfile
 from .pkginfo import read_pkg_info, write_pkg_info
@@ -85,6 +85,7 @@ class bdist_wheel(Command):
         self.bdist_dir = None
         self.data_dir = None
         self.plat_name = None
+        self.plat_tag = None
         self.format = 'zip'
         self.keep_temp = False
         self.dist_dir = None
@@ -97,6 +98,7 @@ class bdist_wheel(Command):
         self.group = None
         self.universal = False
         self.python_tag = 'py' + get_impl_ver()[0]
+        self.plat_name_supplied = False
 
     def finalize_options(self):
         if self.bdist_dir is None:
@@ -104,6 +106,7 @@ class bdist_wheel(Command):
             self.bdist_dir = os.path.join(bdist_base, 'wheel')
 
         self.data_dir = self.wheel_dist_name + '.data'
+        self.plat_name_supplied = self.plat_name is not None
 
         need_options = ('dist_dir', 'plat_name', 'skip_build')
 
@@ -128,30 +131,30 @@ class bdist_wheel(Command):
                          safer_version(self.distribution.get_version())))
 
     def get_tag(self):
-        supported_tags = pep425tags.get_supported()
+        # bdist sets self.plat_name if unset, we should only use it for purepy
+        # wheels if the user supplied it.
+        if self.plat_name_supplied:
+            plat_name = self.plat_name
+        elif self.root_is_pure:
+            plat_name = 'any'
+        else:
+            plat_name = self.plat_name or get_platform()
+        plat_name = plat_name.replace('-', '_').replace('.', '_')
 
         if self.root_is_pure:
             if self.universal:
                 impl = 'py2.py3'
             else:
                 impl = self.python_tag
-            tag = (impl, 'none', 'any')
+            tag = (impl, 'none', plat_name)
         else:
-            plat_name = self.plat_name
-            if plat_name is None:
-                plat_name = get_platform()
-            plat_name = plat_name.replace('-', '_').replace('.', '_')
             impl_name = get_abbr_impl()
             impl_ver = get_impl_ver()
-            # PEP 3149 -- no SOABI in Py 2
-            # For PyPy?
-            # "pp%s%s" % (sys.pypy_version_info.major,
-            # sys.pypy_version_info.minor)
-            abi_tag = sysconfig.get_config_vars().get('SOABI', 'none')
-            if abi_tag.startswith('cpython-'):
-                abi_tag = 'cp' + abi_tag.split('-')[1]
-
+            # PEP 3149
+            abi_tag = str(get_abi_tag()).lower()
             tag = (impl_name + impl_ver, abi_tag, plat_name)
+            supported_tags = pep425tags.get_supported(
+                supplied_platform=plat_name if self.plat_name_supplied else None)
             # XXX switch to this alternate implementation for non-pure:
             assert tag == supported_tags[0]
         return tag
@@ -200,7 +203,7 @@ class bdist_wheel(Command):
         if os.name == 'nt':
             # win32 barfs if any of these are ''; could be '.'?
             # (distutils.command.install:change_roots bug)
-            basedir_observed = os.path.join(self.data_dir, '..')
+            basedir_observed = os.path.normpath(os.path.join(self.data_dir, '..'))
             self.install_libbase = self.install_lib = basedir_observed
 
         setattr(install,
@@ -378,9 +381,11 @@ class bdist_wheel(Command):
                                                      'not-zip-safe',)))
 
             # delete dependency_links if it is only whitespace
-            dependency_links = os.path.join(distinfo_path, 'dependency_links.txt')
-            if not open(dependency_links, 'r').read().strip():
-                adios(dependency_links)
+            dependency_links_path = os.path.join(distinfo_path, 'dependency_links.txt')
+            with open(dependency_links_path, 'r') as dependency_links_file:
+                dependency_links = dependency_links_file.read().strip()
+            if not dependency_links:
+                adios(dependency_links_path)
 
         write_pkg_info(os.path.join(distinfo_path, 'METADATA'), pkg_info)
 
@@ -410,7 +415,7 @@ class bdist_wheel(Command):
             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)
 
diff --git a/wheel/metadata.py b/wheel/metadata.py
index 8756fde..b3cc65c 100644
--- a/wheel/metadata.py
+++ b/wheel/metadata.py
@@ -74,7 +74,14 @@ def handle_requires(metadata, pkg_info, key):
 
     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 = OrderedDict((('requires', value),))
             if key.extra:
                 may_requirement['extra'] = key.extra
diff --git a/wheel/pep425tags.py b/wheel/pep425tags.py
index 2cf2230..106c879 100644
--- a/wheel/pep425tags.py
+++ b/wheel/pep425tags.py
@@ -1,6 +1,7 @@
 """Generate and work with PEP 425 Compatibility Tags."""
 
 import sys
+import warnings
 
 try:
     import sysconfig
@@ -10,6 +11,14 @@ except ImportError:  # pragma nocover
 import distutils.util
 
 
+def get_config_var(var):
+    try:
+        return sysconfig.get_config_var(var)
+    except IOError as e:  # pip Issue #1074
+        warnings.warn("{0}".format(e), RuntimeWarning)
+        return None
+
+
 def get_abbr_impl():
     """Return abbreviated implementation name."""
     if hasattr(sys, 'pypy_version_info'):
@@ -25,19 +34,76 @@ def get_abbr_impl():
 
 def get_impl_ver():
     """Return implementation version."""
-    impl_ver = sysconfig.get_config_var("py_version_nodot")
-    if not impl_ver:
-        impl_ver = ''.join(map(str, sys.version_info[:2]))
+    impl_ver = get_config_var("py_version_nodot")
+    if not impl_ver or get_abbr_impl() == 'pp':
+        impl_ver = ''.join(map(str, get_impl_version_info()))
     return impl_ver
 
 
+def get_impl_version_info():
+    """Return sys.version_info-like tuple for use in decrementing the minor
+    version."""
+    if get_abbr_impl() == 'pp':
+        # as per https://github.com/pypa/pip/issues/2882
+        return (sys.version_info[0], sys.pypy_version_info.major,
+                sys.pypy_version_info.minor)
+    else:
+        return sys.version_info[0], sys.version_info[1]
+
+
+def get_flag(var, fallback, expected=True, warn=True):
+    """Use a fallback method for determining SOABI flags if the needed config
+    var is unset or unavailable."""
+    val = get_config_var(var)
+    if val is None:
+        if warn:
+            warnings.warn("Config variable '{0}' is unset, Python ABI tag may "
+                          "be incorrect".format(var), RuntimeWarning, 2)
+        return fallback()
+    return val == expected
+
+
+def get_abi_tag():
+    """Return the ABI tag based on SOABI (if available) or emulate SOABI
+    (CPython 2, PyPy)."""
+    soabi = get_config_var('SOABI')
+    impl = get_abbr_impl()
+    if not soabi and impl in ('cp', 'pp') and hasattr(sys, 'maxunicode'):
+        d = ''
+        m = ''
+        u = ''
+        if get_flag('Py_DEBUG',
+                    lambda: hasattr(sys, 'gettotalrefcount'),
+                    warn=(impl == 'cp')):
+            d = 'd'
+        if get_flag('WITH_PYMALLOC',
+                    lambda: impl == 'cp',
+                    warn=(impl == 'cp')):
+            m = 'm'
+        if get_flag('Py_UNICODE_SIZE',
+                    lambda: sys.maxunicode == 0x10ffff,
+                    expected=4,
+                    warn=(impl == 'cp' and
+                          sys.version_info < (3, 3))) \
+                and sys.version_info < (3, 3):
+            u = 'u'
+        abi = '%s%s%s%s%s' % (impl, get_impl_ver(), d, m, u)
+    elif soabi and soabi.startswith('cpython-'):
+        abi = 'cp' + soabi.split('-')[1]
+    elif soabi:
+        abi = soabi.replace('.', '_').replace('-', '_')
+    else:
+        abi = None
+    return abi
+
+
 def get_platform():
     """Return our platform name 'win32', 'linux_x86_64'"""
     # XXX remove distutils dependency
     return distutils.util.get_platform().replace('.', '_').replace('-', '_')
 
 
-def get_supported(versions=None):
+def get_supported(versions=None, supplied_platform=None):
     """Return a list of supported tags for each version specified in
     `versions`.
 
@@ -49,18 +115,19 @@ def get_supported(versions=None):
     # Versions must be given with respect to the preference
     if versions is None:
         versions = []
-        major = sys.version_info[0]
+        version_info = get_impl_version_info()
+        major = version_info[:-1]
         # Support all previous minor Python versions.
-        for minor in range(sys.version_info[1], -1, -1):
-            versions.append(''.join(map(str, (major, minor))))
+        for minor in range(version_info[-1], -1, -1):
+            versions.append(''.join(map(str, major + (minor,))))
             
     impl = get_abbr_impl()
     
     abis = []
 
-    soabi = sysconfig.get_config_var('SOABI')
-    if soabi and soabi.startswith('cpython-'):
-        abis[0:0] = ['cp' + soabi.split('-')[1]]
+    abi = get_abi_tag()
+    if abi:
+        abis[0:0] = [abi]
  
     abi3s = set()
     import imp
@@ -72,11 +139,15 @@ def get_supported(versions=None):
 
     abis.append('none')
 
-    arch = get_platform()
+    platforms = []
+    if supplied_platform:
+        platforms.append(supplied_platform)
+    platforms.append(get_platform())
     
     # Current version, current API (built specifically for our Python):
     for abi in abis:
-        supported.append(('%s%s' % (impl, versions[0]), abi, arch))
+        for arch in platforms:
+            supported.append(('%s%s' % (impl, versions[0]), abi, arch))
             
     # No abi / arch, but requires our implementation:
     for i, version in enumerate(versions):
@@ -96,5 +167,3 @@ def get_supported(versions=None):
             supported.append(('py%s' % (version[0]), 'none', 'any'))
         
     return supported
-
-
diff --git a/wheel/test/test_tagopt.py b/wheel/test/test_tagopt.py
index 300fcf9..b0d083e 100644
--- a/wheel/test/test_tagopt.py
+++ b/wheel/test/test_tagopt.py
@@ -1,5 +1,6 @@
 """
-Tests for the bdist_wheel tag options (--python-tag and --universal)
+Tests for the bdist_wheel tag options (--python-tag, --universal, and
+--plat-name)
 """
 
 import sys
@@ -10,27 +11,39 @@ import tempfile
 import subprocess
 
 SETUP_PY = """\
-from setuptools import setup
+from setuptools import setup, Extension
 
 setup(
     name="Test",
     version="1.0",
     author_email="author at example.com",
     py_modules=["test"],
+    {ext_modules}
 )
 """
 
+EXT_MODULES = "ext_modules=[Extension('_test', sources=['test.c'])],"
+
 @pytest.fixture
-def temp_pkg(request):
+def temp_pkg(request, ext=False):
     tempdir = tempfile.mkdtemp()
     def fin():
         shutil.rmtree(tempdir)
     request.addfinalizer(fin)
     temppath = py.path.local(tempdir)
     temppath.join('test.py').write('print("Hello, world")')
-    temppath.join('setup.py').write(SETUP_PY)
+    if ext:
+        temppath.join('test.c').write('#include <stdio.h>')
+        setup_py = SETUP_PY.format(ext_modules=EXT_MODULES)
+    else:
+        setup_py = SETUP_PY.format(ext_modules='')
+    temppath.join('setup.py').write(setup_py)
     return temppath
 
+ at pytest.fixture
+def temp_ext_pkg(request):
+    return temp_pkg(request, ext=True)
+
 def test_default_tag(temp_pkg):
     subprocess.check_call([sys.executable, 'setup.py', 'bdist_wheel'],
             cwd=str(temp_pkg))
@@ -38,7 +51,7 @@ def test_default_tag(temp_pkg):
     assert dist_dir.check(dir=1)
     wheels = dist_dir.listdir()
     assert len(wheels) == 1
-    assert wheels[0].basename.startswith('Test-1.0-py%s-' % (sys.version[0],))
+    assert wheels[0].basename == 'Test-1.0-py%s-none-any.whl' % (sys.version[0],)
     assert wheels[0].ext == '.whl'
 
 def test_explicit_tag(temp_pkg):
@@ -110,3 +123,54 @@ def test_legacy_wheel_section_in_setup_cfg(temp_pkg):
     assert wheels[0].basename.startswith('Test-1.0-py2.py3-')
     assert wheels[0].ext == '.whl'
 
+def test_plat_name_purepy(temp_pkg):
+    subprocess.check_call(
+        [sys.executable, 'setup.py', 'bdist_wheel', '--plat-name=testplat.pure'],
+        cwd=str(temp_pkg))
+    dist_dir = temp_pkg.join('dist')
+    assert dist_dir.check(dir=1)
+    wheels = dist_dir.listdir()
+    assert len(wheels) == 1
+    assert wheels[0].basename.endswith('-testplat_pure.whl')
+    assert wheels[0].ext == '.whl'
+
+def test_plat_name_ext(temp_ext_pkg):
+    try:
+        subprocess.check_call(
+            [sys.executable, 'setup.py', 'bdist_wheel', '--plat-name=testplat.arch'],
+            cwd=str(temp_ext_pkg))
+    except subprocess.CalledProcessError:
+        pytest.skip("Cannot compile C Extensions")
+    dist_dir = temp_ext_pkg.join('dist')
+    assert dist_dir.check(dir=1)
+    wheels = dist_dir.listdir()
+    assert len(wheels) == 1
+    assert wheels[0].basename.endswith('-testplat_arch.whl')
+    assert wheels[0].ext == '.whl'
+
+def test_plat_name_purepy_in_setupcfg(temp_pkg):
+    temp_pkg.join('setup.cfg').write('[bdist_wheel]\nplat_name=testplat.pure')
+    subprocess.check_call(
+        [sys.executable, 'setup.py', 'bdist_wheel'],
+        cwd=str(temp_pkg))
+    dist_dir = temp_pkg.join('dist')
+    assert dist_dir.check(dir=1)
+    wheels = dist_dir.listdir()
+    assert len(wheels) == 1
+    assert wheels[0].basename.endswith('-testplat_pure.whl')
+    assert wheels[0].ext == '.whl'
+
+def test_plat_name_ext_in_setupcfg(temp_ext_pkg):
+    temp_ext_pkg.join('setup.cfg').write('[bdist_wheel]\nplat_name=testplat.arch')
+    try:
+        subprocess.check_call(
+            [sys.executable, 'setup.py', 'bdist_wheel'],
+            cwd=str(temp_ext_pkg))
+    except subprocess.CalledProcessError:
+        pytest.skip("Cannot compile C Extensions")
+    dist_dir = temp_ext_pkg.join('dist')
+    assert dist_dir.check(dir=1)
+    wheels = dist_dir.listdir()
+    assert len(wheels) == 1
+    assert wheels[0].basename.endswith('-testplat_arch.whl')
+    assert wheels[0].ext == '.whl'
diff --git a/wheel/test/test_tool.py b/wheel/test/test_tool.py
index 31a927c..078f1ed 100644
--- a/wheel/test/test_tool.py
+++ b/wheel/test/test_tool.py
@@ -1,17 +1,14 @@
 from .. import tool
 
-def test_keygen():    
+def test_keygen():
     def get_keyring():
         WheelKeys, keyring = tool.get_keyring()
-        
+
         class WheelKeysTest(WheelKeys):
             def save(self):
                 pass
-        
+
         class keyringTest:
-            backend = keyring.backend
-            class backends:
-                file = keyring.backends.file
             @classmethod
             def get_keyring(cls):
                 class keyringTest2:
@@ -20,9 +17,9 @@ def test_keygen():
                         self.pw = c
                     def get_password(self, a, b):
                         return self.pw
-                    
+
                 return keyringTest2()
-        
+
         return WheelKeysTest, keyringTest
-    
+
     tool.keygen(get_keyring=get_keyring)
diff --git a/wheel/test/test_wheelfile.py b/wheel/test/test_wheelfile.py
index e362ceb..181668f 100644
--- 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,40 @@ def test_pop_zipfile():
     
     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('SOURCE_DATE_EPOCH', '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)
+
+def test_zipfile_attributes():
+    # With the change from ZipFile.write() to .writestr(), we need to manually
+    # set member attributes.
+    with temporary_directory() as tempdir:
+        files = (('foo', 0o644), ('bar', 0o755))
+        for filename, mode in files:
+            path = os.path.join(tempdir, filename)
+            with codecs.open(path, 'w', encoding='utf-8') as fp:
+                fp.write(filename + '\n')
+            os.chmod(path, mode)
+        zip_base_name = os.path.join(tempdir, 'dummy')
+        zip_filename = wheel.archive.make_wheelfile_inner(
+            zip_base_name, tempdir)
+        with readable_zipfile(zip_filename) as zf:
+            for filename, mode in files:
+                info = zf.getinfo(os.path.join(tempdir, filename))
+                assert info.external_attr == (mode | 0o100000) << 16
+                assert info.compress_type == zipfile.ZIP_DEFLATED
diff --git a/wheel/tool/__init__.py b/wheel/tool/__init__.py
index a997d1f..95f0a9b 100644
--- a/wheel/tool/__init__.py
+++ b/wheel/tool/__init__.py
@@ -10,7 +10,7 @@ import wheel.paths
 
 from glob import iglob
 from .. import signatures
-from ..util import (urlsafe_b64decode, urlsafe_b64encode, native, binary, 
+from ..util import (urlsafe_b64decode, urlsafe_b64encode, native, binary,
                     matches_requirement)
 from ..install import WheelFile
 
@@ -29,8 +29,9 @@ def get_keyring():
     try:
         from ..signatures import keys
         import keyring
-    except ImportError:
-        raise WheelError("Install wheel[signatures] (requires keyring, pyxdg) for signatures.")
+        assert keyring.get_keyring().priority
+    except (ImportError, AssertionError):
+        raise WheelError("Install wheel[signatures] (requires keyring, keyrings.alt, pyxdg) for signatures.")
     return keys.WheelKeys, keyring
 
 def keygen(get_keyring=get_keyring):
@@ -47,10 +48,7 @@ def keygen(get_keyring=get_keyring):
     kr = keyring.get_keyring()
     kr.set_password("wheel", vk, sk)
     sys.stdout.write("Created Ed25519 keypair with vk={0}\n".format(vk))
-    if isinstance(kr, keyring.backends.file.BaseKeyring):
-        sys.stdout.write("in {0}\n".format(kr.file_path))
-    else:
-        sys.stdout.write("in %r\n" % kr.__class__)
+    sys.stdout.write("in {0!r}\n".format(kr))
 
     sk2 = kr.get_password('wheel', vk)
     if sk2 != sk:
@@ -94,9 +92,9 @@ def sign(wheelfile, replace=False, get_keyring=get_keyring):
 def unsign(wheelfile):
     """
     Remove RECORD.jws from a wheel by truncating the zip file.
-    
-    RECORD.jws must be at the end of the archive. The zip file must be an 
-    ordinary archive, with the compressed files and the directory in the same 
+
+    RECORD.jws must be at the end of the archive. The zip file must be an
+    ordinary archive, with the compressed files and the directory in the same
     order, and without any non-zip content after the truncation point.
     """
     import wheel.install
@@ -109,8 +107,8 @@ def unsign(wheelfile):
 
 def verify(wheelfile):
     """Verify a wheel.
-    
-    The signature will be verified for internal consistency ONLY and printed. 
+
+    The signature will be verified for internal consistency ONLY and printed.
     Wheel's own unpack/install commands verify the manifest against the
     signature and file contents.
     """
@@ -142,7 +140,7 @@ def install(requirements, requirements_file=None,
             wheel_dirs=None, force=False, list_files=False,
             dry_run=False):
     """Install wheels.
-    
+
     :param requirements: A list of requirements or wheel files to install.
     :param requirements_file: A file containing requirements to install.
     :param wheel_dirs: A list of directories to search for wheels.
@@ -243,7 +241,7 @@ def install_scripts(distributions):
 
 def convert(installers, dest_dir, verbose):
     require_pkgresources('wheel convert')
-    
+
     # Only support wheel convert if pkg_resources is present
     from ..wininst2wheel import bdist_wininst2wheel
     from ..egg2wheel import egg2wheel
@@ -318,7 +316,7 @@ def parser():
                                 "but don't actually install anything.")
     install_parser.set_defaults(func=install_f)
 
-    def install_scripts_f(args):        
+    def install_scripts_f(args):
         install_scripts(args.distributions)
     install_scripts_parser = s.add_parser('install-scripts', help='Install console_scripts')
     install_scripts_parser.add_argument('distributions', nargs='*',

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/wheel.git



More information about the Python-modules-commits mailing list