Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retag wheels automatically when fusing #215

Merged
merged 21 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion delocate/cmd/delocate_fuse.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
help="Directory to store delocated wheels"
" (default is to overwrite 1st WHEEL input with 2nd)",
)
parser.add_argument(
"--retag",
action="store_true",
help="Retag the fused wheel. This includes updating its filename and"
" dist-info (Only works when fusing to make a universal2 wheel)",
)


def main() -> None: # noqa: D103
Expand All @@ -36,7 +42,7 @@ def main() -> None: # noqa: D103
out_wheel = wheel1
else:
out_wheel = pjoin(abspath(expanduser(args.wheel_dir)), basename(wheel1))
fuse_wheels(wheel1, wheel2, out_wheel)
fuse_wheels(wheel1, wheel2, out_wheel, retag=args.retag)


if __name__ == "__main__":
Expand Down
22 changes: 14 additions & 8 deletions delocate/delocating.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
tree_libs,
tree_libs_from_directory,
)
from .pkginfo import read_pkg_info, write_pkg_info
from .tmpdirs import TemporaryDirectory
from .tools import (
_is_macho_file,
Expand Down Expand Up @@ -653,6 +654,14 @@ def _get_archs_and_version_from_wheel_name(
raise ValueError(f"Invalid platform tag: {platform_tag.platform}")
major, minor, arch = match.groups()
platform_requirements[arch] = Version(f"{major}.{minor}")
# If we have a wheel name with arm64 and x86_64 we have to convert that to
# universal2
if set(platform_requirements.keys()) == set(("arm64", "x86_64")):
dunkmann00 marked this conversation as resolved.
Show resolved Hide resolved
version = platform_requirements["arm64"]
if version == Version("11.0"):
version = platform_requirements["x86_64"]
platform_requirements = {"universal2": version}

return platform_requirements


Expand Down Expand Up @@ -867,14 +876,11 @@ def _update_wheelfile(wheel_dir: Path, wheel_name: str) -> None:
"""
platform_tag_set = parse_wheel_filename(wheel_name)[-1]
(file_path,) = wheel_dir.glob("*.dist-info/WHEEL")
with file_path.open(encoding="utf-8") as f:
lines = f.readlines()
with file_path.open("w", encoding="utf-8") as f:
for line in lines:
if line.startswith("Tag:"):
f.write(f"Tag: {'.'.join(str(x) for x in platform_tag_set)}\n")
else:
f.write(line)
info = read_pkg_info(file_path)
del info["Tag"]
for tag in platform_tag_set:
info.add_header("Tag", str(tag))
write_pkg_info(file_path, info)


def delocate_wheel(
Expand Down
58 changes: 56 additions & 2 deletions delocate/fuse.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@

import os
import shutil
from os.path import abspath, exists, relpath, splitext
from os.path import abspath, basename, exists, relpath, splitext
from os.path import dirname as pdirname
from os.path import join as pjoin
from pathlib import Path

from packaging.utils import parse_wheel_filename

from .delocating import _check_and_update_wheel_name, _update_wheelfile
from .tmpdirs import InTemporaryDirectory
from .tools import (
chmod_perms,
Expand All @@ -39,6 +44,41 @@ def _copyfile(in_fname, out_fname):
os.chmod(out_fname, perms)


def retag_wheel(to_wheel, from_wheel, to_tree):
dunkmann00 marked this conversation as resolved.
Show resolved Hide resolved
"""Update the name and dist-info to reflect a univeral2 wheel.

Parameters
----------
to_wheel : str
filename of wheel to fuse into
from_wheel : str
filename of wheel to fuse from
to_tree : str
path of tree to fuse into (update into)

Returns
-------
retag_name : str
The new, retagged name the out wheel should be.
"""
# Add from_wheel platform tags onto to_wheel filename, but make sure to not
# add a tag if it is already there
from_wheel_tags = parse_wheel_filename(basename(from_wheel))[-1]
to_wheel_tags = parse_wheel_filename(basename(to_wheel))[-1]
add_platform_tags = (
f".{tag.platform}" for tag in from_wheel_tags - to_wheel_tags
)
retag_name = Path(to_wheel).stem + "".join(add_platform_tags) + ".whl"

retag_name = _check_and_update_wheel_name(
Path(retag_name), to_tree, None
).name

_update_wheelfile(Path(to_tree), retag_name)

return retag_name


def fuse_trees(to_tree, from_tree, lib_exts=(".so", ".dylib", ".a")):
"""Fuse path `from_tree` into path `to_tree`.

Expand Down Expand Up @@ -83,7 +123,7 @@ def fuse_trees(to_tree, from_tree, lib_exts=(".so", ".dylib", ".a")):
_copyfile(from_path, to_path)


def fuse_wheels(to_wheel, from_wheel, out_wheel):
def fuse_wheels(to_wheel, from_wheel, out_wheel, retag):
dunkmann00 marked this conversation as resolved.
Show resolved Hide resolved
"""Fuse `from_wheel` into `to_wheel`, write to `out_wheel`.

Parameters
Expand All @@ -94,13 +134,27 @@ def fuse_wheels(to_wheel, from_wheel, out_wheel):
filename of wheel to fuse from
out_wheel : str
filename of new wheel from fusion of `to_wheel` and `from_wheel`
retag : bool
update the name and dist-info of the out_wheel to reflect univeral2

Returns
-------
out_wheel : str
filename of new wheel from fusion of `to_wheel` and `from_wheel` (May be
different than what was passed in to the function when `retag` is
`True`)
"""
to_wheel, from_wheel, out_wheel = [
abspath(w) for w in (to_wheel, from_wheel, out_wheel)
]

with InTemporaryDirectory():
zip2dir(to_wheel, "to_wheel")
dunkmann00 marked this conversation as resolved.
Show resolved Hide resolved
zip2dir(from_wheel, "from_wheel")
fuse_trees("to_wheel", "from_wheel")
if retag:
out_wheel_name = retag_wheel(to_wheel, from_wheel, "to_wheel")
out_wheel = pjoin(pdirname(out_wheel), out_wheel_name)
rewrite_record("to_wheel")
dir2zip("to_wheel", out_wheel)
return out_wheel
Loading