From c5709d69d340050a49102dd78e11ce44fb29316d Mon Sep 17 00:00:00 2001 From: mayeut Date: Sat, 9 Oct 2021 19:48:16 +0200 Subject: [PATCH 1/4] Try wheel cli Try using https://github.com/pypa/wheel/pull/422 --- requirements-repair.txt | 3 +-- scripts/repair_wheel.py | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/requirements-repair.txt b/requirements-repair.txt index 2ca56a4..6288236 100644 --- a/requirements-repair.txt +++ b/requirements-repair.txt @@ -1,2 +1 @@ -git+https://github.com/jcfr/wheeltools.git@wheeltools-2018-10-28-a2f174d0e -wheel<0.38 +git+https://github.com/henryiii/wheel.git@deb2a78012b41bb3a9ebdef9e139261d62ce6be5 diff --git a/scripts/repair_wheel.py b/scripts/repair_wheel.py index 737df38..1467d5d 100644 --- a/scripts/repair_wheel.py +++ b/scripts/repair_wheel.py @@ -8,8 +8,6 @@ import zipfile from pathlib import Path -from convert_to_generic_platform_wheel import convert_to_generic_platform_wheel - def main(): if sys.platform.startswith("linux"): @@ -56,8 +54,8 @@ def main(): assert len(files) == 1, files file = files[0] - # we need to handle macOS x86_64 & arm64 here for now, let's use additional_platforms for this. - additional_platforms = [] + # we need to handle macOS x86_64 & arm64 here for now, let's use platform_tag_args for this. + platform_tag_args = [] if os_ == "macos": # delocate-wheel --require-archs does not seem to check executables... with tempfile.TemporaryDirectory() as tmpdir2_: @@ -67,7 +65,7 @@ def main(): exe = list(tmpdir2.glob("**/bin/ninja")) assert len(exe) == 1, exe subprocess.run(["lipo", str(exe[0]), "-verify_arch", "x86_64", "arm64"], check=True, stdout=subprocess.PIPE) - + additional_platforms = [] # first, get the target macOS deployment target from the wheel match = re.match(r"^.*-macosx_(\d+)_(\d+)_.*\.whl$", file.name) assert match is not None, f"Couldn't match on {file.name}" @@ -88,13 +86,18 @@ def main(): # They're were also issues with pip not picking up some universal2 wheels, tag twice additional_platforms.append("macosx_11_0_universal2") + platform_tag_args = ["--platform-tag", f".{'.'.join(additional_platforms)}"] + # make this a py2.py3 wheel - convert_to_generic_platform_wheel( - str(file), - out_dir=str(wheelhouse), - py2_py3=True, - additional_platforms=additional_platforms, + subprocess.run( + ["wheel", "tags", "--python-tag", "py2.py3", "--abi-tag", "none", *platform_tag_args, "--remove", str(file)], + check=True, + stdout=subprocess.PIPE, ) + files = list(tmpdir.glob("*.whl")) + assert len(files) == 1, files + file = files[0] + file.rename(wheelhouse / file.name) if __name__ == "__main__": From cf4e5f4b26a30c4af15f492f19c88977d035e46f Mon Sep 17 00:00:00 2001 From: mayeut Date: Sat, 9 Oct 2021 20:04:26 +0200 Subject: [PATCH 2/4] Update pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6af9975..5f15151 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ before-all = [ 'pipx install -f --pip-args="-c {project}/constraints-ci.txt" cmake', 'cmake --version', ] -before-build = "pip install -r requirements-repair.txt" +before-build = "pip install --upgrade --force-reinstall -r requirements-repair.txt" repair-wheel-command = "python scripts/repair_wheel.py -w {dest_dir} {wheel}" test-extras = "test" test-command = "pytest {project}/tests" From 08a6bf883d60a93e2e0f0e15d7c4e6018a806fe8 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Thu, 30 Dec 2021 12:12:54 -0500 Subject: [PATCH 3/4] Update requirements-repair.txt --- requirements-repair.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-repair.txt b/requirements-repair.txt index 6288236..26a1ca1 100644 --- a/requirements-repair.txt +++ b/requirements-repair.txt @@ -1 +1 @@ -git+https://github.com/henryiii/wheel.git@deb2a78012b41bb3a9ebdef9e139261d62ce6be5 +git+https://github.com/henryiii/wheel.git@de5b0e90886e9ac18e0b67a747ae764e9bb2a612 From 5abecec51c617454d0d89c644d2409c4b9252536 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Tue, 14 Mar 2023 15:43:23 -0400 Subject: [PATCH 4/4] chore: use the recently released wheel 0.40 Signed-off-by: Henry Schreiner --- pyproject.toml | 2 +- requirements-repair.txt | 2 +- scripts/convert_to_generic_platform_wheel.py | 208 ------------------- scripts/repair_wheel.py | 2 +- 4 files changed, 3 insertions(+), 211 deletions(-) delete mode 100644 scripts/convert_to_generic_platform_wheel.py diff --git a/pyproject.toml b/pyproject.toml index 5f15151..6af9975 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ before-all = [ 'pipx install -f --pip-args="-c {project}/constraints-ci.txt" cmake', 'cmake --version', ] -before-build = "pip install --upgrade --force-reinstall -r requirements-repair.txt" +before-build = "pip install -r requirements-repair.txt" repair-wheel-command = "python scripts/repair_wheel.py -w {dest_dir} {wheel}" test-extras = "test" test-command = "pytest {project}/tests" diff --git a/requirements-repair.txt b/requirements-repair.txt index 26a1ca1..de121f3 100644 --- a/requirements-repair.txt +++ b/requirements-repair.txt @@ -1 +1 @@ -git+https://github.com/henryiii/wheel.git@de5b0e90886e9ac18e0b67a747ae764e9bb2a612 +wheel>=0.40.0 diff --git a/scripts/convert_to_generic_platform_wheel.py b/scripts/convert_to_generic_platform_wheel.py deleted file mode 100644 index 7296d73..0000000 --- a/scripts/convert_to_generic_platform_wheel.py +++ /dev/null @@ -1,208 +0,0 @@ -# -*- coding: utf-8 -*- -import argparse -import logging -import os -import sys -from itertools import product -from os.path import abspath, basename, dirname, isfile, splitext -from os.path import join as pjoin - -try: - from wheel.install import WheelFile -except ImportError: # As of Wheel 0.32.0 - from wheel.wheelfile import WheelFile - -from wheel.pkginfo import read_pkg_info, write_pkg_info -from wheeltools.tools import unique_by_index -from wheeltools.wheeltools import InWheelCtx - -logger = logging.getLogger(splitext(basename(__file__))[0]) - - -def _get_wheelinfo_name(wheelfile): - # Work round wheel API compatibility - try: - return wheelfile.wheelinfo_name - except AttributeError: - return wheelfile.dist_info_path + "/WHEEL" - - -def _to_generic_pyver(pyver_tags): - """Convert from CPython implementation to generic python version tags - - Convert each CPython version tag to the equivalent generic tag. - - For example:: - - cp35 -> py3 - cp27 -> py2 - - See https://www.python.org/dev/peps/pep-0425/#python-tag - """ - return ['py%s' % tag[2] if tag.startswith('cp') else tag for tag in pyver_tags] - - -def _convert_to_generic_platform_wheel(wheel_ctx, py2_py3, additional_platforms): - """Switch to generic python tags and remove ABI tags from a wheel - - Convert implementation specific python tags to their generic equivalent and - remove all ABI tags from wheel_ctx's filename and ``WHEEL`` file. - - Parameters - ---------- - wheel_ctx : InWheelCtx - An open wheel context - py2_py3: Bool - Whether the pyver tag shall be py2.py3 or just the one inferred from the wheel name - additional_platforms : Optional[Iterable[str]] - An optional iterable of additional platform to add to the wheel - """ - - abi_tags = ['none'] - - wf = WheelFile(wheel_ctx.in_wheel) - info_fname = _get_wheelinfo_name(wf) - info = read_pkg_info(info_fname) - - # Check what tags we have - if wheel_ctx.out_wheel is not None: - out_dir = dirname(wheel_ctx.out_wheel) - wheel_fname = basename(wheel_ctx.out_wheel) - else: - out_dir = '.' - wheel_fname = basename(wheel_ctx.in_wheel) - - # Update wheel filename - fparts = wf.parsed_filename.groupdict() - platform_tags = fparts['plat'].split('.') - logger.debug('Previous platform tags: %s', ', '.join(platform_tags)) - if additional_platforms: - platform_tags = sorted(set(platform_tags + list(additional_platforms))) - fparts['plat'] = '.'.join(platform_tags) - logger.debug('New platform tags ....: %s', ', '.join(platform_tags)) - else: - logger.debug('No platform tags change needed.') - - original_abi_tags = fparts['abi'].split('.') - logger.debug('Previous ABI tags: %s', ', '.join(original_abi_tags)) - if abi_tags != original_abi_tags: - logger.debug('New ABI tags ....: %s', ', '.join(abi_tags)) - fparts['abi'] = '.'.join(abi_tags) - else: - logger.debug('No ABI tags change needed.') - - original_pyver_tags = fparts['pyver'].split('.') - logger.debug('Previous pyver tags: %s', ', '.join(original_pyver_tags)) - pyver_tags = _to_generic_pyver(original_pyver_tags) - if py2_py3: - if len({"py2", "py3"} & set(pyver_tags)) == 0: - raise ValueError("pyver_tags does not contain py2 nor py3") - pyver_tags = sorted(set(pyver_tags + ["py2", "py3"])) - if pyver_tags != original_pyver_tags: - logger.debug('New pyver tags ....: %s', ', '.join(pyver_tags)) - fparts['pyver'] = '.'.join(pyver_tags) - else: - logger.debug('No pyver change needed.') - - _, ext = splitext(wheel_fname) - fparts['ext'] = ext - out_wheel_fname = "{namever}-{pyver}-{abi}-{plat}{ext}".format(**fparts) - - logger.info('Previous filename: %s', wheel_fname) - if out_wheel_fname != wheel_fname: - logger.info('New filename ....: %s', out_wheel_fname) - else: - logger.info('No filename change needed.') - - out_wheel = pjoin(out_dir, out_wheel_fname) - - # Update wheel tags - in_info_tags = [tag for name, tag in info.items() if name == 'Tag'] - logger.info('Previous WHEEL info tags: %s', ', '.join(in_info_tags)) - - # Python version, C-API version combinations - pyc_apis = [] - for py_ver in pyver_tags: - abi = 'none' - pyc_apis.append('-'.join([py_ver, abi])) - # unique Python version, C-API version combinations - pyc_apis = unique_by_index(pyc_apis) - - # Set tags for each Python version, C-API combination - updated_tags = ['-'.join(tup) for tup in product(pyc_apis, platform_tags)] - - if updated_tags != in_info_tags: - del info['Tag'] - for tag in updated_tags: - info.add_header('Tag', tag) - - logger.info('New WHEEL info tags ....: %s', ', '.join(info.get_all('Tag'))) - write_pkg_info(info_fname, info) - else: - logger.info('No WHEEL info change needed.') - return out_wheel - - -def convert_to_generic_platform_wheel(wheel_path, out_dir='./dist/', remove_original=False, verbose=0, - py2_py3=False, additional_platforms=None): - logging.disable(logging.NOTSET) - if verbose >= 1: - logging.basicConfig(level=logging.DEBUG) - else: - logging.basicConfig(level=logging.INFO) - - wheel_fname = basename(wheel_path) - out_dir = abspath(out_dir) - - with InWheelCtx(wheel_path) as ctx: - ctx.out_wheel = pjoin(out_dir, wheel_fname) - ctx.out_wheel = _convert_to_generic_platform_wheel(ctx, py2_py3, additional_platforms) - - if remove_original: - logger.info('Removed original wheel %s', wheel_path) - os.remove(wheel_path) - - -def main(): - p = argparse.ArgumentParser(description='Convert wheel to be independent of python implementation and ABI') - p.set_defaults(prog=basename(sys.argv[0])) - p.add_argument("-v", - "--verbose", - action='count', - dest='verbose', - default=0, - help='Give more output. Option is additive') - - p.add_argument('WHEEL_FILE', help='Path to wheel file.') - p.add_argument('-w', - '--wheel-dir', - dest='WHEEL_DIR', - type=abspath, - help='Directory to store updated wheels (default: "dist/")', - default='dist/') - p.add_argument("-r", - "--remove-original", - dest='remove_original', - action='store_true', - help='Remove original wheel') - p.add_argument("--py2-py3", - dest='py2_py3', - action='store_true', - help='Remove original wheel') - p.add_argument("-p", - "--add-platform", - dest='additional_platforms', - action="append", - help='Add a platform tag') - - args = p.parse_args() - - if not isfile(args.WHEEL_FILE): - p.error('cannot access %s. No such file' % args.WHEEL_FILE) - - convert_to_generic_platform_wheel(args.WHEEL_FILE, args.WHEEL_DIR, args.remove_original, args.verbose, - args.py2_py3, args.additional_platforms) - - -if __name__ == '__main__': - main() diff --git a/scripts/repair_wheel.py b/scripts/repair_wheel.py index 1467d5d..b7e14a0 100644 --- a/scripts/repair_wheel.py +++ b/scripts/repair_wheel.py @@ -86,7 +86,7 @@ def main(): # They're were also issues with pip not picking up some universal2 wheels, tag twice additional_platforms.append("macosx_11_0_universal2") - platform_tag_args = ["--platform-tag", f".{'.'.join(additional_platforms)}"] + platform_tag_args = [f"--platform-tag=+{'.'.join(additional_platforms)}"] # make this a py2.py3 wheel subprocess.run(