diff options
| author | Alex Grönholm <alex.gronholm@nextday.fi> | 2021-12-24 01:27:26 +0200 |
|---|---|---|
| committer | Alex Grönholm <alex.gronholm@nextday.fi> | 2021-12-24 01:45:01 +0200 |
| commit | 5eb690c72ea59bc0f8a2fa34d3993ebe3dbe0d38 (patch) | |
| tree | dff2a2103314f0fe6c5cc53b91a120f59edf78d3 | |
| parent | 64d0b8d779b5b41bacea2ef3b59f3e06f0e683ed (diff) | |
| download | wheel-git-5eb690c72ea59bc0f8a2fa34d3993ebe3dbe0d38.tar.gz | |
Adopted black and reformatted the codebase to match
31 files changed, 1145 insertions, 787 deletions
diff --git a/.github/workflows/codeqa-test.yml b/.github/workflows/codeqa-test.yml index 1450f52..c7c26e8 100644 --- a/.github/workflows/codeqa-test.yml +++ b/.github/workflows/codeqa-test.yml @@ -18,12 +18,13 @@ jobs: path: ~/.cache/pip key: pip-lint - name: Install dependencies - run: pip install flake8 + run: pip install black flake8 + - name: Run black + run: black --check --diff src tests - name: Run flake8 run: flake8 src tests test: - needs: [lint] strategy: fail-fast: false matrix: diff --git a/pyproject.toml b/pyproject.toml index e047bea..02579ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,9 @@ [build-system] requires = ["setuptools >= 45.2.0"] build-backend = "setuptools.build_meta" + +[tool.black] +target-version = ['py37'] +extend-exclude = ''' +^/src/wheel/vendored/ +''' @@ -60,4 +60,4 @@ omit = */vendored/* show_missing = true [flake8] -max-line-length = 99 +max-line-length = 88 diff --git a/src/wheel/__init__.py b/src/wheel/__init__.py index a4b3835..04b7c86 100644 --- a/src/wheel/__init__.py +++ b/src/wheel/__init__.py @@ -1 +1 @@ -__version__ = '0.37.1' +__version__ = "0.37.1" diff --git a/src/wheel/__main__.py b/src/wheel/__main__.py index b3773a2..99993ed 100644 --- a/src/wheel/__main__.py +++ b/src/wheel/__main__.py @@ -6,12 +6,14 @@ import sys def main(): # needed for console script - if __package__ == '': + if __package__ == "": # To be able to run 'python wheel-0.9.whl/wheel': import os.path + path = os.path.dirname(os.path.dirname(__file__)) sys.path[0:0] = [path] import wheel.cli + sys.exit(wheel.cli.main()) diff --git a/src/wheel/bdist_wheel.py b/src/wheel/bdist_wheel.py index ae8da2a..bd08898 100644 --- a/src/wheel/bdist_wheel.py +++ b/src/wheel/bdist_wheel.py @@ -34,11 +34,11 @@ from . import __version__ as wheel_version safe_name = pkg_resources.safe_name safe_version = pkg_resources.safe_version -PY_LIMITED_API_PATTERN = r'cp3\d' +PY_LIMITED_API_PATTERN = r"cp3\d" def python_tag(): - return f'py{sys.version_info[0]}' + return f"py{sys.version_info[0]}" def get_platform(archive_root): @@ -59,41 +59,46 @@ def get_flag(var, fallback, expected=True, warn=True): val = get_config_var(var) if val is None: if warn: - warnings.warn("Config variable '{}' is unset, Python ABI tag may " - "be incorrect".format(var), RuntimeWarning, 2) + warnings.warn( + "Config variable '{}' 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 (PyPy).""" - soabi = get_config_var('SOABI') + soabi = get_config_var("SOABI") impl = tags.interpreter_name() - if not soabi and impl in ('cp', 'pp') and hasattr(sys, 'maxunicode'): - d = '' - m = '' - u = '' - if get_flag('Py_DEBUG', - hasattr(sys, 'gettotalrefcount'), - warn=(impl == 'cp')): - d = 'd' - - if get_flag('WITH_PYMALLOC', - impl == 'cp', - warn=(impl == 'cp' and - sys.version_info < (3, 8))) \ - and sys.version_info < (3, 8): - m = 'm' - - abi = f'{impl}{tags.interpreter_version()}{d}{m}{u}' - elif soabi and soabi.startswith('cpython-'): - abi = 'cp' + soabi.split('-')[1] - elif soabi and soabi.startswith('pypy-'): + if not soabi and impl in ("cp", "pp") and hasattr(sys, "maxunicode"): + d = "" + m = "" + u = "" + if get_flag("Py_DEBUG", hasattr(sys, "gettotalrefcount"), warn=(impl == "cp")): + d = "d" + + if ( + get_flag( + "WITH_PYMALLOC", + impl == "cp", + warn=(impl == "cp" and sys.version_info < (3, 8)), + ) + and sys.version_info < (3, 8) + ): + m = "m" + + abi = f"{impl}{tags.interpreter_version()}{d}{m}{u}" + elif soabi and soabi.startswith("cpython-"): + abi = "cp" + soabi.split("-")[1] + elif soabi and soabi.startswith("pypy-"): # we want something like pypy36-pp73 - abi = '-'.join(soabi.split('-')[:2]) - abi = abi.replace('.', '_').replace('-', '_') + abi = "-".join(soabi.split("-")[:2]) + abi = abi.replace(".", "_").replace("-", "_") elif soabi: - abi = soabi.replace('.', '_').replace('-', '_') + abi = soabi.replace(".", "_").replace("-", "_") else: abi = None @@ -101,11 +106,11 @@ def get_abi_tag(): def safer_name(name): - return safe_name(name).replace('-', '_') + return safe_name(name).replace("-", "_") def safer_version(version): - return safe_version(version).replace('-', '_') + return safe_version(version).replace("-", "_") def remove_readonly(func, path, excinfo): @@ -116,61 +121,78 @@ def remove_readonly(func, path, excinfo): class bdist_wheel(Command): - description = 'create a wheel distribution' - - supported_compressions = OrderedDict([ - ('stored', ZIP_STORED), - ('deflated', ZIP_DEFLATED) - ]) - - user_options = [('bdist-dir=', 'b', - "temporary directory for creating the distribution"), - ('plat-name=', 'p', - "platform name to embed in generated filenames " - "(default: %s)" % get_platform(None)), - ('keep-temp', 'k', - "keep the pseudo-installation tree around after " + - "creating the distribution archive"), - ('dist-dir=', 'd', - "directory to put final built distributions in"), - ('skip-build', None, - "skip rebuilding everything (for testing/debugging)"), - ('relative', None, - "build the archive using relative paths " - "(default: false)"), - ('owner=', 'u', - "Owner name used when creating a tar file" - " [default: current user]"), - ('group=', 'g', - "Group name used when creating a tar file" - " [default: current group]"), - ('universal', None, - "make a universal wheel" - " (default: false)"), - ('compression=', None, - "zipfile compression (one of: {})" - " (default: 'deflated')" - .format(', '.join(supported_compressions))), - ('python-tag=', None, - "Python implementation compatibility tag" - " (default: '%s')" % (python_tag())), - ('build-number=', None, - "Build number for this particular version. " - "As specified in PEP-0427, this must start with a digit. " - "[default: None]"), - ('py-limited-api=', None, - "Python tag (cp32|cp33|cpNN) for abi3 wheel tag" - " (default: false)"), - ] - - boolean_options = ['keep-temp', 'skip-build', 'relative', 'universal'] + description = "create a wheel distribution" + + supported_compressions = OrderedDict( + [("stored", ZIP_STORED), ("deflated", ZIP_DEFLATED)] + ) + + user_options = [ + ("bdist-dir=", "b", "temporary directory for creating the distribution"), + ( + "plat-name=", + "p", + "platform name to embed in generated filenames " + "(default: %s)" % get_platform(None), + ), + ( + "keep-temp", + "k", + "keep the pseudo-installation tree around after " + + "creating the distribution archive", + ), + ("dist-dir=", "d", "directory to put final built distributions in"), + ("skip-build", None, "skip rebuilding everything (for testing/debugging)"), + ( + "relative", + None, + "build the archive using relative paths " "(default: false)", + ), + ( + "owner=", + "u", + "Owner name used when creating a tar file" " [default: current user]", + ), + ( + "group=", + "g", + "Group name used when creating a tar file" " [default: current group]", + ), + ("universal", None, "make a universal wheel" " (default: false)"), + ( + "compression=", + None, + "zipfile compression (one of: {})" + " (default: 'deflated')".format(", ".join(supported_compressions)), + ), + ( + "python-tag=", + None, + "Python implementation compatibility tag" + " (default: '%s')" % (python_tag()), + ), + ( + "build-number=", + None, + "Build number for this particular version. " + "As specified in PEP-0427, this must start with a digit. " + "[default: None]", + ), + ( + "py-limited-api=", + None, + "Python tag (cp32|cp33|cpNN) for abi3 wheel tag" " (default: false)", + ), + ] + + boolean_options = ["keep-temp", "skip-build", "relative", "universal"] def initialize_options(self): self.bdist_dir = None self.data_dir = None self.plat_name = None self.plat_tag = None - self.format = 'zip' + self.format = "zip" self.keep_temp = False self.dist_dir = None self.egginfo_dir = None @@ -180,7 +202,7 @@ class bdist_wheel(Command): self.owner = None self.group = None self.universal = False - self.compression = 'deflated' + self.compression = "deflated" self.python_tag = python_tag() self.build_number = None self.py_limited_api = False @@ -188,35 +210,37 @@ class bdist_wheel(Command): def finalize_options(self): if self.bdist_dir is None: - bdist_base = self.get_finalized_command('bdist').bdist_base - self.bdist_dir = os.path.join(bdist_base, 'wheel') + bdist_base = self.get_finalized_command("bdist").bdist_base + self.bdist_dir = os.path.join(bdist_base, "wheel") - self.data_dir = self.wheel_dist_name + '.data' + self.data_dir = self.wheel_dist_name + ".data" self.plat_name_supplied = self.plat_name is not None try: self.compression = self.supported_compressions[self.compression] except KeyError: - raise ValueError(f'Unsupported compression: {self.compression}') + raise ValueError(f"Unsupported compression: {self.compression}") - need_options = ('dist_dir', 'plat_name', 'skip_build') + need_options = ("dist_dir", "plat_name", "skip_build") - self.set_undefined_options('bdist', - *zip(need_options, need_options)) + self.set_undefined_options("bdist", *zip(need_options, need_options)) - self.root_is_pure = not (self.distribution.has_ext_modules() - or self.distribution.has_c_libraries()) + self.root_is_pure = not ( + self.distribution.has_ext_modules() or self.distribution.has_c_libraries() + ) - if self.py_limited_api and not re.match(PY_LIMITED_API_PATTERN, self.py_limited_api): + if self.py_limited_api and not re.match( + PY_LIMITED_API_PATTERN, self.py_limited_api + ): raise ValueError("py-limited-api must match '%s'" % PY_LIMITED_API_PATTERN) # Support legacy [wheel] section for setting universal - wheel = self.distribution.get_option_dict('wheel') - if 'universal' in wheel: + wheel = self.distribution.get_option_dict("wheel") + if "universal" in wheel: # please don't define this in your global configs - logger.warn('The [wheel] section is deprecated. Use [bdist_wheel] instead.') - val = wheel['universal'][1].strip() - if val.lower() in ('1', 'true', 'yes'): + logger.warn("The [wheel] section is deprecated. Use [bdist_wheel] instead.") + val = wheel["universal"][1].strip() + if val.lower() in ("1", "true", "yes"): self.universal = True if self.build_number is not None and not self.build_number[:1].isdigit(): @@ -225,11 +249,13 @@ class bdist_wheel(Command): @property def wheel_dist_name(self): """Return distribution full name with - replaced with _""" - components = (safer_name(self.distribution.get_name()), - safer_version(self.distribution.get_version())) + components = ( + safer_name(self.distribution.get_name()), + safer_version(self.distribution.get_version()), + ) if self.build_number: components += (self.build_number,) - return '-'.join(components) + return "-".join(components) def get_tag(self): # bdist sets self.plat_name if unset, we should only use it for purepy @@ -237,7 +263,7 @@ class bdist_wheel(Command): if self.plat_name_supplied: plat_name = self.plat_name elif self.root_is_pure: - plat_name = 'any' + plat_name = "any" else: # macosx contains system version in platform name so need special handle if self.plat_name and not self.plat_name.startswith("macosx"): @@ -251,47 +277,52 @@ class bdist_wheel(Command): # modules, use the default platform name. plat_name = get_platform(self.bdist_dir) - if plat_name in ('linux-x86_64', 'linux_x86_64') and sys.maxsize == 2147483647: - plat_name = 'linux_i686' + if ( + plat_name in ("linux-x86_64", "linux_x86_64") + and sys.maxsize == 2147483647 + ): + plat_name = "linux_i686" - plat_name = plat_name.lower().replace('-', '_').replace('.', '_') + plat_name = plat_name.lower().replace("-", "_").replace(".", "_") if self.root_is_pure: if self.universal: - impl = 'py2.py3' + impl = "py2.py3" else: impl = self.python_tag - tag = (impl, 'none', plat_name) + tag = (impl, "none", plat_name) else: impl_name = tags.interpreter_name() impl_ver = tags.interpreter_version() impl = impl_name + impl_ver # We don't work on CPython 3.1, 3.0. - if self.py_limited_api and (impl_name + impl_ver).startswith('cp3'): + if self.py_limited_api and (impl_name + impl_ver).startswith("cp3"): impl = self.py_limited_api - abi_tag = 'abi3' + abi_tag = "abi3" else: abi_tag = str(get_abi_tag()).lower() tag = (impl, abi_tag, plat_name) # issue gh-374: allow overriding plat_name - supported_tags = [(t.interpreter, t.abi, plat_name) - for t in tags.sys_tags()] - assert tag in supported_tags, f"would build wheel with unsupported tag {tag}" + supported_tags = [ + (t.interpreter, t.abi, plat_name) for t in tags.sys_tags() + ] + assert ( + tag in supported_tags + ), f"would build wheel with unsupported tag {tag}" return tag def run(self): - build_scripts = self.reinitialize_command('build_scripts') - build_scripts.executable = 'python' + build_scripts = self.reinitialize_command("build_scripts") + build_scripts.executable = "python" build_scripts.force = True - build_ext = self.reinitialize_command('build_ext') + build_ext = self.reinitialize_command("build_ext") build_ext.inplace = False if not self.skip_build: - self.run_command('build') + self.run_command("build") - install = self.reinitialize_command('install', - reinit_subcommands=True) + install = self.reinitialize_command("install", reinit_subcommands=True) install.root = self.bdist_dir install.compile = False install.skip_build = self.skip_build @@ -300,31 +331,31 @@ class bdist_wheel(Command): # A wheel without setuptools scripts is more cross-platform. # Use the (undocumented) `no_ep` option to setuptools' # install_scripts command to avoid creating entry point scripts. - install_scripts = self.reinitialize_command('install_scripts') + install_scripts = self.reinitialize_command("install_scripts") install_scripts.no_ep = True # Use a custom scheme for the archive, because we have to decide # at installation time which scheme to use. - for key in ('headers', 'scripts', 'data', 'purelib', 'platlib'): - setattr(install, - 'install_' + key, - os.path.join(self.data_dir, key)) + for key in ("headers", "scripts", "data", "purelib", "platlib"): + setattr(install, "install_" + key, os.path.join(self.data_dir, key)) - basedir_observed = '' + basedir_observed = "" - if os.name == 'nt': + if os.name == "nt": # win32 barfs if any of these are ''; could be '.'? # (distutils.command.install:change_roots bug) - basedir_observed = os.path.normpath(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, - 'install_purelib' if self.root_is_pure else 'install_platlib', - basedir_observed) + setattr( + install, + "install_purelib" if self.root_is_pure else "install_platlib", + basedir_observed, + ) logger.info("installing to %s", self.bdist_dir) - self.run_command('install') + self.run_command("install") impl_tag, abi_tag, plat_tag = self.get_tag() archive_basename = f"{self.wheel_dist_name}-{impl_tag}-{abi_tag}-{plat_tag}" @@ -332,13 +363,14 @@ class bdist_wheel(Command): archive_root = self.bdist_dir else: archive_root = os.path.join( - self.bdist_dir, - self._ensure_relative(install.install_base)) + self.bdist_dir, self._ensure_relative(install.install_base) + ) - self.set_undefined_options('install_egg_info', ('target', 'egginfo_dir')) - distinfo_dirname = '{}-{}.dist-info'.format( + self.set_undefined_options("install_egg_info", ("target", "egginfo_dir")) + distinfo_dirname = "{}-{}.dist-info".format( safer_name(self.distribution.get_name()), - safer_version(self.distribution.get_version())) + safer_version(self.distribution.get_version()), + ) distinfo_dir = os.path.join(self.bdist_dir, distinfo_dirname) self.egg2dist(self.egginfo_dir, distinfo_dir) @@ -348,44 +380,49 @@ class bdist_wheel(Command): if not os.path.exists(self.dist_dir): os.makedirs(self.dist_dir) - wheel_path = os.path.join(self.dist_dir, archive_basename + '.whl') - with WheelFile(wheel_path, 'w', self.compression) as wf: + wheel_path = os.path.join(self.dist_dir, archive_basename + ".whl") + with WheelFile(wheel_path, "w", self.compression) as wf: wf.write_files(archive_root) # Add to 'Distribution.dist_files' so that the "upload" command works - getattr(self.distribution, 'dist_files', []).append( - ('bdist_wheel', - '{}.{}'.format(*sys.version_info[:2]), # like 3.7 - wheel_path)) + getattr(self.distribution, "dist_files", []).append( + ( + "bdist_wheel", + "{}.{}".format(*sys.version_info[:2]), # like 3.7 + wheel_path, + ) + ) if not self.keep_temp: - logger.info('removing %s', self.bdist_dir) + logger.info("removing %s", self.bdist_dir) if not self.dry_run: rmtree(self.bdist_dir, onerror=remove_readonly) - def write_wheelfile(self, wheelfile_base, generator='bdist_wheel (' + wheel_version + ')'): + def write_wheelfile( + self, wheelfile_base, generator="bdist_wheel (" + wheel_version + ")" + ): from email.message import Message msg = Message() - msg['Wheel-Version'] = '1.0' # of the spec - msg['Generator'] = generator - msg['Root-Is-Purelib'] = str(self.root_is_pure).lower() + msg["Wheel-Version"] = "1.0" # of the spec + msg["Generator"] = generator + msg["Root-Is-Purelib"] = str(self.root_is_pure).lower() if self.build_number is not None: - msg['Build'] = self.build_number + msg["Build"] = self.build_number # Doesn't work for bdist_wininst impl_tag, abi_tag, plat_tag = self.get_tag() - for impl in impl_tag.split('.'): - for abi in abi_tag.split('.'): - for plat in plat_tag.split('.'): - msg['Tag'] = '-'.join((impl, abi, plat)) + for impl in impl_tag.split("."): + for abi in abi_tag.split("."): + for plat in plat_tag.split("."): + msg["Tag"] = "-".join((impl, abi, plat)) - wheelfile_path = os.path.join(wheelfile_base, 'WHEEL') - logger.info('creating %s', wheelfile_path) + wheelfile_path = os.path.join(wheelfile_base, "WHEEL") + logger.info("creating %s", wheelfile_path) buffer = BytesIO() BytesGenerator(buffer, maxheaderlen=0).flatten(msg) - with open(wheelfile_path, 'wb') as f: - f.write(buffer.getvalue().replace(b'\r\n', b'\r')) + with open(wheelfile_path, "wb") as f: + f.write(buffer.getvalue().replace(b"\r\n", b"\r")) def _ensure_relative(self, path): # copied from dir_util, deleted @@ -396,34 +433,42 @@ class bdist_wheel(Command): @property def license_paths(self): - metadata = self.distribution.get_option_dict('metadata') + metadata = self.distribution.get_option_dict("metadata") files = set() - patterns = sorted({ - option for option in metadata.get('license_files', ('', ''))[1].split() - }) + patterns = sorted( + {option for option in metadata.get("license_files", ("", ""))[1].split()} + ) - if 'license_file' in metadata: - warnings.warn('The "license_file" option is deprecated. Use ' - '"license_files" instead.', DeprecationWarning) - files.add(metadata['license_file'][1]) + if "license_file" in metadata: + warnings.warn( + 'The "license_file" option is deprecated. Use ' + '"license_files" instead.', + DeprecationWarning, + ) + files.add(metadata["license_file"][1]) - if 'license_file' not in metadata and 'license_files' not in metadata: - patterns = ('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*') + if "license_file" not in metadata and "license_files" not in metadata: + patterns = ("LICEN[CS]E*", "COPYING*", "NOTICE*", "AUTHORS*") for pattern in patterns: for path in iglob(pattern): - if path.endswith('~'): - logger.debug('ignoring license file "%s" as it looks like a backup', path) + if path.endswith("~"): + logger.debug( + 'ignoring license file "%s" as it looks like a backup', path + ) continue if path not in files and os.path.isfile(path): - logger.info('adding license file "%s" (matched pattern "%s")', path, pattern) + logger.info( + 'adding license file "%s" (matched pattern "%s")', path, pattern + ) files.add(path) return files def egg2dist(self, egginfo_path, distinfo_path): """Convert an .egg-info directory into a .dist-info directory""" + def adios(p): """Appropriately delete directory, file or link.""" if os.path.exists(p) and not os.path.islink(p) and os.path.isdir(p): @@ -439,7 +484,8 @@ class bdist_wheel(Command): # to name the archive file. Check for this case and report # accordingly. import glob - pat = os.path.join(os.path.dirname(egginfo_path), '*.egg-info') + + pat = os.path.join(os.path.dirname(egginfo_path), "*.egg-info") possible = glob.glob(pat) err = f"Egg metadata expected at {egginfo_path} but not found" if possible: @@ -455,23 +501,29 @@ class bdist_wheel(Command): os.mkdir(distinfo_path) else: # .egg-info is a directory - pkginfo_path = os.path.join(egginfo_path, 'PKG-INFO') + pkginfo_path = os.path.join(egginfo_path, "PKG-INFO") pkg_info = pkginfo_to_metadata(egginfo_path, pkginfo_path) # ignore common egg metadata that is useless to wheel - shutil.copytree(egginfo_path, distinfo_path, - ignore=lambda x, y: {'PKG-INFO', 'requires.txt', 'SOURCES.txt', - 'not-zip-safe'} - ) + shutil.copytree( + egginfo_path, + distinfo_path, + ignore=lambda x, y: { + "PKG-INFO", + "requires.txt", + "SOURCES.txt", + "not-zip-safe", + }, + ) # delete dependency_links if it is only whitespace - dependency_links_path = os.path.join(distinfo_path, 'dependency_links.txt') + dependency_links_path = os.path.join(distinfo_path, "dependency_links.txt") with open(dependency_links_path) 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) + write_pkg_info(os.path.join(distinfo_path, "METADATA"), pkg_info) for license_path in self.license_paths: filename = os.path.basename(license_path) diff --git a/src/wheel/cli/__init__.py b/src/wheel/cli/__init__.py index c8a3b35..31ac4c8 100644 --- a/src/wheel/cli/__init__.py +++ b/src/wheel/cli/__init__.py @@ -20,21 +20,25 @@ class WheelError(Exception): def unpack_f(args): from .unpack import unpack + unpack(args.wheelfile, args.dest) def pack_f(args): from .pack import pack + pack(args.directory, args.dest_dir, args.build_number) def convert_f(args): from .convert import convert + convert(args.files, args.dest_dir, args.verbose) def version_f(args): from .. import __version__ + print("wheel %s" % __version__) @@ -42,30 +46,41 @@ def parser(): p = argparse.ArgumentParser() s = p.add_subparsers(help="commands") - unpack_parser = s.add_parser('unpack', help='Unpack wheel') - unpack_parser.add_argument('--dest', '-d', help='Destination directory', - default='.') - unpack_parser.add_argument('wheelfile', help='Wheel file') + unpack_parser = s.add_parser("unpack", help="Unpack wheel") + unpack_parser.add_argument( + "--dest", "-d", help="Destination directory", default="." + ) + unpack_parser.add_argument("wheelfile", help="Wheel file") unpack_parser.set_defaults(func=unpack_f) - repack_parser = s.add_parser('pack', help='Repack wheel') - repack_parser.add_argument('directory', help='Root directory of the unpacked wheel') - repack_parser.add_argument('--dest-dir', '-d', default=os.path.curdir, - help="Directory to store the wheel (default %(default)s)") - repack_parser.add_argument('--build-number', help="Build tag to use in the wheel name") + repack_parser = s.add_parser("pack", help="Repack wheel") + repack_parser.add_argument("directory", help="Root directory of the unpacked wheel") + repack_parser.add_argument( + "--dest-dir", + "-d", + default=os.path.curdir, + help="Directory to store the wheel (default %(default)s)", + ) + repack_parser.add_argument( + "--build-number", help="Build tag to use in the wheel name" + ) repack_parser.set_defaults(func=pack_f) - convert_parser = s.add_parser('convert', help='Convert egg or wininst to wheel') - convert_parser.add_argument('files', nargs='*', help='Files to convert') - convert_parser.add_argument('--dest-dir', '-d', default=os.path.curdir, - help="Directory to store wheels (default %(default)s)") - convert_parser.add_argument('--verbose', '-v', action='store_true') + convert_parser = s.add_parser("convert", help="Convert egg or wininst to wheel") + convert_parser.add_argument("files", nargs="*", help="Files to convert") + convert_parser.add_argument( + "--dest-dir", + "-d", + default=os.path.curdir, + help="Directory to store wheels (default %(default)s)", + ) + convert_parser.add_argument("--verbose", "-v", action="store_true") convert_parser.set_defaults(func=convert_f) - version_parser = s.add_parser('version', help='Print version and exit') + version_parser = s.add_parser("version", help="Print version and exit") version_parser.set_defaults(func=version_f) - help_parser = s.add_parser('help', help='Show this help') + help_parser = s.add_parser("help", help="Show this help") help_parser.set_defaults(func=lambda args: p.print_help()) return p @@ -74,7 +89,7 @@ def parser(): def main(): p = parser() args = p.parse_args() - if not hasattr(args, 'func'): + if not hasattr(args, "func"): p.print_help() else: try: diff --git a/src/wheel/cli/convert.py b/src/wheel/cli/convert.py index 5c76d5f..b2f685f 100755 --- a/src/wheel/cli/convert.py +++ b/src/wheel/cli/convert.py @@ -10,11 +10,14 @@ from ..bdist_wheel import bdist_wheel from ..wheelfile import WheelFile from . import WheelError, require_pkgresources -egg_info_re = re.compile(r''' +egg_info_re = re.compile( + r""" (?P<name>.+?)-(?P<ver>.+?) (-(?P<pyver>py\d\.\d+) (-(?P<arch>.+?))? - )?.egg$''', re.VERBOSE) + )?.egg$""", + re.VERBOSE, +) class _bdist_wheel_tag(bdist_wheel): @@ -37,7 +40,7 @@ def egg2wheel(egg_path, dest_dir): filename = os.path.basename(egg_path) match = egg_info_re.match(filename) if not match: - raise WheelError(f'Invalid egg file name: {filename}') + raise WheelError(f"Invalid egg file name: {filename}") egg_info = match.groupdict() dir = tempfile.mkdtemp(suffix="_e2w") @@ -54,16 +57,16 @@ def egg2wheel(egg_path, dest_dir): else: shutil.copytree(src, os.path.join(dir, pth)) - pyver = egg_info['pyver'] + pyver = egg_info["pyver"] if pyver: - pyver = egg_info['pyver'] = pyver.replace('.', '') + pyver = egg_info["pyver"] = pyver.replace(".", "") - arch = (egg_info['arch'] or 'any').replace('.', '_').replace('-', '_') + arch = (egg_info["arch"] or "any").replace(".", "_").replace("-", "_") # assume all binary eggs are for CPython - abi = 'cp' + pyver[2:] if arch != 'any' else 'none' + abi = "cp" + pyver[2:] if arch != "any" else "none" - root_is_purelib = egg_info['arch'] is None + root_is_purelib = egg_info["arch"] is None if root_is_purelib: bw = bdist_wheel(dist.Distribution()) else: @@ -72,16 +75,16 @@ def egg2wheel(egg_path, dest_dir): bw.root_is_pure = root_is_purelib bw.python_tag = pyver bw.plat_name_supplied = True - bw.plat_name = egg_info['arch'] or 'any' + bw.plat_name = egg_info["arch"] or "any" if not root_is_purelib: bw.full_tag_supplied = True bw.full_tag = (pyver, abi, arch) - dist_info_dir = os.path.join(dir, '{name}-{ver}.dist-info'.format(**egg_info)) - bw.egg2dist(os.path.join(dir, 'EGG-INFO'), dist_info_dir) - bw.write_wheelfile(dist_info_dir, generator='egg2wheel') - wheel_name = '{name}-{ver}-{pyver}-{}-{}.whl'.format(abi, arch, **egg_info) - with WheelFile(os.path.join(dest_dir, wheel_name), 'w') as wf: + dist_info_dir = os.path.join(dir, "{name}-{ver}.dist-info".format(**egg_info)) + bw.egg2dist(os.path.join(dir, "EGG-INFO"), dist_info_dir) + bw.write_wheelfile(dist_info_dir, generator="egg2wheel") + wheel_name = "{name}-{ver}-{pyver}-{}-{}.whl".format(abi, arch, **egg_info) + with WheelFile(os.path.join(dest_dir, wheel_name), "w") as wf: wf.write_files(dir) shutil.rmtree(dir) @@ -128,34 +131,34 @@ def parse_wininst_info(wininfo_name, egginfo_name): # Parse the wininst filename # 1. Distribution name (up to the first '-') - w_name, sep, rest = wininfo_name.partition('-') + w_name, sep, rest = wininfo_name.partition("-") if not sep: raise ValueError(f"Installer filename {wininfo_name} is not valid") # Strip '.exe' rest = rest[:-4] # 2. Python version (from the last '-', must start with 'py') - rest2, sep, w_pyver = rest.rpartition('-') - if sep and w_pyver.startswith('py'): + rest2, sep, w_pyver = rest.rpartition("-") + if sep and w_pyver.startswith("py"): rest = rest2 - w_pyver = w_pyver.replace('.', '') + w_pyver = w_pyver.replace(".", "") else: # Not version specific - use py2.py3. While it is possible that # pure-Python code is not compatible with both Python 2 and 3, there # is no way of knowing from the wininst format, so we assume the best # here (the user can always manually rename the wheel to be more # restrictive if needed). - w_pyver = 'py2.py3' + w_pyver = "py2.py3" # 3. Version and architecture - w_ver, sep, w_arch = rest.rpartition('.') + w_ver, sep, w_arch = rest.rpartition(".") if not sep: raise ValueError(f"Installer filename {wininfo_name} is not valid") if egginfo: - w_name = egginfo.group('name') - w_ver = egginfo.group('ver') + w_name = egginfo.group("name") + w_ver = egginfo.group("ver") - return {'name': w_name, 'ver': w_ver, 'arch': w_arch, 'pyver': w_pyver} + return {"name": w_name, "ver": w_ver, "arch": w_arch, "pyver": w_pyver} def wininst2wheel(path, dest_dir): @@ -163,7 +166,7 @@ def wininst2wheel(path, dest_dir): # Search for egg-info in the archive egginfo_name = None for filename in bdw.namelist(): - if '.egg-info' in filename: + if ".egg-info" in filename: egginfo_name = filename break @@ -171,13 +174,13 @@ def wininst2wheel(path, dest_dir): root_is_purelib = True for zipinfo in bdw.infolist(): - if zipinfo.filename.startswith('PLATLIB'): + if zipinfo.filename.startswith("PLATLIB"): root_is_purelib = False break if root_is_purelib: - paths = {'purelib': ''} + paths = {"purelib": ""} else: - paths = {'platlib': ''} + paths = {"platlib": ""} dist_info = "%(name)s-%(ver)s" % info datadir = "%s.data/" % dist_info @@ -185,13 +188,13 @@ def wininst2wheel(path, dest_dir): # rewrite paths to trick ZipFile into extracting an egg # XXX grab wininst .ini - between .exe, padding, and first zip file. members = [] - egginfo_name = '' + egginfo_name = "" for zipinfo in bdw.infolist(): - key, basename = zipinfo.filename.split('/', 1) + key, basename = zipinfo.filename.split("/", 1) key = key.lower() basepath = paths.get(key, None) if basepath is None: - basepath = datadir + key.lower() + '/' + basepath = datadir + key.lower() + "/" oldname = zipinfo.filename newname = basepath + basename zipinfo.filename = newname @@ -202,27 +205,27 @@ def wininst2wheel(path, dest_dir): members.append(newname) # Remember egg-info name for the egg2dist call below if not egginfo_name: - if newname.endswith('.egg-info'): + if newname.endswith(".egg-info"): egginfo_name = newname - elif '.egg-info/' in newname: - egginfo_name, sep, _ = newname.rpartition('/') + elif ".egg-info/" in newname: + egginfo_name, sep, _ = newname.rpartition("/") dir = tempfile.mkdtemp(suffix="_b2w") bdw.extractall(dir, members) # egg2wheel - abi = 'none' - pyver = info['pyver'] - arch = (info['arch'] or 'any').replace('.', '_').replace('-', '_') + abi = "none" + pyver = info["pyver"] + arch = (info["arch"] or "any").replace(".", "_").replace("-", "_") # Wininst installers always have arch even if they are not # architecture-specific (because the format itself is). # So, assume the content is architecture-neutral if root is purelib. if root_is_purelib: - arch = 'any' + arch = "any" # If the installer is architecture-specific, it's almost certainly also # CPython-specific. - if arch != 'any': - pyver = pyver.replace('py', 'cp') - wheel_name = '-'.join((dist_info, pyver, abi, arch)) + if arch != "any": + pyver = pyver.replace("py", "cp") + wheel_name = "-".join((dist_info, pyver, abi, arch)) if root_is_purelib: bw = bdist_wheel(dist.Distribution()) else: @@ -231,18 +234,18 @@ def wininst2wheel(path, dest_dir): bw.root_is_pure = root_is_purelib bw.python_tag = pyver bw.plat_name_supplied = True - bw.plat_name = info['arch'] or 'any' + bw.plat_name = info["arch"] or "any" if not root_is_purelib: bw.full_tag_supplied = True bw.full_tag = (pyver, abi, arch) - dist_info_dir = os.path.join(dir, '%s.dist-info' % dist_info) + dist_info_dir = os.path.join(dir, "%s.dist-info" % dist_info) bw.egg2dist(os.path.join(dir, egginfo_name), dist_info_dir) - bw.write_wheelfile(dist_info_dir, generator='wininst2wheel') + bw.write_wheelfile(dist_info_dir, generator="wininst2wheel") wheel_path = os.path.join(dest_dir, wheel_name) - with WheelFile(wheel_path, 'w') as wf: + with WheelFile(wheel_path, "w") as wf: wf.write_files(dir) shutil.rmtree(dir) @@ -250,11 +253,11 @@ def wininst2wheel(path, dest_dir): def convert(files, dest_dir, verbose): # Only support wheel convert if pkg_resources is present - require_pkgresources('wheel convert') + require_pkgresources("wheel convert") for pat in files: for installer in iglob(pat): - if os.path.splitext(installer)[1] == '.egg': + if os.path.splitext(installer)[1] == ".egg": conv = egg2wheel else: conv = wininst2wheel diff --git a/src/wheel/cli/pack.py b/src/wheel/cli/pack.py index 094eb67..349f722 100644 --- a/src/wheel/cli/pack.py +++ b/src/wheel/cli/pack.py @@ -5,7 +5,7 @@ from wheel.cli import WheelError from wheel.wheelfile import WheelFile DIST_INFO_RE = re.compile(r"^(?P<namever>(?P<name>.+?)-(?P<ver>\d.*?))\.dist-info$") -BUILD_NUM_RE = re.compile(br'Build: (\d\w*)$') +BUILD_NUM_RE = re.compile(br"Build: (\d\w*)$") def pack(directory, dest_dir, build_number): @@ -18,44 +18,54 @@ def pack(directory, dest_dir, build_number): :param dest_dir: Destination directory (defaults to the current directory) """ # Find the .dist-info directory - dist_info_dirs = [fn for fn in os.listdir(directory) - if os.path.isdir(os.path.join(directory, fn)) and DIST_INFO_RE.match(fn)] + dist_info_dirs = [ + fn + for fn in os.listdir(directory) + if os.path.isdir(os.path.join(directory, fn)) and DIST_INFO_RE.match(fn) + ] if len(dist_info_dirs) > 1: - raise WheelError(f'Multiple .dist-info directories found in {directory}') + raise WheelError(f"Multiple .dist-info directories found in {directory}") elif not dist_info_dirs: - raise WheelError(f'No .dist-info directories found in {directory}') + raise WheelError(f"No .dist-info directories found in {directory}") # Determine the target wheel filename dist_info_dir = dist_info_dirs[0] - name_version = DIST_INFO_RE.match(dist_info_dir).group('namever') + name_version = DIST_INFO_RE.match(dist_info_dir).group("namever") # Read the tags and the existing build number from .dist-info/WHEEL existing_build_number = None - wheel_file_path = os.path.join(directory, dist_info_dir, 'WHEEL') + wheel_file_path = os.path.join(directory, dist_info_dir, "WHEEL") with open(wheel_file_path) as f: tags = [] for line in f: - if line.startswith('Tag: '): - tags.append(line.split(' ')[1].rstrip()) - elif line.startswith('Build: '): - existing_build_number = line.split(' ')[1].rstrip() + if line.startswith("Tag: "): + tags.append(line.split(" ")[1].rstrip()) + elif line.startswith("Build: "): + existing_build_number = line.split(" ")[1].rstrip() if not tags: - raise WheelError('No tags present in {}/WHEEL; cannot determine target wheel filename' - .format(dist_info_dir)) + raise WheelError( + "No tags present in {}/WHEEL; cannot determine target wheel " + "filename".format(dist_info_dir) + ) # Set the wheel file name and add/replace/remove the Build tag in .dist-info/WHEEL build_number = build_number if build_number is not None else existing_build_number if build_number is not None: if build_number: - name_version += '-' + build_number + name_version += "-" + build_number if build_number != existing_build_number: - replacement = ('Build: %s\r\n' % build_number).encode('ascii') if build_number else b'' - with open(wheel_file_path, 'rb+') as f: + replacement = ( + ("Build: %s\r\n" % build_number).encode("ascii") + if build_number + else b"" + ) + with open(wheel_file_path, "rb+") as f: wheel_file_content = f.read() - wheel_file_content, num_replaced = BUILD_NUM_RE.subn(replacement, - wheel_file_content) + wheel_file_content, num_replaced = BUILD_NUM_RE.subn( + replacement, wheel_file_content + ) if not num_replaced: wheel_file_content += replacement @@ -64,15 +74,15 @@ def pack(directory, dest_dir, build_number): f.write(wheel_file_content) # Reassemble the tags for the wheel file - impls = sorted({tag.split('-')[0] for tag in tags}) - abivers = sorted({tag.split('-')[1] for tag in tags}) - platforms = sorted({tag.split('-')[2] for tag in tags}) - tagline = '-'.join(['.'.join(impls), '.'.join(abivers), '.'.join(platforms)]) + impls = sorted({tag.split("-")[0] for tag in tags}) + abivers = sorted({tag.split("-")[1] for tag in tags}) + platforms = sorted({tag.split("-")[2] for tag in tags}) + tagline = "-".join([".".join(impls), ".".join(abivers), ".".join(platforms)]) # Repack the wheel - wheel_path = os.path.join(dest_dir, f'{name_version}-{tagline}.whl') - with WheelFile(wheel_path, 'w') as wf: - print(f"Repacking wheel as {wheel_path}...", end='', flush=True) + wheel_path = os.path.join(dest_dir, f"{name_version}-{tagline}.whl") + with WheelFile(wheel_path, "w") as wf: + print(f"Repacking wheel as {wheel_path}...", end="", flush=True) wf.write_files(directory) - print('OK') + print("OK") diff --git a/src/wheel/cli/unpack.py b/src/wheel/cli/unpack.py index 3f3963c..ffd0e81 100644 --- a/src/wheel/cli/unpack.py +++ b/src/wheel/cli/unpack.py @@ -3,7 +3,7 @@ import os.path from ..wheelfile import WheelFile -def unpack(path, dest='.'): +def unpack(path, dest="."): """Unpack a wheel. Wheel content will be unpacked to {dest}/{name}-{ver}, where {name} @@ -13,9 +13,9 @@ def unpack(path, dest='.'): :param dest: Destination directory (default to current directory). """ with WheelFile(path) as wf: - namever = wf.parsed_filename.group('namever') + namever = wf.parsed_filename.group("namever") destination = os.path.join(dest, namever) - print(f"Unpacking to: {destination}...", end='', flush=True) + print(f"Unpacking to: {destination}...", end="", flush=True) wf.extractall(destination) - print('OK') + print("OK") diff --git a/src/wheel/macosx_libfile.py b/src/wheel/macosx_libfile.py index 29b0395..c96e7cb 100644 --- a/src/wheel/macosx_libfile.py +++ b/src/wheel/macosx_libfile.py @@ -44,26 +44,29 @@ import sys """here the needed const and struct from mach-o header files""" -FAT_MAGIC = 0xcafebabe -FAT_CIGAM = 0xbebafeca -FAT_MAGIC_64 = 0xcafebabf -FAT_CIGAM_64 = 0xbfbafeca -MH_MAGIC = 0xfeedface -MH_CIGAM = 0xcefaedfe -MH_MAGIC_64 = 0xfeedfacf -MH_CIGAM_64 = 0xcffaedfe +FAT_MAGIC = 0xCAFEBABE +FAT_CIGAM = 0xBEBAFECA +FAT_MAGIC_64 = 0xCAFEBABF +FAT_CIGAM_64 = 0xBFBAFECA +MH_MAGIC = 0xFEEDFACE +MH_CIGAM = 0xCEFAEDFE +MH_MAGIC_64 = 0xFEEDFACF +MH_CIGAM_64 = 0xCFFAEDFE LC_VERSION_MIN_MACOSX = 0x24 LC_BUILD_VERSION = 0x32 -CPU_TYPE_ARM64 = 0x0100000c +CPU_TYPE_ARM64 = 0x0100000C mach_header_fields = [ - ("magic", ctypes.c_uint32), ("cputype", ctypes.c_int), - ("cpusubtype", ctypes.c_int), ("filetype", ctypes.c_uint32), - ("ncmds", ctypes.c_uint32), ("sizeofcmds", ctypes.c_uint32), - ("flags", ctypes.c_uint32) - ] + ("magic", ctypes.c_uint32), + ("cputype", ctypes.c_int), + ("cpusubtype", ctypes.c_int), + ("filetype", ctypes.c_uint32), + ("ncmds", ctypes.c_uint32), + ("sizeofcmds", ctypes.c_uint32), + ("flags", ctypes.c_uint32), +] """ struct mach_header { uint32_t magic; /* mach magic number identifier */ @@ -101,9 +104,11 @@ struct fat_header { """ fat_arch_fields = [ - ("cputype", ctypes.c_int), ("cpusubtype", ctypes.c_int), - ("offset", ctypes.c_uint32), ("size", ctypes.c_uint32), - ("align", ctypes.c_uint32) + ("cputype", ctypes.c_int), + ("cpusubtype", ctypes.c_int), + ("offset", ctypes.c_uint32), + ("size", ctypes.c_uint32), + ("align", ctypes.c_uint32), ] """ struct fat_arch { @@ -116,9 +121,12 @@ struct fat_arch { """ fat_arch_64_fields = [ - ("cputype", ctypes.c_int), ("cpusubtype", ctypes.c_int), - ("offset", ctypes.c_uint64), ("size", ctypes.c_uint64), - ("align", ctypes.c_uint32), ("reserved", ctypes.c_uint32) + ("cputype", ctypes.c_int), + ("cpusubtype", ctypes.c_int), + ("offset", ctypes.c_uint64), + ("size", ctypes.c_uint64), + ("align", ctypes.c_uint32), + ("reserved", ctypes.c_uint32), ] """ struct fat_arch_64 { @@ -135,13 +143,18 @@ segment_base_fields = [("cmd", ctypes.c_uint32), ("cmdsize", ctypes.c_uint32)] """base for reading segment info""" segment_command_fields = [ - ("cmd", ctypes.c_uint32), ("cmdsize", ctypes.c_uint32), - ("segname", ctypes.c_char * 16), ("vmaddr", ctypes.c_uint32), - ("vmsize", ctypes.c_uint32), ("fileoff", ctypes.c_uint32), - ("filesize", ctypes.c_uint32), ("maxprot", ctypes.c_int), - ("initprot", ctypes.c_int), ("nsects", ctypes.c_uint32), + ("cmd", ctypes.c_uint32), + ("cmdsize", ctypes.c_uint32), + ("segname", ctypes.c_char * 16), + ("vmaddr", ctypes.c_uint32), + ("vmsize", ctypes.c_uint32), + ("fileoff", ctypes.c_uint32), + ("filesize", ctypes.c_uint32), + ("maxprot", ctypes.c_int), + ("initprot", ctypes.c_int), + ("nsects", ctypes.c_uint32), ("flags", ctypes.c_uint32), - ] +] """ struct segment_command { /* for 32-bit architectures */ uint32_t cmd; /* LC_SEGMENT */ @@ -160,13 +173,18 @@ typedef int vm_prot_t; """ segment_command_fields_64 = [ - ("cmd", ctypes.c_uint32), ("cmdsize", ctypes.c_uint32), - ("segname", ctypes.c_char * 16), ("vmaddr", ctypes.c_uint64), - ("vmsize", ctypes.c_uint64), ("fileoff", ctypes.c_uint64), - ("filesize", ctypes.c_uint64), ("maxprot", ctypes.c_int), - ("initprot", ctypes.c_int), ("nsects", ctypes.c_uint32), + ("cmd", ctypes.c_uint32), + ("cmdsize", ctypes.c_uint32), + ("segname", ctypes.c_char * 16), + ("vmaddr", ctypes.c_uint64), + ("vmsize", ctypes.c_uint64), + ("fileoff", ctypes.c_uint64), + ("filesize", ctypes.c_uint64), + ("maxprot", ctypes.c_int), + ("initprot", ctypes.c_int), + ("nsects", ctypes.c_uint32), ("flags", ctypes.c_uint32), - ] +] """ struct segment_command_64 { /* for 64-bit architectures */ uint32_t cmd; /* LC_SEGMENT_64 */ @@ -183,8 +201,10 @@ struct segment_command_64 { /* for 64-bit architectures */ }; """ -version_min_command_fields = segment_base_fields + \ - [("version", ctypes.c_uint32), ("sdk", ctypes.c_uint32)] +version_min_command_fields = segment_base_fields + [ + ("version", ctypes.c_uint32), + ("sdk", ctypes.c_uint32), +] """ struct version_min_command { uint32_t cmd; /* LC_VERSION_MIN_MACOSX or @@ -197,9 +217,12 @@ struct version_min_command { }; """ -build_version_command_fields = segment_base_fields + \ - [("platform", ctypes.c_uint32), ("minos", ctypes.c_uint32), - ("sdk", ctypes.c_uint32), ("ntools", ctypes.c_uint32)] +build_version_command_fields = segment_base_fields + [ + ("platform", ctypes.c_uint32), + ("minos", ctypes.c_uint32), + ("sdk", ctypes.c_uint32), + ("ntools", ctypes.c_uint32), +] """ struct build_version_command { uint32_t cmd; /* LC_BUILD_VERSION */ @@ -214,10 +237,12 @@ struct build_version_command { def swap32(x): - return (((x << 24) & 0xFF000000) | - ((x << 8) & 0x00FF0000) | - ((x >> 8) & 0x0000FF00) | - ((x >> 24) & 0x000000FF)) + return ( + ((x << 24) & 0xFF000000) + | ((x << 8) & 0x00FF0000) + | ((x >> 8) & 0x0000FF00) + | ((x >> 24) & 0x000000FF) + ) def get_base_class_and_magic_number(lib_file, seek=None): @@ -226,7 +251,8 @@ def get_base_class_and_magic_number(lib_file, seek=None): else: lib_file.seek(seek) magic_number = ctypes.c_uint32.from_buffer_copy( - lib_file.read(ctypes.sizeof(ctypes.c_uint32))).value + lib_file.read(ctypes.sizeof(ctypes.c_uint32)) + ).value # Handle wrong byte order if magic_number in [FAT_CIGAM, FAT_CIGAM_64, MH_CIGAM, MH_CIGAM_64]: @@ -244,8 +270,7 @@ def get_base_class_and_magic_number(lib_file, seek=None): def read_data(struct_class, lib_file): - return struct_class.from_buffer_copy(lib_file.read( - ctypes.sizeof(struct_class))) + return struct_class.from_buffer_copy(lib_file.read(ctypes.sizeof(struct_class))) def extract_macosx_min_system_version(path_to_lib): @@ -255,6 +280,7 @@ def extract_macosx_min_system_version(path_to_lib): return if magic_number in [FAT_MAGIC, FAT_CIGAM_64]: + class FatHeader(BaseClass): _fields_ = fat_header_fields @@ -263,12 +289,15 @@ def extract_macosx_min_system_version(path_to_lib): class FatArch(BaseClass): _fields_ = fat_arch_fields + else: class FatArch(BaseClass): _fields_ = fat_arch_64_fields - fat_arch_list = [read_data(FatArch, lib_file) for _ in range(fat_header.nfat_arch)] + fat_arch_list = [ + read_data(FatArch, lib_file) for _ in range(fat_header.nfat_arch) + ] versions_list = [] for el in fat_arch_list: @@ -333,12 +362,14 @@ def read_mach_header(lib_file, seek=None): segment_base = read_data(SegmentBase, lib_file) lib_file.seek(pos) if segment_base.cmd == LC_VERSION_MIN_MACOSX: + class VersionMinCommand(base_class): _fields_ = version_min_command_fields version_info = read_data(VersionMinCommand, lib_file) return parse_version(version_info.version) elif segment_base.cmd == LC_BUILD_VERSION: + class VersionBuild(base_class): _fields_ = build_version_command_fields @@ -350,9 +381,9 @@ def read_mach_header(lib_file, seek=None): def parse_version(version): - x = (version & 0xffff0000) >> 16 - y = (version & 0x0000ff00) >> 8 - z = (version & 0x000000ff) + x = (version & 0xFFFF0000) >> 16 + y = (version & 0x0000FF00) >> 8 + z = version & 0x000000FF return x, y, z @@ -362,25 +393,28 @@ def calculate_macosx_platform_tag(archive_root, platform_tag): Example platform tag `macosx-10.14-x86_64` """ - prefix, base_version, suffix = platform_tag.split('-') + prefix, base_version, suffix = platform_tag.split("-") base_version = tuple(int(x) for x in base_version.split(".")) base_version = base_version[:2] if base_version[0] > 10: base_version = (base_version[0], 0) assert len(base_version) == 2 if "MACOSX_DEPLOYMENT_TARGET" in os.environ: - deploy_target = tuple(int(x) for x in os.environ[ - "MACOSX_DEPLOYMENT_TARGET"].split(".")) + deploy_target = tuple( + int(x) for x in os.environ["MACOSX_DEPLOYMENT_TARGET"].split(".") + ) deploy_target = deploy_target[:2] if deploy_target[0] > 10: deploy_target = (deploy_target[0], 0) if deploy_target < base_version: sys.stderr.write( - "[WARNING] MACOSX_DEPLOYMENT_TARGET is set to a lower value ({}) than the " - "version on which the Python interpreter was compiled ({}), and will be " - "ignored.\n".format('.'.join(str(x) for x in deploy_target), - '.'.join(str(x) for x in base_version)) + "[WARNING] MACOSX_DEPLOYMENT_TARGET is set to a lower value ({}) than " + "the version on which the Python interpreter was compiled ({}), and " + "will be ignored.\n".format( + ".".join(str(x) for x in deploy_target), + ".".join(str(x) for x in base_version), ) + ) else: base_version = deploy_target @@ -389,7 +423,7 @@ def calculate_macosx_platform_tag(archive_root, platform_tag): versions_dict = {} for (dirpath, dirnames, filenames) in os.walk(archive_root): for filename in filenames: - if filename.endswith('.dylib') or filename.endswith('.so'): + if filename.endswith(".dylib") or filename.endswith(".so"): lib_path = os.path.join(dirpath, filename) min_ver = extract_macosx_min_system_version(lib_path) if min_ver is not None: @@ -410,17 +444,24 @@ def calculate_macosx_platform_tag(archive_root, platform_tag): files_form = "this file" else: files_form = "these files" - error_message = \ - "[WARNING] This wheel needs a higher macOS version than {} " \ - "To silence this warning, set MACOSX_DEPLOYMENT_TARGET to at least " +\ - fin_base_version + " or recreate " + files_form + " with lower " \ + error_message = ( + "[WARNING] This wheel needs a higher macOS version than {} " + "To silence this warning, set MACOSX_DEPLOYMENT_TARGET to at least " + + fin_base_version + + " or recreate " + + files_form + + " with lower " "MACOSX_DEPLOYMENT_TARGET: \n" + problematic_files + ) if "MACOSX_DEPLOYMENT_TARGET" in os.environ: - error_message = error_message.format("is set in MACOSX_DEPLOYMENT_TARGET variable.") + error_message = error_message.format( + "is set in MACOSX_DEPLOYMENT_TARGET variable." + ) else: error_message = error_message.format( - "the version your Python interpreter is compiled against.") + "the version your Python interpreter is compiled against." + ) sys.stderr.write(error_message) diff --git a/src/wheel/metadata.py b/src/wheel/metadata.py index 37efa74..ace796d 100644 --- a/src/wheel/metadata.py +++ b/src/wheel/metadata.py @@ -12,15 +12,15 @@ from .pkginfo import read_pkg_info def requires_to_requires_dist(requirement): """Return the version specifier for a requirement in PEP 345/566 fashion.""" - if getattr(requirement, 'url', None): + if getattr(requirement, "url", None): return " @ " + requirement.url requires_dist = [] for op, ver in requirement.specs: requires_dist.append(op + ver) if not requires_dist: - return '' - return " (%s)" % ','.join(sorted(requires_dist)) + return "" + return " (%s)" % ",".join(sorted(requires_dist)) def convert_requirements(requirements): @@ -36,30 +36,30 @@ def convert_requirements(requirements): def generate_requirements(extras_require): """ - Convert requirements from a setup()-style dictionary to ('Requires-Dist', 'requirement') - and ('Provides-Extra', 'extra') tuples. + Convert requirements from a setup()-style dictionary to + ('Requires-Dist', 'requirement') and ('Provides-Extra', 'extra') tuples. extras_require is a dictionary of {extra: [requirements]} as passed to setup(), using the empty extra {'': [requirements]} to hold install_requires. """ for extra, depends in extras_require.items(): - condition = '' - extra = extra or '' - if ':' in extra: # setuptools extra:condition syntax - extra, condition = extra.split(':', 1) + condition = "" + extra = extra or "" + if ":" in extra: # setuptools extra:condition syntax + extra, condition = extra.split(":", 1) extra = pkg_resources.safe_extra(extra) if extra: - yield 'Provides-Extra', extra + yield "Provides-Extra", extra if condition: condition = "(" + condition + ") and " condition += "extra == '%s'" % extra if condition: - condition = ' ; ' + condition + condition = " ; " + condition for new_req in convert_requirements(depends): - yield 'Requires-Dist', new_req + condition + yield "Requires-Dist", new_req + condition def pkginfo_to_metadata(egg_info_path, pkginfo_path): @@ -67,26 +67,27 @@ def pkginfo_to_metadata(egg_info_path, pkginfo_path): Convert .egg-info directory with PKG-INFO to the Metadata 2.1 format """ pkg_info = read_pkg_info(pkginfo_path) - pkg_info.replace_header('Metadata-Version', '2.1') + pkg_info.replace_header("Metadata-Version", "2.1") # Those will be regenerated from `requires.txt`. - del pkg_info['Provides-Extra'] - del pkg_info['Requires-Dist'] - requires_path = os.path.join(egg_info_path, 'requires.txt') + del pkg_info["Provides-Extra"] + del pkg_info["Requires-Dist"] + requires_path = os.path.join(egg_info_path, "requires.txt") if os.path.exists(requires_path): with open(requires_path) as requires_file: requires = requires_file.read() - parsed_requirements = sorted(pkg_resources.split_sections(requires), - key=lambda x: x[0] or '') + parsed_requirements = sorted( + pkg_resources.split_sections(requires), key=lambda x: x[0] or "" + ) for extra, reqs in parsed_requirements: for key, value in generate_requirements({extra: reqs}): if (key, value) not in pkg_info.items(): pkg_info[key] = value - description = pkg_info['Description'] + description = pkg_info["Description"] if description: pkg_info.set_payload(dedent_description(pkg_info)) - del pkg_info['Description'] + del pkg_info["Description"] return pkg_info @@ -98,8 +99,7 @@ def pkginfo_unicode(pkg_info, field): if not isinstance(text, str): for item in pkg_info.raw_items(): if item[0].lower() == field: - text = item[1].encode('ascii', 'surrogateescape') \ - .decode('utf-8') + text = item[1].encode("ascii", "surrogateescape").decode("utf-8") break return text @@ -109,25 +109,28 @@ def dedent_description(pkg_info): """ Dedent and convert pkg_info['Description'] to Unicode. """ - description = pkg_info['Description'] + description = pkg_info["Description"] # Python 3 Unicode handling, sorta. surrogates = False if not isinstance(description, str): surrogates = True - description = pkginfo_unicode(pkg_info, 'Description') + description = pkginfo_unicode(pkg_info, "Description") description_lines = description.splitlines() - description_dedent = '\n'.join( + description_dedent = "\n".join( # if the first line of long_description is blank, # the first line here will be indented. - (description_lines[0].lstrip(), - textwrap.dedent('\n'.join(description_lines[1:])), - '\n')) + ( + description_lines[0].lstrip(), + textwrap.dedent("\n".join(description_lines[1:])), + "\n", + ) + ) if surrogates: - description_dedent = description_dedent \ - .encode("utf8") \ - .decode("ascii", "surrogateescape") + description_dedent = description_dedent.encode("utf8").decode( + "ascii", "surrogateescape" + ) return description_dedent diff --git a/src/wheel/util.py b/src/wheel/util.py index a1f1e3b..09f5b29 100644 --- a/src/wheel/util.py +++ b/src/wheel/util.py @@ -1,7 +1,7 @@ import base64 -def native(s, encoding='utf-8'): +def native(s, encoding="utf-8"): if isinstance(s, bytes): return s.decode(encoding) else: @@ -10,23 +10,23 @@ def native(s, encoding='utf-8'): def urlsafe_b64encode(data): """urlsafe_b64encode without padding""" - return base64.urlsafe_b64encode(data).rstrip(b'=') + return base64.urlsafe_b64encode(data).rstrip(b"=") def urlsafe_b64decode(data): """urlsafe_b64decode without padding""" - pad = b'=' * (4 - (len(data) & 3)) + pad = b"=" * (4 - (len(data) & 3)) return base64.urlsafe_b64decode(data + pad) def as_unicode(s): if isinstance(s, bytes): - return s.decode('utf-8') + return s.decode("utf-8") return s def as_bytes(s): if isinstance(s, str): - return s.encode('utf-8') + return s.encode("utf-8") else: return s diff --git a/src/wheel/wheelfile.py b/src/wheel/wheelfile.py index 83f1611..36b38ef 100644 --- a/src/wheel/wheelfile.py +++ b/src/wheel/wheelfile.py @@ -10,20 +10,27 @@ from io import StringIO, TextIOWrapper from zipfile import ZIP_DEFLATED, ZipInfo, ZipFile from wheel.cli import WheelError -from wheel.util import urlsafe_b64decode, as_unicode, native, urlsafe_b64encode, as_bytes +from wheel.util import ( + urlsafe_b64decode, + as_unicode, + native, + urlsafe_b64encode, + as_bytes, +) # Non-greedy matching of an optional build number may be too clever (more # invalid wheel filenames will match). Separate regex for .dist-info? WHEEL_INFO_RE = re.compile( r"""^(?P<namever>(?P<name>.+?)-(?P<ver>.+?))(-(?P<build>\d[^-]*))? -(?P<pyver>.+?)-(?P<abi>.+?)-(?P<plat>.+?)\.whl$""", - re.VERBOSE) + re.VERBOSE, +) def get_zipinfo_datetime(timestamp=None): - # 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 = int(os.environ.get('SOURCE_DATE_EPOCH', timestamp or time.time())) + # 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 = int(os.environ.get("SOURCE_DATE_EPOCH", timestamp or time.time())) return time.gmtime(timestamp)[0:6] @@ -34,49 +41,56 @@ class WheelFile(ZipFile): _default_algorithm = hashlib.sha256 - def __init__(self, file, mode='r', compression=ZIP_DEFLATED): + def __init__(self, file, mode="r", compression=ZIP_DEFLATED): basename = os.path.basename(file) self.parsed_filename = WHEEL_INFO_RE.match(basename) - if not basename.endswith('.whl') or self.parsed_filename is None: + if not basename.endswith(".whl") or self.parsed_filename is None: raise WheelError(f"Bad wheel filename {basename!r}") ZipFile.__init__(self, file, mode, compression=compression, allowZip64=True) - self.dist_info_path = '{}.dist-info'.format(self.parsed_filename.group('namever')) - self.record_path = self.dist_info_path + '/RECORD' + self.dist_info_path = "{}.dist-info".format( + self.parsed_filename.group("namever") + ) + self.record_path = self.dist_info_path + "/RECORD" self._file_hashes = OrderedDict() self._file_sizes = {} - if mode == 'r': + if mode == "r": # Ignore RECORD and any embedded wheel signatures self._file_hashes[self.record_path] = None, None - self._file_hashes[self.record_path + '.jws'] = None, None - self._file_hashes[self.record_path + '.p7s'] = None, None + self._file_hashes[self.record_path + ".jws"] = None, None + self._file_hashes[self.record_path + ".p7s"] = None, None # Fill in the expected hashes by reading them from RECORD try: record = self.open(self.record_path) except KeyError: - raise WheelError(f'Missing {self.record_path} file') + raise WheelError(f"Missing {self.record_path} file") with record: - for line in csv.reader(TextIOWrapper(record, newline='', encoding='utf-8')): + for line in csv.reader( + TextIOWrapper(record, newline="", encoding="utf-8") + ): path, hash_sum, size = line if not hash_sum: continue - algorithm, hash_sum = hash_sum.split('=') + algorithm, hash_sum = hash_sum.split("=") try: hashlib.new(algorithm) except ValueError: - raise WheelError(f'Unsupported hash algorithm: {algorithm}') + raise WheelError(f"Unsupported hash algorithm: {algorithm}") - if algorithm.lower() in {'md5', 'sha1'}: + if algorithm.lower() in {"md5", "sha1"}: raise WheelError( - 'Weak hash algorithm ({}) is not permitted by PEP 427' - .format(algorithm)) + "Weak hash algorithm ({}) is not permitted by PEP " + "427".format(algorithm) + ) self._file_hashes[path] = ( - algorithm, urlsafe_b64decode(hash_sum.encode('ascii'))) + algorithm, + urlsafe_b64decode(hash_sum.encode("ascii")), + ) def open(self, name_or_info, mode="r", pwd=None): def _update_crc(newdata, eof=None): @@ -90,16 +104,22 @@ class WheelFile(ZipFile): if eof and running_hash.digest() != expected_hash: raise WheelError(f"Hash mismatch for file '{native(ef_name)}'") - ef_name = as_unicode(name_or_info.filename if isinstance(name_or_info, ZipInfo) - else name_or_info) - if mode == 'r' and not ef_name.endswith('/') and ef_name not in self._file_hashes: + ef_name = as_unicode( + name_or_info.filename if isinstance(name_or_info, ZipInfo) else name_or_info + ) + if ( + mode == "r" + and not ef_name.endswith("/") + and ef_name not in self._file_hashes + ): raise WheelError(f"No hash found for file '{native(ef_name)}'") ef = ZipFile.open(self, name_or_info, mode, pwd) - if mode == 'r' and not ef_name.endswith('/'): + if mode == "r" and not ef_name.endswith("/"): algorithm, expected_hash = self._file_hashes[ef_name] if expected_hash is not None: - # Monkey patch the _update_crc method to also check for the hash from RECORD + # Monkey patch the _update_crc method to also check for the hash from + # RECORD running_hash = hashlib.new(algorithm) update_crc_orig, ef._update_crc = ef._update_crc, _update_crc @@ -115,10 +135,10 @@ class WheelFile(ZipFile): for name in sorted(filenames): path = os.path.normpath(os.path.join(root, name)) if os.path.isfile(path): - arcname = os.path.relpath(path, base_dir).replace(os.path.sep, '/') + arcname = os.path.relpath(path, base_dir).replace(os.path.sep, "/") if arcname == self.record_path: pass - elif root.endswith('.dist-info'): + elif root.endswith(".dist-info"): deferred.append((path, arcname)) else: self.write(path, arcname) @@ -128,38 +148,43 @@ class WheelFile(ZipFile): self.write(path, arcname) def write(self, filename, arcname=None, compress_type=None): - with open(filename, 'rb') as f: + with open(filename, "rb") as f: st = os.fstat(f.fileno()) data = f.read() - zinfo = ZipInfo(arcname or filename, date_time=get_zipinfo_datetime(st.st_mtime)) + zinfo = ZipInfo( + arcname or filename, date_time=get_zipinfo_datetime(st.st_mtime) + ) zinfo.external_attr = (stat.S_IMODE(st.st_mode) | stat.S_IFMT(st.st_mode)) << 16 zinfo.compress_type = compress_type or self.compression self.writestr(zinfo, data, compress_type) def writestr(self, zinfo_or_arcname, bytes, compress_type=None): ZipFile.writestr(self, zinfo_or_arcname, bytes, compress_type) - fname = (zinfo_or_arcname.filename if isinstance(zinfo_or_arcname, ZipInfo) - else zinfo_or_arcname) + fname = ( + zinfo_or_arcname.filename + if isinstance(zinfo_or_arcname, ZipInfo) + else zinfo_or_arcname + ) logger.info("adding '%s'", fname) if fname != self.record_path: hash_ = self._default_algorithm(bytes) - self._file_hashes[fname] = hash_.name, native(urlsafe_b64encode(hash_.digest())) + self._file_hashes[fname] = hash_.name, native( + urlsafe_b64encode(hash_.digest()) + ) self._file_sizes[fname] = len(bytes) def close(self): # Write RECORD - if self.fp is not None and self.mode == 'w' and self._file_hashes: + if self.fp is not None and self.mode == "w" and self._file_hashes: data = StringIO() - writer = csv.writer(data, delimiter=',', quotechar='"', lineterminator='\n') - writer.writerows(( + writer = csv.writer(data, delimiter=",", quotechar='"', lineterminator="\n") + writer.writerows( ( - fname, - algorithm + "=" + hash_, - self._file_sizes[fname] + (fname, algorithm + "=" + hash_, self._file_sizes[fname]) + for fname, (algorithm, hash_) in self._file_hashes.items() ) - for fname, (algorithm, hash_) in self._file_hashes.items() - )) + ) writer.writerow((format(self.record_path), "", "")) zinfo = ZipInfo(native(self.record_path), date_time=get_zipinfo_datetime()) zinfo.compress_type = self.compression diff --git a/tests/cli/test_convert.py b/tests/cli/test_convert.py index 7d711aa..82a75eb 100644 --- a/tests/cli/test_convert.py +++ b/tests/cli/test_convert.py @@ -7,7 +7,7 @@ from wheel.wheelfile import WHEEL_INFO_RE def test_egg_re(): """Make sure egg_info_re matches.""" - egg_names_path = os.path.join(os.path.dirname(__file__), 'eggnames.txt') + egg_names_path = os.path.join(os.path.dirname(__file__), "eggnames.txt") with open(egg_names_path) as egg_names: for line in egg_names: line = line.strip() @@ -20,5 +20,7 @@ def test_convert_egg(egg_paths, tmpdir): wheel_names = [path.basename for path in tmpdir.listdir()] assert len(wheel_names) == len(egg_paths) assert all(WHEEL_INFO_RE.match(filename) for filename in wheel_names) - assert all(re.match(r'^[\w\d.]+-\d\.\d-\w+\d+-[\w\d]+-[\w\d]+\.whl$', fname) - for fname in wheel_names) + assert all( + re.match(r"^[\w\d.]+-\d\.\d-\w+\d+-[\w\d]+-[\w\d]+\.whl$", fname) + for fname in wheel_names + ) diff --git a/tests/cli/test_pack.py b/tests/cli/test_pack.py index 3f689a4..8fa9008 100644 --- a/tests/cli/test_pack.py +++ b/tests/cli/test_pack.py @@ -7,31 +7,38 @@ import pytest from wheel.cli.pack import pack THISDIR = os.path.dirname(__file__) -TESTWHEEL_NAME = 'test-1.0-py2.py3-none-any.whl' -TESTWHEEL_PATH = os.path.join(THISDIR, '..', 'testdata', TESTWHEEL_NAME) +TESTWHEEL_NAME = "test-1.0-py2.py3-none-any.whl" +TESTWHEEL_PATH = os.path.join(THISDIR, "..", "testdata", TESTWHEEL_NAME) -@pytest.mark.filterwarnings('error:Duplicate name') -@pytest.mark.parametrize('build_tag_arg, existing_build_tag, filename', [ - (None, None, 'test-1.0-py2.py3-none-any.whl'), - ('2b', None, 'test-1.0-2b-py2.py3-none-any.whl'), - (None, '3', 'test-1.0-3-py2.py3-none-any.whl'), - ('', '3', 'test-1.0-py2.py3-none-any.whl'), -], ids=['nobuildnum', 'newbuildarg', 'oldbuildnum', 'erasebuildnum']) +@pytest.mark.filterwarnings("error:Duplicate name") +@pytest.mark.parametrize( + "build_tag_arg, existing_build_tag, filename", + [ + (None, None, "test-1.0-py2.py3-none-any.whl"), + ("2b", None, "test-1.0-2b-py2.py3-none-any.whl"), + (None, "3", "test-1.0-3-py2.py3-none-any.whl"), + ("", "3", "test-1.0-py2.py3-none-any.whl"), + ], + ids=["nobuildnum", "newbuildarg", "oldbuildnum", "erasebuildnum"], +) def test_pack(tmpdir_factory, tmpdir, build_tag_arg, existing_build_tag, filename): - unpack_dir = tmpdir_factory.mktemp('wheeldir') + unpack_dir = tmpdir_factory.mktemp("wheeldir") with ZipFile(TESTWHEEL_PATH) as zf: - old_record = zf.read('test-1.0.dist-info/RECORD') - old_record_lines = sorted(line.rstrip() for line in old_record.split(b'\n') - if line and not line.startswith(b'test-1.0.dist-info/WHEEL,')) + old_record = zf.read("test-1.0.dist-info/RECORD") + old_record_lines = sorted( + line.rstrip() + for line in old_record.split(b"\n") + if line and not line.startswith(b"test-1.0.dist-info/WHEEL,") + ) zf.extractall(str(unpack_dir)) if existing_build_tag: # Add the build number to WHEEL - wheel_file_path = unpack_dir.join('test-1.0.dist-info').join('WHEEL') + wheel_file_path = unpack_dir.join("test-1.0.dist-info").join("WHEEL") wheel_file_content = wheel_file_path.read_binary() - assert b'Build' not in wheel_file_content - wheel_file_content += b'Build: 3\r\n' + assert b"Build" not in wheel_file_content + wheel_file_content += b"Build: 3\r\n" wheel_file_path.write_binary(wheel_file_content) pack(str(unpack_dir), str(tmpdir), build_tag_arg) @@ -39,24 +46,31 @@ def test_pack(tmpdir_factory, tmpdir, build_tag_arg, existing_build_tag, filenam assert new_wheel_path.isfile() with ZipFile(str(new_wheel_path)) as zf: - new_record = zf.read('test-1.0.dist-info/RECORD') - new_record_lines = sorted(line.rstrip() for line in new_record.split(b'\n') - if line and not line.startswith(b'test-1.0.dist-info/WHEEL,')) + new_record = zf.read("test-1.0.dist-info/RECORD") + new_record_lines = sorted( + line.rstrip() + for line in new_record.split(b"\n") + if line and not line.startswith(b"test-1.0.dist-info/WHEEL,") + ) - new_wheel_file_content = zf.read('test-1.0.dist-info/WHEEL') + new_wheel_file_content = zf.read("test-1.0.dist-info/WHEEL") assert new_record_lines == old_record_lines expected_build_num = build_tag_arg or existing_build_tag - expected_wheel_content = dedent("""\ + expected_wheel_content = dedent( + """\ Wheel-Version: 1.0 Generator: bdist_wheel (0.30.0) Root-Is-Purelib: false Tag: py2-none-any Tag: py3-none-any - """.replace('\n', '\r\n')) + """.replace( + "\n", "\r\n" + ) + ) if expected_build_num: - expected_wheel_content += 'Build: %s\r\n' % expected_build_num + expected_wheel_content += "Build: %s\r\n" % expected_build_num - expected_wheel_content = expected_wheel_content.encode('ascii') + expected_wheel_content = expected_wheel_content.encode("ascii") assert new_wheel_file_content == expected_wheel_content diff --git a/tests/conftest.py b/tests/conftest.py index 153954c..a7c5d61 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,35 +9,55 @@ import sys import pytest -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def wheels_and_eggs(tmpdir_factory): """Build wheels and eggs from test distributions.""" - test_distributions = ("complex-dist", "simple.dist", "headers.dist", "commasinfilenames.dist", - "unicode.dist") - - if sys.platform != 'win32': + test_distributions = ( + "complex-dist", + "simple.dist", + "headers.dist", + "commasinfilenames.dist", + "unicode.dist", + ) + + if sys.platform != "win32": # ABI3 extensions don't really work on Windows test_distributions += ("abi3extension.dist",) pwd = os.path.abspath(os.curdir) this_dir = os.path.dirname(__file__) - build_dir = tmpdir_factory.mktemp('build') - dist_dir = tmpdir_factory.mktemp('dist') + build_dir = tmpdir_factory.mktemp("build") + dist_dir = tmpdir_factory.mktemp("dist") for dist in test_distributions: - os.chdir(os.path.join(this_dir, 'testdata', dist)) - subprocess.check_call([sys.executable, 'setup.py', - 'bdist_egg', '-b', str(build_dir), '-d', str(dist_dir), - 'bdist_wheel', '-b', str(build_dir), '-d', str(dist_dir)]) + os.chdir(os.path.join(this_dir, "testdata", dist)) + subprocess.check_call( + [ + sys.executable, + "setup.py", + "bdist_egg", + "-b", + str(build_dir), + "-d", + str(dist_dir), + "bdist_wheel", + "-b", + str(build_dir), + "-d", + str(dist_dir), + ] + ) os.chdir(pwd) - return sorted(str(fname) for fname in dist_dir.listdir() if fname.ext in ('.whl', '.egg')) + return sorted( + str(fname) for fname in dist_dir.listdir() if fname.ext in (".whl", ".egg") + ) -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def wheel_paths(wheels_and_eggs): - return [fname for fname in wheels_and_eggs if fname.endswith('.whl')] + return [fname for fname in wheels_and_eggs if fname.endswith(".whl")] -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def egg_paths(wheels_and_eggs): - return [fname for fname in wheels_and_eggs if fname.endswith('.egg')] + return [fname for fname in wheels_and_eggs if fname.endswith(".egg")] diff --git a/tests/test_bdist_wheel.py b/tests/test_bdist_wheel.py index 6c47c47..67e5f92 100644 --- a/tests/test_bdist_wheel.py +++ b/tests/test_bdist_wheel.py @@ -11,117 +11,160 @@ from wheel.bdist_wheel import bdist_wheel from wheel.wheelfile import WheelFile DEFAULT_FILES = { - 'dummy_dist-1.0.dist-info/top_level.txt', - 'dummy_dist-1.0.dist-info/METADATA', - 'dummy_dist-1.0.dist-info/WHEEL', - 'dummy_dist-1.0.dist-info/RECORD' + "dummy_dist-1.0.dist-info/top_level.txt", + "dummy_dist-1.0.dist-info/METADATA", + "dummy_dist-1.0.dist-info/WHEEL", + "dummy_dist-1.0.dist-info/RECORD", } DEFAULT_LICENSE_FILES = { - 'LICENSE', 'LICENSE.txt', 'LICENCE', 'LICENCE.txt', 'COPYING', - 'COPYING.md', 'NOTICE', 'NOTICE.rst', 'AUTHORS', 'AUTHORS.txt' + "LICENSE", + "LICENSE.txt", + "LICENCE", + "LICENCE.txt", + "COPYING", + "COPYING.md", + "NOTICE", + "NOTICE.rst", + "AUTHORS", + "AUTHORS.txt", } OTHER_IGNORED_FILES = { - 'LICENSE~', 'AUTHORS~', + "LICENSE~", + "AUTHORS~", } @pytest.fixture def dummy_dist(tmpdir_factory): - basedir = tmpdir_factory.mktemp('dummy_dist') - basedir.join('setup.py').write("""\ + basedir = tmpdir_factory.mktemp("dummy_dist") + basedir.join("setup.py").write( + """\ from setuptools import setup setup( name='dummy_dist', version='1.0' ) -""") +""" + ) for fname in DEFAULT_LICENSE_FILES | OTHER_IGNORED_FILES: - basedir.join(fname).write('') + basedir.join(fname).write("") - basedir.join('licenses').mkdir().join('DUMMYFILE').write('') + basedir.join("licenses").mkdir().join("DUMMYFILE").write("") return basedir def test_no_scripts(wheel_paths): """Make sure entry point scripts are not generated.""" - path = next(path for path in wheel_paths if 'complex_dist' in path) + path = next(path for path in wheel_paths if "complex_dist" in path) for entry in ZipFile(path).infolist(): - assert '.data/scripts/' not in entry.filename + assert ".data/scripts/" not in entry.filename -@pytest.mark.skipif(sys.version_info < (3, 6), - reason='Packaging unicode file names only works reliably on Python 3.6+') +@pytest.mark.skipif( + sys.version_info < (3, 6), + reason="Packaging unicode file names only works reliably on Python 3.6+", +) def test_unicode_record(wheel_paths): - path = next(path for path in wheel_paths if 'unicode.dist' in path) + path = next(path for path in wheel_paths if "unicode.dist" in path) with ZipFile(path) as zf: - record = zf.read('unicode.dist-0.1.dist-info/RECORD') + record = zf.read("unicode.dist-0.1.dist-info/RECORD") - assert 'åäö_日本語.py'.encode() in record + assert "åäö_日本語.py".encode() in record def test_licenses_default(dummy_dist, monkeypatch, tmpdir): monkeypatch.chdir(dummy_dist) - subprocess.check_call([sys.executable, 'setup.py', 'bdist_wheel', '-b', str(tmpdir), - '--universal']) - with WheelFile('dist/dummy_dist-1.0-py2.py3-none-any.whl') as wf: - license_files = {'dummy_dist-1.0.dist-info/' + fname for fname in DEFAULT_LICENSE_FILES} + subprocess.check_call( + [sys.executable, "setup.py", "bdist_wheel", "-b", str(tmpdir), "--universal"] + ) + with WheelFile("dist/dummy_dist-1.0-py2.py3-none-any.whl") as wf: + license_files = { + "dummy_dist-1.0.dist-info/" + fname for fname in DEFAULT_LICENSE_FILES + } assert set(wf.namelist()) == DEFAULT_FILES | license_files def test_licenses_deprecated(dummy_dist, monkeypatch, tmpdir): - dummy_dist.join('setup.cfg').write('[metadata]\nlicense_file=licenses/DUMMYFILE') + dummy_dist.join("setup.cfg").write("[metadata]\nlicense_file=licenses/DUMMYFILE") monkeypatch.chdir(dummy_dist) - subprocess.check_call([sys.executable, 'setup.py', 'bdist_wheel', '-b', str(tmpdir), - '--universal']) - with WheelFile('dist/dummy_dist-1.0-py2.py3-none-any.whl') as wf: - license_files = {'dummy_dist-1.0.dist-info/DUMMYFILE'} + subprocess.check_call( + [sys.executable, "setup.py", "bdist_wheel", "-b", str(tmpdir), "--universal"] + ) + with WheelFile("dist/dummy_dist-1.0-py2.py3-none-any.whl") as wf: + license_files = {"dummy_dist-1.0.dist-info/DUMMYFILE"} assert set(wf.namelist()) == DEFAULT_FILES | license_files def test_licenses_override(dummy_dist, monkeypatch, tmpdir): - dummy_dist.join('setup.cfg').write('[metadata]\nlicense_files=licenses/*\n LICENSE') + dummy_dist.join("setup.cfg").write( + "[metadata]\nlicense_files=licenses/*\n LICENSE" + ) monkeypatch.chdir(dummy_dist) - subprocess.check_call([sys.executable, 'setup.py', 'bdist_wheel', '-b', str(tmpdir), - '--universal']) - with WheelFile('dist/dummy_dist-1.0-py2.py3-none-any.whl') as wf: - license_files = {'dummy_dist-1.0.dist-info/' + fname for fname in {'DUMMYFILE', 'LICENSE'}} + subprocess.check_call( + [sys.executable, "setup.py", "bdist_wheel", "-b", str(tmpdir), "--universal"] + ) + with WheelFile("dist/dummy_dist-1.0-py2.py3-none-any.whl") as wf: + license_files = { + "dummy_dist-1.0.dist-info/" + fname for fname in {"DUMMYFILE", "LICENSE"} + } assert set(wf.namelist()) == DEFAULT_FILES | license_files def test_licenses_disabled(dummy_dist, monkeypatch, tmpdir): - dummy_dist.join('setup.cfg').write('[metadata]\nlicense_files=\n') + dummy_dist.join("setup.cfg").write("[metadata]\nlicense_files=\n") monkeypatch.chdir(dummy_dist) - subprocess.check_call([sys.executable, 'setup.py', 'bdist_wheel', '-b', str(tmpdir), - '--universal']) - with WheelFile('dist/dummy_dist-1.0-py2.py3-none-any.whl') as wf: + subprocess.check_call( + [sys.executable, "setup.py", "bdist_wheel", "-b", str(tmpdir), "--universal"] + ) + with WheelFile("dist/dummy_dist-1.0-py2.py3-none-any.whl") as wf: assert set(wf.namelist()) == DEFAULT_FILES def test_build_number(dummy_dist, monkeypatch, tmpdir): monkeypatch.chdir(dummy_dist) - subprocess.check_call([sys.executable, 'setup.py', 'bdist_wheel', '-b', str(tmpdir), - '--universal', '--build-number=2']) - with WheelFile('dist/dummy_dist-1.0-2-py2.py3-none-any.whl') as wf: + subprocess.check_call( + [ + sys.executable, + "setup.py", + "bdist_wheel", + "-b", + str(tmpdir), + "--universal", + "--build-number=2", + ] + ) + with WheelFile("dist/dummy_dist-1.0-2-py2.py3-none-any.whl") as wf: filenames = set(wf.namelist()) - assert 'dummy_dist-1.0.dist-info/RECORD' in filenames - assert 'dummy_dist-1.0.dist-info/METADATA' in filenames + assert "dummy_dist-1.0.dist-info/RECORD" in filenames + assert "dummy_dist-1.0.dist-info/METADATA" in filenames -@pytest.mark.skipif(sys.version_info[0] < 3, reason='The limited ABI only works on Python 3+') +@pytest.mark.skipif( + sys.version_info[0] < 3, reason="The limited ABI only works on Python 3+" +) def test_limited_abi(monkeypatch, tmpdir): """Test that building a binary wheel with the limited ABI works.""" this_dir = os.path.dirname(__file__) - source_dir = os.path.join(this_dir, 'testdata', 'extension.dist') - build_dir = tmpdir.join('build') - dist_dir = tmpdir.join('dist') + source_dir = os.path.join(this_dir, "testdata", "extension.dist") + build_dir = tmpdir.join("build") + dist_dir = tmpdir.join("dist") monkeypatch.chdir(source_dir) - subprocess.check_call([sys.executable, 'setup.py', 'bdist_wheel', '-b', str(build_dir), - '-d', str(dist_dir)]) + subprocess.check_call( + [ + sys.executable, + "setup.py", + "bdist_wheel", + "-b", + str(build_dir), + "-d", + str(dist_dir), + ] + ) def test_build_from_readonly_tree(dummy_dist, monkeypatch, tmpdir): - basedir = str(tmpdir.join('dummy')) + basedir = str(tmpdir.join("dummy")) shutil.copytree(str(dummy_dist), basedir) monkeypatch.chdir(basedir) @@ -130,19 +173,31 @@ def test_build_from_readonly_tree(dummy_dist, monkeypatch, tmpdir): for fname in files: os.chmod(os.path.join(root, fname), stat.S_IREAD) - subprocess.check_call([sys.executable, 'setup.py', 'bdist_wheel']) + subprocess.check_call([sys.executable, "setup.py", "bdist_wheel"]) -@pytest.mark.parametrize('option, compress_type', list(bdist_wheel.supported_compressions.items()), - ids=list(bdist_wheel.supported_compressions)) +@pytest.mark.parametrize( + "option, compress_type", + list(bdist_wheel.supported_compressions.items()), + ids=list(bdist_wheel.supported_compressions), +) def test_compression(dummy_dist, monkeypatch, tmpdir, option, compress_type): monkeypatch.chdir(dummy_dist) - subprocess.check_call([sys.executable, 'setup.py', 'bdist_wheel', '-b', str(tmpdir), - '--universal', f'--compression={option}']) - with WheelFile('dist/dummy_dist-1.0-py2.py3-none-any.whl') as wf: + subprocess.check_call( + [ + sys.executable, + "setup.py", + "bdist_wheel", + "-b", + str(tmpdir), + "--universal", + f"--compression={option}", + ] + ) + with WheelFile("dist/dummy_dist-1.0-py2.py3-none-any.whl") as wf: filenames = set(wf.namelist()) - assert 'dummy_dist-1.0.dist-info/RECORD' in filenames - assert 'dummy_dist-1.0.dist-info/METADATA' in filenames + assert "dummy_dist-1.0.dist-info/RECORD" in filenames + assert "dummy_dist-1.0.dist-info/METADATA" in filenames for zinfo in wf.filelist: assert zinfo.compress_type == compress_type @@ -150,6 +205,6 @@ def test_compression(dummy_dist, monkeypatch, tmpdir, option, compress_type): def test_wheelfile_line_endings(wheel_paths): for path in wheel_paths: with WheelFile(path) as wf: - wheelfile = next(fn for fn in wf.filelist if fn.filename.endswith('WHEEL')) + wheelfile = next(fn for fn in wf.filelist if fn.filename.endswith("WHEEL")) wheelfile_contents = wf.read(wheelfile) - assert b'\r' not in wheelfile_contents + assert b"\r" not in wheelfile_contents diff --git a/tests/test_macosx_libfile.py b/tests/test_macosx_libfile.py index 614e723..aad953c 100644 --- a/tests/test_macosx_libfile.py +++ b/tests/test_macosx_libfile.py @@ -8,8 +8,7 @@ from wheel.bdist_wheel import get_platform def test_read_from_dylib(): dirname = os.path.dirname(__file__) - dylib_dir = os.path.join(dirname, "testdata", - "macosx_minimal_system_version") + dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version") versions = [ ("test_lib_10_6_fat.dylib", "10.6.0"), ("test_lib_10_10_fat.dylib", "10.10.0"), @@ -31,12 +30,12 @@ def test_read_from_dylib(): ) str_ver = ".".join([str(x) for x in extracted]) assert str_ver == ver - assert extract_macosx_min_system_version( - os.path.join(dylib_dir, "test_lib.c") - ) is None - assert extract_macosx_min_system_version( - os.path.join(dylib_dir, "libb.dylib") - ) is None + assert ( + extract_macosx_min_system_version(os.path.join(dylib_dir, "test_lib.c")) is None + ) + assert ( + extract_macosx_min_system_version(os.path.join(dylib_dir, "libb.dylib")) is None + ) def return_factory(return_val): @@ -50,38 +49,60 @@ class TestGetPlatformMacosx: def test_simple(self, monkeypatch): dirname = os.path.dirname(__file__) dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version") - monkeypatch.setattr(distutils.util, "get_platform", return_factory("macosx-11.0-x86_64")) + monkeypatch.setattr( + distutils.util, "get_platform", return_factory("macosx-11.0-x86_64") + ) assert get_platform(dylib_dir) == "macosx_11_0_x86_64" def test_version_bump(self, monkeypatch, capsys): dirname = os.path.dirname(__file__) dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version") - monkeypatch.setattr(distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")) + monkeypatch.setattr( + distutils.util, "get_platform", return_factory("macosx-10.9-x86_64") + ) assert get_platform(dylib_dir) == "macosx_11_0_x86_64" captured = capsys.readouterr() assert "[WARNING] This wheel needs a higher macOS version than" in captured.err - def test_information_about_problematic_files_python_version(self, monkeypatch, capsys): + def test_information_about_problematic_files_python_version( + self, monkeypatch, capsys + ): dirname = os.path.dirname(__file__) dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version") - monkeypatch.setattr(distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")) - monkeypatch.setattr(os, "walk", return_factory( - [(dylib_dir, [], ["test_lib_10_6.dylib", "test_lib_10_10_fat.dylib"])] - )) + monkeypatch.setattr( + distutils.util, "get_platform", return_factory("macosx-10.9-x86_64") + ) + monkeypatch.setattr( + os, + "walk", + return_factory( + [(dylib_dir, [], ["test_lib_10_6.dylib", "test_lib_10_10_fat.dylib"])] + ), + ) assert get_platform(dylib_dir) == "macosx_10_10_x86_64" captured = capsys.readouterr() assert "[WARNING] This wheel needs a higher macOS version than" in captured.err - assert "the version your Python interpreter is compiled against." in captured.err + assert ( + "the version your Python interpreter is compiled against." in captured.err + ) assert "test_lib_10_10_fat.dylib" in captured.err - def test_information_about_problematic_files_env_variable(self, monkeypatch, capsys): + def test_information_about_problematic_files_env_variable( + self, monkeypatch, capsys + ): dirname = os.path.dirname(__file__) dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version") - monkeypatch.setattr(distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")) + monkeypatch.setattr( + distutils.util, "get_platform", return_factory("macosx-10.9-x86_64") + ) monkeypatch.setenv("MACOSX_DEPLOYMENT_TARGET", "10.8") - monkeypatch.setattr(os, "walk", return_factory( - [(dylib_dir, [], ["test_lib_10_6.dylib", "test_lib_10_10_fat.dylib"])] - )) + monkeypatch.setattr( + os, + "walk", + return_factory( + [(dylib_dir, [], ["test_lib_10_6.dylib", "test_lib_10_10_fat.dylib"])] + ), + ) assert get_platform(dylib_dir) == "macosx_10_10_x86_64" captured = capsys.readouterr() assert "[WARNING] This wheel needs a higher macOS version than" in captured.err @@ -91,10 +112,16 @@ class TestGetPlatformMacosx: def test_bump_platform_tag_by_env_variable(self, monkeypatch, capsys): dirname = os.path.dirname(__file__) dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version") - monkeypatch.setattr(distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")) - monkeypatch.setattr(os, "walk", return_factory( - [(dylib_dir, [], ["test_lib_10_6.dylib", "test_lib_10_6_fat.dylib"])] - )) + monkeypatch.setattr( + distutils.util, "get_platform", return_factory("macosx-10.9-x86_64") + ) + monkeypatch.setattr( + os, + "walk", + return_factory( + [(dylib_dir, [], ["test_lib_10_6.dylib", "test_lib_10_6_fat.dylib"])] + ), + ) assert get_platform(dylib_dir) == "macosx_10_9_x86_64" monkeypatch.setenv("MACOSX_DEPLOYMENT_TARGET", "10.10") assert get_platform(dylib_dir) == "macosx_10_10_x86_64" @@ -104,11 +131,26 @@ class TestGetPlatformMacosx: def test_bugfix_release_platform_tag(self, monkeypatch, capsys): dirname = os.path.dirname(__file__) dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version") - monkeypatch.setattr(distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")) - monkeypatch.setattr(os, "walk", return_factory( - [(dylib_dir, [], ["test_lib_10_6.dylib", "test_lib_10_6_fat.dylib", - "test_lib_10_10_10.dylib"])] - )) + monkeypatch.setattr( + distutils.util, "get_platform", return_factory("macosx-10.9-x86_64") + ) + monkeypatch.setattr( + os, + "walk", + return_factory( + [ + ( + dylib_dir, + [], + [ + "test_lib_10_6.dylib", + "test_lib_10_6_fat.dylib", + "test_lib_10_10_10.dylib", + ], + ) + ] + ), + ) assert get_platform(dylib_dir) == "macosx_10_10_x86_64" captured = capsys.readouterr() assert "This wheel needs a higher macOS version than" in captured.err @@ -120,32 +162,53 @@ class TestGetPlatformMacosx: def test_warning_on_to_low_env_variable(self, monkeypatch, capsys): dirname = os.path.dirname(__file__) dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version") - monkeypatch.setattr(distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")) + monkeypatch.setattr( + distutils.util, "get_platform", return_factory("macosx-10.9-x86_64") + ) monkeypatch.setenv("MACOSX_DEPLOYMENT_TARGET", "10.8") - monkeypatch.setattr(os, "walk", return_factory( - [(dylib_dir, [], ["test_lib_10_6.dylib", "test_lib_10_6_fat.dylib"])] - )) + monkeypatch.setattr( + os, + "walk", + return_factory( + [(dylib_dir, [], ["test_lib_10_6.dylib", "test_lib_10_6_fat.dylib"])] + ), + ) assert get_platform(dylib_dir) == "macosx_10_9_x86_64" captured = capsys.readouterr() - assert "MACOSX_DEPLOYMENT_TARGET is set to a lower value (10.8) than the" in captured.err + assert ( + "MACOSX_DEPLOYMENT_TARGET is set to a lower value (10.8) than the" + in captured.err + ) def test_get_platform_bigsur_env(self, monkeypatch): dirname = os.path.dirname(__file__) dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version") - monkeypatch.setattr(distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")) + monkeypatch.setattr( + distutils.util, "get_platform", return_factory("macosx-10.9-x86_64") + ) monkeypatch.setenv("MACOSX_DEPLOYMENT_TARGET", "11") - monkeypatch.setattr(os, "walk", return_factory( - [(dylib_dir, [], ["test_lib_10_6.dylib", "test_lib_10_10_fat.dylib"])] - )) + monkeypatch.setattr( + os, + "walk", + return_factory( + [(dylib_dir, [], ["test_lib_10_6.dylib", "test_lib_10_10_fat.dylib"])] + ), + ) assert get_platform(dylib_dir) == "macosx_11_0_x86_64" def test_get_platform_bigsur_platform(self, monkeypatch): dirname = os.path.dirname(__file__) dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version") - monkeypatch.setattr(distutils.util, "get_platform", return_factory("macosx-11-x86_64")) - monkeypatch.setattr(os, "walk", return_factory( - [(dylib_dir, [], ["test_lib_10_6.dylib", "test_lib_10_10_fat.dylib"])] - )) + monkeypatch.setattr( + distutils.util, "get_platform", return_factory("macosx-11-x86_64") + ) + monkeypatch.setattr( + os, + "walk", + return_factory( + [(dylib_dir, [], ["test_lib_10_6.dylib", "test_lib_10_10_fat.dylib"])] + ), + ) assert get_platform(dylib_dir) == "macosx_11_0_x86_64" diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 2e4f24c..3ecf64f 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -3,30 +3,34 @@ from wheel.metadata import pkginfo_to_metadata def test_pkginfo_to_metadata(tmpdir): expected_metadata = [ - ('Metadata-Version', '2.1'), - ('Name', 'spam'), - ('Version', '0.1'), - ('Requires-Dist', "pip @ https://github.com/pypa/pip/archive/1.3.1.zip"), - ('Requires-Dist', 'pywin32 ; sys_platform=="win32"'), - ('Requires-Dist', 'foo @ http://host/foo.zip ; sys_platform=="win32"'), - ('Provides-Extra', 'signatures'), - ('Requires-Dist', 'pyxdg ; (sys_platform!="win32") and extra == \'signatures\''), - ('Provides-Extra', 'empty_extra'), - ('Provides-Extra', 'extra'), - ('Requires-Dist', 'bar @ http://host/bar.zip ; extra == \'extra\''), - ('Provides-Extra', 'faster-signatures'), - ('Requires-Dist', "ed25519ll ; extra == 'faster-signatures'"), - ('Provides-Extra', 'rest'), - ('Requires-Dist', "docutils (>=0.8) ; extra == 'rest'"), - ('Requires-Dist', "keyring ; extra == 'signatures'"), - ('Requires-Dist', "keyrings.alt ; extra == 'signatures'"), - ('Provides-Extra', 'test'), - ('Requires-Dist', "pytest (>=3.0.0) ; extra == 'test'"), - ('Requires-Dist', "pytest-cov ; extra == 'test'"), + ("Metadata-Version", "2.1"), + ("Name", "spam"), + ("Version", "0.1"), + ("Requires-Dist", "pip @ https://github.com/pypa/pip/archive/1.3.1.zip"), + ("Requires-Dist", 'pywin32 ; sys_platform=="win32"'), + ("Requires-Dist", 'foo @ http://host/foo.zip ; sys_platform=="win32"'), + ("Provides-Extra", "signatures"), + ( + "Requires-Dist", + "pyxdg ; (sys_platform!=\"win32\") and extra == 'signatures'", + ), + ("Provides-Extra", "empty_extra"), + ("Provides-Extra", "extra"), + ("Requires-Dist", "bar @ http://host/bar.zip ; extra == 'extra'"), + ("Provides-Extra", "faster-signatures"), + ("Requires-Dist", "ed25519ll ; extra == 'faster-signatures'"), + ("Provides-Extra", "rest"), + ("Requires-Dist", "docutils (>=0.8) ; extra == 'rest'"), + ("Requires-Dist", "keyring ; extra == 'signatures'"), + ("Requires-Dist", "keyrings.alt ; extra == 'signatures'"), + ("Provides-Extra", "test"), + ("Requires-Dist", "pytest (>=3.0.0) ; extra == 'test'"), + ("Requires-Dist", "pytest-cov ; extra == 'test'"), ] - pkg_info = tmpdir.join('PKG-INFO') - pkg_info.write("""\ + pkg_info = tmpdir.join("PKG-INFO") + pkg_info.write( + """\ Metadata-Version: 0.0 Name: spam Version: 0.1 @@ -35,10 +39,12 @@ Provides-Extra: test Provides-Extra: reST Provides-Extra: signatures Provides-Extra: Signatures -Provides-Extra: faster-signatures""") +Provides-Extra: faster-signatures""" + ) - egg_info_dir = tmpdir.ensure_dir('test.egg-info') - egg_info_dir.join('requires.txt').write("""\ + egg_info_dir = tmpdir.ensure_dir("test.egg-info") + egg_info_dir.join("requires.txt").write( + """\ pip@https://github.com/pypa/pip/archive/1.3.1.zip [extra] @@ -65,7 +71,10 @@ pyxdg [test] pytest>=3.0.0 -pytest-cov""") +pytest-cov""" + ) - message = pkginfo_to_metadata(egg_info_path=str(egg_info_dir), pkginfo_path=str(pkg_info)) + message = pkginfo_to_metadata( + egg_info_path=str(egg_info_dir), pkginfo_path=str(pkg_info) + ) assert message.items() == expected_metadata diff --git a/tests/test_pkginfo.py b/tests/test_pkginfo.py index a7e07a8..544f9d5 100644 --- a/tests/test_pkginfo.py +++ b/tests/test_pkginfo.py @@ -4,7 +4,9 @@ from wheel.pkginfo import write_pkg_info def test_pkginfo_mangle_from(tmpdir): - """Test that write_pkginfo() will not prepend a ">" to a line starting with "From".""" + """ + Test that write_pkginfo() will not prepend a ">" to a line starting with "From". + """ metadata = """\ Metadata-Version: 2.1 Name: foo @@ -17,6 +19,6 @@ Test """ message = Parser().parsestr(metadata) - pkginfo_file = tmpdir.join('PKGINFO') + pkginfo_file = tmpdir.join("PKGINFO") write_pkg_info(str(pkginfo_file), message) - assert pkginfo_file.read_text('ascii') == metadata + assert pkginfo_file.read_text("ascii") == metadata diff --git a/tests/test_tagopt.py b/tests/test_tagopt.py index dd0c7a2..12be34b 100644 --- a/tests/test_tagopt.py +++ b/tests/test_tagopt.py @@ -25,176 +25,185 @@ EXT_MODULES = "ext_modules=[Extension('_test', sources=['test.c'])]," @pytest.fixture def temp_pkg(request, tmpdir): - tmpdir.join('test.py').write('print("Hello, world")') + tmpdir.join("test.py").write('print("Hello, world")') - ext = getattr(request, 'param', [False, '']) + ext = getattr(request, "param", [False, ""]) if ext[0]: # if ext[1] is not '', it will write a bad header and fail to compile - tmpdir.join('test.c').write('#include <std%sio.h>' % ext[1]) + tmpdir.join("test.c").write("#include <std%sio.h>" % ext[1]) setup_py = SETUP_PY.format(ext_modules=EXT_MODULES) else: - setup_py = SETUP_PY.format(ext_modules='') + setup_py = SETUP_PY.format(ext_modules="") - tmpdir.join('setup.py').write(setup_py) + tmpdir.join("setup.py").write(setup_py) if ext[0]: try: subprocess.check_call( - [sys.executable, 'setup.py', 'build_ext'], cwd=str(tmpdir)) + [sys.executable, "setup.py", "build_ext"], cwd=str(tmpdir) + ) except subprocess.CalledProcessError: - pytest.skip('Cannot compile C extensions') + pytest.skip("Cannot compile C extensions") return tmpdir -@pytest.mark.parametrize('temp_pkg', [[True, 'xxx']], indirect=['temp_pkg']) +@pytest.mark.parametrize("temp_pkg", [[True, "xxx"]], indirect=["temp_pkg"]) def test_nocompile_skips(temp_pkg): assert False # should have skipped with a "Cannot compile" message def test_default_tag(temp_pkg): - subprocess.check_call([sys.executable, 'setup.py', 'bdist_wheel'], cwd=str(temp_pkg)) - dist_dir = temp_pkg.join('dist') + 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 == f'Test-1.0-py{sys.version_info[0]}-none-any.whl' - assert wheels[0].ext == '.whl' + assert wheels[0].basename == f"Test-1.0-py{sys.version_info[0]}-none-any.whl" + assert wheels[0].ext == ".whl" def test_build_number(temp_pkg): - subprocess.check_call([sys.executable, 'setup.py', 'bdist_wheel', '--build-number=1'], - cwd=str(temp_pkg)) - dist_dir = temp_pkg.join('dist') + subprocess.check_call( + [sys.executable, "setup.py", "bdist_wheel", "--build-number=1"], + 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 == f'Test-1.0-1-py{sys.version_info[0]}-none-any.whl') - assert wheels[0].ext == '.whl' + assert wheels[0].basename == f"Test-1.0-1-py{sys.version_info[0]}-none-any.whl" + assert wheels[0].ext == ".whl" def test_explicit_tag(temp_pkg): subprocess.check_call( - [sys.executable, 'setup.py', 'bdist_wheel', '--python-tag=py32'], - cwd=str(temp_pkg)) - dist_dir = temp_pkg.join('dist') + [sys.executable, "setup.py", "bdist_wheel", "--python-tag=py32"], + 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.startswith('Test-1.0-py32-') - assert wheels[0].ext == '.whl' + assert wheels[0].basename.startswith("Test-1.0-py32-") + assert wheels[0].ext == ".whl" def test_universal_tag(temp_pkg): subprocess.check_call( - [sys.executable, 'setup.py', 'bdist_wheel', '--universal'], - cwd=str(temp_pkg)) - dist_dir = temp_pkg.join('dist') + [sys.executable, "setup.py", "bdist_wheel", "--universal"], 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.startswith('Test-1.0-py2.py3-') - assert wheels[0].ext == '.whl' + assert wheels[0].basename.startswith("Test-1.0-py2.py3-") + assert wheels[0].ext == ".whl" def test_universal_beats_explicit_tag(temp_pkg): subprocess.check_call( - [sys.executable, 'setup.py', 'bdist_wheel', '--universal', '--python-tag=py32'], - cwd=str(temp_pkg)) - dist_dir = temp_pkg.join('dist') + [sys.executable, "setup.py", "bdist_wheel", "--universal", "--python-tag=py32"], + 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.startswith('Test-1.0-py2.py3-') - assert wheels[0].ext == '.whl' + assert wheels[0].basename.startswith("Test-1.0-py2.py3-") + assert wheels[0].ext == ".whl" def test_universal_in_setup_cfg(temp_pkg): - temp_pkg.join('setup.cfg').write('[bdist_wheel]\nuniversal=1') + temp_pkg.join("setup.cfg").write("[bdist_wheel]\nuniversal=1") subprocess.check_call( - [sys.executable, 'setup.py', 'bdist_wheel'], - cwd=str(temp_pkg)) - dist_dir = temp_pkg.join('dist') + [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.startswith('Test-1.0-py2.py3-') - assert wheels[0].ext == '.whl' + assert wheels[0].basename.startswith("Test-1.0-py2.py3-") + assert wheels[0].ext == ".whl" def test_pythontag_in_setup_cfg(temp_pkg): - temp_pkg.join('setup.cfg').write('[bdist_wheel]\npython_tag=py32') + temp_pkg.join("setup.cfg").write("[bdist_wheel]\npython_tag=py32") subprocess.check_call( - [sys.executable, 'setup.py', 'bdist_wheel'], - cwd=str(temp_pkg)) - dist_dir = temp_pkg.join('dist') + [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.startswith('Test-1.0-py32-') - assert wheels[0].ext == '.whl' + assert wheels[0].basename.startswith("Test-1.0-py32-") + assert wheels[0].ext == ".whl" def test_legacy_wheel_section_in_setup_cfg(temp_pkg): - temp_pkg.join('setup.cfg').write('[wheel]\nuniversal=1') + temp_pkg.join("setup.cfg").write("[wheel]\nuniversal=1") subprocess.check_call( - [sys.executable, 'setup.py', 'bdist_wheel'], - cwd=str(temp_pkg)) - dist_dir = temp_pkg.join('dist') + [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.startswith('Test-1.0-py2.py3-') - assert wheels[0].ext == '.whl' + 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') + [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' + assert wheels[0].basename.endswith("-testplat_pure.whl") + assert wheels[0].ext == ".whl" -@pytest.mark.parametrize('temp_pkg', [[True, '']], indirect=['temp_pkg']) +@pytest.mark.parametrize("temp_pkg", [[True, ""]], indirect=["temp_pkg"]) def test_plat_name_ext(temp_pkg): subprocess.check_call( - [sys.executable, 'setup.py', 'bdist_wheel', '--plat-name=testplat.arch'], - cwd=str(temp_pkg)) + [sys.executable, "setup.py", "bdist_wheel", "--plat-name=testplat.arch"], + cwd=str(temp_pkg), + ) - dist_dir = temp_pkg.join('dist') + 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_arch.whl') - assert wheels[0].ext == '.whl' + 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') + 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') + [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' + assert wheels[0].basename.endswith("-testplat_pure.whl") + assert wheels[0].ext == ".whl" -@pytest.mark.parametrize('temp_pkg', [[True, '']], indirect=['temp_pkg']) +@pytest.mark.parametrize("temp_pkg", [[True, ""]], indirect=["temp_pkg"]) def test_plat_name_ext_in_setupcfg(temp_pkg): - temp_pkg.join('setup.cfg').write('[bdist_wheel]\nplat_name=testplat.arch') + temp_pkg.join("setup.cfg").write("[bdist_wheel]\nplat_name=testplat.arch") subprocess.check_call( - [sys.executable, 'setup.py', 'bdist_wheel'], - cwd=str(temp_pkg)) + [sys.executable, "setup.py", "bdist_wheel"], cwd=str(temp_pkg) + ) - dist_dir = temp_pkg.join('dist') + 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_arch.whl') - assert wheels[0].ext == '.whl' + assert wheels[0].basename.endswith("-testplat_arch.whl") + assert wheels[0].ext == ".whl" diff --git a/tests/test_wheelfile.py b/tests/test_wheelfile.py index f6e6125..6b484ab 100644 --- a/tests/test_wheelfile.py +++ b/tests/test_wheelfile.py @@ -10,83 +10,99 @@ from wheel.wheelfile import WheelFile @pytest.fixture def wheel_path(tmpdir): - return str(tmpdir.join('test-1.0-py2.py3-none-any.whl')) + return str(tmpdir.join("test-1.0-py2.py3-none-any.whl")) def test_wheelfile_re(tmpdir): # Regression test for #208 - path = tmpdir.join('foo-2-py3-none-any.whl') - with WheelFile(str(path), 'w') as wf: - assert wf.parsed_filename.group('namever') == 'foo-2' - - -@pytest.mark.parametrize('filename', [ - 'test.whl', - 'test-1.0.whl', - 'test-1.0-py2.whl', - 'test-1.0-py2-none.whl', - 'test-1.0-py2-none-any' -]) + path = tmpdir.join("foo-2-py3-none-any.whl") + with WheelFile(str(path), "w") as wf: + assert wf.parsed_filename.group("namever") == "foo-2" + + +@pytest.mark.parametrize( + "filename", + [ + "test.whl", + "test-1.0.whl", + "test-1.0-py2.whl", + "test-1.0-py2-none.whl", + "test-1.0-py2-none-any", + ], +) def test_bad_wheel_filename(filename): exc = pytest.raises(WheelError, WheelFile, filename) - exc.match(f'^Bad wheel filename {filename!r}$') + exc.match(f"^Bad wheel filename {filename!r}$") def test_missing_record(wheel_path): - with ZipFile(wheel_path, 'w') as zf: - zf.writestr(native('hello/héllö.py'), as_bytes('print("Héllö, w0rld!")\n')) + with ZipFile(wheel_path, "w") as zf: + zf.writestr(native("hello/héllö.py"), as_bytes('print("Héllö, w0rld!")\n')) exc = pytest.raises(WheelError, WheelFile, wheel_path) exc.match("^Missing test-1.0.dist-info/RECORD file$") def test_unsupported_hash_algorithm(wheel_path): - with ZipFile(wheel_path, 'w') as zf: - zf.writestr(native('hello/héllö.py'), as_bytes('print("Héllö, w0rld!")\n')) + with ZipFile(wheel_path, "w") as zf: + zf.writestr(native("hello/héllö.py"), as_bytes('print("Héllö, w0rld!")\n')) zf.writestr( - 'test-1.0.dist-info/RECORD', - as_bytes('hello/héllö.py,sha000=bv-QV3RciQC2v3zL8Uvhd_arp40J5A9xmyubN34OVwo,25')) + "test-1.0.dist-info/RECORD", + as_bytes( + "hello/héllö.py,sha000=bv-QV3RciQC2v3zL8Uvhd_arp40J5A9xmyubN34OVwo,25" + ), + ) exc = pytest.raises(WheelError, WheelFile, wheel_path) exc.match("^Unsupported hash algorithm: sha000$") -@pytest.mark.parametrize('algorithm, digest', [ - ('md5', '4J-scNa2qvSgy07rS4at-Q'), - ('sha1', 'QjCnGu5Qucb6-vir1a6BVptvOA4') -], ids=['md5', 'sha1']) +@pytest.mark.parametrize( + "algorithm, digest", + [("md5", "4J-scNa2qvSgy07rS4at-Q"), ("sha1", "QjCnGu5Qucb6-vir1a6BVptvOA4")], + ids=["md5", "sha1"], +) def test_weak_hash_algorithm(wheel_path, algorithm, digest): - hash_string = f'{algorithm}={digest}' - with ZipFile(wheel_path, 'w') as zf: - zf.writestr(native('hello/héllö.py'), as_bytes('print("Héllö, w0rld!")\n')) - zf.writestr('test-1.0.dist-info/RECORD', - as_bytes(f'hello/héllö.py,{hash_string},25')) + hash_string = f"{algorithm}={digest}" + with ZipFile(wheel_path, "w") as zf: + zf.writestr(native("hello/héllö.py"), as_bytes('print("Héllö, w0rld!")\n')) + zf.writestr( + "test-1.0.dist-info/RECORD", as_bytes(f"hello/héllö.py,{hash_string},25") + ) exc = pytest.raises(WheelError, WheelFile, wheel_path) exc.match(fr"^Weak hash algorithm \({algorithm}\) is not permitted by PEP 427$") -@pytest.mark.parametrize('algorithm, digest', [ - ('sha256', 'bv-QV3RciQC2v3zL8Uvhd_arp40J5A9xmyubN34OVwo'), - ('sha384', 'cDXriAy_7i02kBeDkN0m2RIDz85w6pwuHkt2PZ4VmT2PQc1TZs8Ebvf6eKDFcD_S'), - ('sha512', 'kdX9CQlwNt4FfOpOKO_X0pn_v1opQuksE40SrWtMyP1NqooWVWpzCE3myZTfpy8g2azZON_' - 'iLNpWVxTwuDWqBQ') -], ids=['sha256', 'sha384', 'sha512']) +@pytest.mark.parametrize( + "algorithm, digest", + [ + ("sha256", "bv-QV3RciQC2v3zL8Uvhd_arp40J5A9xmyubN34OVwo"), + ("sha384", "cDXriAy_7i02kBeDkN0m2RIDz85w6pwuHkt2PZ4VmT2PQc1TZs8Ebvf6eKDFcD_S"), + ( + "sha512", + "kdX9CQlwNt4FfOpOKO_X0pn_v1opQuksE40SrWtMyP1NqooWVWpzCE3myZTfpy8g2azZON_" + "iLNpWVxTwuDWqBQ", + ), + ], + ids=["sha256", "sha384", "sha512"], +) def test_testzip(wheel_path, algorithm, digest): - hash_string = f'{algorithm}={digest}' - with ZipFile(wheel_path, 'w') as zf: - zf.writestr(native('hello/héllö.py'), as_bytes('print("Héllö, world!")\n')) - zf.writestr('test-1.0.dist-info/RECORD', - as_bytes(f'hello/héllö.py,{hash_string},25')) + hash_string = f"{algorithm}={digest}" + with ZipFile(wheel_path, "w") as zf: + zf.writestr(native("hello/héllö.py"), as_bytes('print("Héllö, world!")\n')) + zf.writestr( + "test-1.0.dist-info/RECORD", as_bytes(f"hello/héllö.py,{hash_string},25") + ) with WheelFile(wheel_path) as wf: wf.testzip() def test_testzip_missing_hash(wheel_path): - with ZipFile(wheel_path, 'w') as zf: - zf.writestr(native('hello/héllö.py'), as_bytes('print("Héllö, world!")\n')) - zf.writestr('test-1.0.dist-info/RECORD', '') + with ZipFile(wheel_path, "w") as zf: + zf.writestr(native("hello/héllö.py"), as_bytes('print("Héllö, world!")\n')) + zf.writestr("test-1.0.dist-info/RECORD", "") with WheelFile(wheel_path) as wf: exc = pytest.raises(WheelError, wf.testzip) @@ -94,11 +110,14 @@ def test_testzip_missing_hash(wheel_path): def test_testzip_bad_hash(wheel_path): - with ZipFile(wheel_path, 'w') as zf: - zf.writestr(native('hello/héllö.py'), as_bytes('print("Héllö, w0rld!")\n')) + with ZipFile(wheel_path, "w") as zf: + zf.writestr(native("hello/héllö.py"), as_bytes('print("Héllö, w0rld!")\n')) zf.writestr( - 'test-1.0.dist-info/RECORD', - as_bytes('hello/héllö.py,sha256=bv-QV3RciQC2v3zL8Uvhd_arp40J5A9xmyubN34OVwo,25')) + "test-1.0.dist-info/RECORD", + as_bytes( + "hello/héllö.py,sha256=bv-QV3RciQC2v3zL8Uvhd_arp40J5A9xmyubN34OVwo,25" + ), + ) with WheelFile(wheel_path) as wf: exc = pytest.raises(WheelError, wf.testzip) @@ -106,66 +125,68 @@ def test_testzip_bad_hash(wheel_path): def test_write_str(wheel_path): - with WheelFile(wheel_path, 'w') as wf: - wf.writestr(native('hello/héllö.py'), as_bytes('print("Héllö, world!")\n')) - wf.writestr(native('hello/h,ll,.py'), as_bytes('print("Héllö, world!")\n')) + with WheelFile(wheel_path, "w") as wf: + wf.writestr(native("hello/héllö.py"), as_bytes('print("Héllö, world!")\n')) + wf.writestr(native("hello/h,ll,.py"), as_bytes('print("Héllö, world!")\n')) - with ZipFile(wheel_path, 'r') as zf: + with ZipFile(wheel_path, "r") as zf: infolist = zf.infolist() assert len(infolist) == 3 - assert infolist[0].filename == native('hello/héllö.py') + assert infolist[0].filename == native("hello/héllö.py") assert infolist[0].file_size == 25 - assert infolist[1].filename == native('hello/h,ll,.py') + assert infolist[1].filename == native("hello/h,ll,.py") assert infolist[1].file_size == 25 - assert infolist[2].filename == 'test-1.0.dist-info/RECORD' + assert infolist[2].filename == "test-1.0.dist-info/RECORD" - record = zf.read('test-1.0.dist-info/RECORD') + record = zf.read("test-1.0.dist-info/RECORD") assert record == as_bytes( - 'hello/héllö.py,sha256=bv-QV3RciQC2v3zL8Uvhd_arp40J5A9xmyubN34OVwo,25\n' + "hello/héllö.py,sha256=bv-QV3RciQC2v3zL8Uvhd_arp40J5A9xmyubN34OVwo,25\n" '"hello/h,ll,.py",sha256=bv-QV3RciQC2v3zL8Uvhd_arp40J5A9xmyubN34OVwo,25\n' - 'test-1.0.dist-info/RECORD,,\n') + "test-1.0.dist-info/RECORD,,\n" + ) def test_timestamp(tmpdir_factory, wheel_path, monkeypatch): # An environment variable can be used to influence the timestamp on # TarInfo objects inside the zip. See issue #143. - build_dir = tmpdir_factory.mktemp('build') - for filename in ('one', 'two', 'three'): - build_dir.join(filename).write(filename + '\n') + build_dir = tmpdir_factory.mktemp("build") + for filename in ("one", "two", "three"): + build_dir.join(filename).write(filename + "\n") # The earliest date representable in TarInfos, 1980-01-01 - monkeypatch.setenv(native('SOURCE_DATE_EPOCH'), native('315576060')) + monkeypatch.setenv(native("SOURCE_DATE_EPOCH"), native("315576060")) - with WheelFile(wheel_path, 'w') as wf: + with WheelFile(wheel_path, "w") as wf: wf.write_files(str(build_dir)) - with ZipFile(wheel_path, 'r') as zf: + with ZipFile(wheel_path, "r") as zf: for info in zf.infolist(): assert info.date_time[:3] == (1980, 1, 1) assert info.compress_type == ZIP_DEFLATED -@pytest.mark.skipif(sys.platform == 'win32', - reason='Windows does not support UNIX-like permissions') +@pytest.mark.skipif( + sys.platform == "win32", reason="Windows does not support UNIX-like permissions" +) def test_attributes(tmpdir_factory, wheel_path): # With the change from ZipFile.write() to .writestr(), we need to manually # set member attributes. - build_dir = tmpdir_factory.mktemp('build') - files = (('foo', 0o644), ('bar', 0o755)) + build_dir = tmpdir_factory.mktemp("build") + files = (("foo", 0o644), ("bar", 0o755)) for filename, mode in files: path = build_dir.join(filename) - path.write(filename + '\n') + path.write(filename + "\n") path.chmod(mode) - with WheelFile(wheel_path, 'w') as wf: + with WheelFile(wheel_path, "w") as wf: wf.write_files(str(build_dir)) - with ZipFile(wheel_path, 'r') as zf: + with ZipFile(wheel_path, "r") as zf: for filename, mode in files: info = zf.getinfo(filename) assert info.external_attr == (mode | 0o100000) << 16 assert info.compress_type == ZIP_DEFLATED - info = zf.getinfo('test-1.0.dist-info/RECORD') + info = zf.getinfo("test-1.0.dist-info/RECORD") permissions = (info.external_attr >> 16) & 0o777 assert permissions == 0o664 diff --git a/tests/testdata/abi3extension.dist/setup.py b/tests/testdata/abi3extension.dist/setup.py index e9a08df..10127da 100644 --- a/tests/testdata/abi3extension.dist/setup.py +++ b/tests/testdata/abi3extension.dist/setup.py @@ -1,11 +1,10 @@ from setuptools import setup, Extension -setup(name='extension.dist', - version='0.1', - description='A testing distribution \N{SNOWMAN}', - ext_modules=[ - Extension(name='extension', - sources=['extension.c'], - py_limited_api=True) - ], - ) +setup( + name="extension.dist", + version="0.1", + description="A testing distribution \N{SNOWMAN}", + ext_modules=[ + Extension(name="extension", sources=["extension.c"], py_limited_api=True) + ], +) diff --git a/tests/testdata/commasinfilenames.dist/setup.py b/tests/testdata/commasinfilenames.dist/setup.py index 8cf9e4e..b24e0cb 100644 --- a/tests/testdata/commasinfilenames.dist/setup.py +++ b/tests/testdata/commasinfilenames.dist/setup.py @@ -1,12 +1,10 @@ from setuptools import setup setup( - name='testrepo', - version='0.1', + name="testrepo", + version="0.1", packages=["mypackage"], - description='A test package with commas in file names', + description="A test package with commas in file names", include_package_data=True, - package_data={ - "mypackage.data": ["*"] - }, + package_data={"mypackage.data": ["*"]}, ) diff --git a/tests/testdata/complex-dist/setup.py b/tests/testdata/complex-dist/setup.py index 632ae3f..70d85df 100644 --- a/tests/testdata/complex-dist/setup.py +++ b/tests/testdata/complex-dist/setup.py @@ -1,21 +1,22 @@ from setuptools import setup -setup(name='complex-dist', - version='0.1', - description='Another testing distribution \N{SNOWMAN}', - long_description='Another testing distribution \N{SNOWMAN}', - author="Illustrious Author", - author_email="illustrious@example.org", - url="http://example.org/exemplary", - packages=['complexdist'], - setup_requires=["wheel", "setuptools"], - install_requires=["quux", "splort"], - extras_require={'simple': ['simple.dist']}, - tests_require=["foo", "bar>=10.0.0"], - entry_points={ - 'console_scripts': [ - 'complex-dist=complexdist:main', - 'complex-dist2=complexdist:main', - ], - }, - ) +setup( + name="complex-dist", + version="0.1", + description="Another testing distribution \N{SNOWMAN}", + long_description="Another testing distribution \N{SNOWMAN}", + author="Illustrious Author", + author_email="illustrious@example.org", + url="http://example.org/exemplary", + packages=["complexdist"], + setup_requires=["wheel", "setuptools"], + install_requires=["quux", "splort"], + extras_require={"simple": ["simple.dist"]}, + tests_require=["foo", "bar>=10.0.0"], + entry_points={ + "console_scripts": [ + "complex-dist=complexdist:main", + "complex-dist2=complexdist:main", + ], + }, +) diff --git a/tests/testdata/extension.dist/setup.py b/tests/testdata/extension.dist/setup.py index c9bf948..fc4042b 100644 --- a/tests/testdata/extension.dist/setup.py +++ b/tests/testdata/extension.dist/setup.py @@ -1,10 +1,8 @@ from setuptools import setup, Extension -setup(name='extension.dist', - version='0.1', - description='A testing distribution \N{SNOWMAN}', - ext_modules=[ - Extension(name='extension', - sources=['extension.c']) - ], - ) +setup( + name="extension.dist", + version="0.1", + description="A testing distribution \N{SNOWMAN}", + ext_modules=[Extension(name="extension", sources=["extension.c"])], +) diff --git a/tests/testdata/headers.dist/setup.py b/tests/testdata/headers.dist/setup.py index 2c7d7ea..d9d8adb 100644 --- a/tests/testdata/headers.dist/setup.py +++ b/tests/testdata/headers.dist/setup.py @@ -1,7 +1,8 @@ from setuptools import setup -setup(name='headers.dist', - version='0.1', - description='A distribution with headers', - headers=['header.h'] - ) +setup( + name="headers.dist", + version="0.1", + description="A distribution with headers", + headers=["header.h"], +) diff --git a/tests/testdata/simple.dist/setup.py b/tests/testdata/simple.dist/setup.py index 81b26cd..3c7da87 100644 --- a/tests/testdata/simple.dist/setup.py +++ b/tests/testdata/simple.dist/setup.py @@ -1,8 +1,9 @@ from setuptools import setup -setup(name='simple.dist', - version='0.1', - description='A testing distribution \N{SNOWMAN}', - packages=['simpledist'], - extras_require={'voting': ['beaglevote']}, - ) +setup( + name="simple.dist", + version="0.1", + description="A testing distribution \N{SNOWMAN}", + packages=["simpledist"], + extras_require={"voting": ["beaglevote"]}, +) diff --git a/tests/testdata/unicode.dist/setup.py b/tests/testdata/unicode.dist/setup.py index 221088e..606f42a 100644 --- a/tests/testdata/unicode.dist/setup.py +++ b/tests/testdata/unicode.dist/setup.py @@ -1,7 +1,8 @@ from setuptools import setup -setup(name='unicode.dist', - version='0.1', - description='A testing distribution \N{SNOWMAN}', - packages=['unicodedist'] - ) +setup( + name="unicode.dist", + version="0.1", + description="A testing distribution \N{SNOWMAN}", + packages=["unicodedist"], +) @@ -13,6 +13,12 @@ isolated_build = true commands = {envpython} -b -m pytest -W always {posargs} extras = test +[testenv:black] +basepython = python3 +deps = black +commands = black src tests +skip_install = true + [testenv:flake8] basepython = python3 deps = flake8 |
