[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