Fix PEP-425 defined tag shrinking

This commit is contained in:
Reid 'arrdem' McKenzie 2021-08-29 16:05:00 -06:00
parent df5294379a
commit a68c09d6b1
2 changed files with 66 additions and 13 deletions

View file

@ -7,6 +7,7 @@ import io
import json import json
import os import os
import pathlib import pathlib
from itertools import chain
import stat import stat
import sys import sys
import zipfile import zipfile
@ -15,6 +16,7 @@ from shutil import move
from tempfile import TemporaryDirectory from tempfile import TemporaryDirectory
from zapp.support.unpack import cache_wheel_path from zapp.support.unpack import cache_wheel_path
from zapp.support.pep425 import compress_tags, decompress_tag
parser = argparse.ArgumentParser(description="The (bootstrap) Zapp compiler") parser = argparse.ArgumentParser(description="The (bootstrap) Zapp compiler")
parser.add_argument("-o", "--out", dest="output", help="Output target file") parser.add_argument("-o", "--out", dest="output", help="Output target file")
@ -81,7 +83,14 @@ def load_wheel(opts, manifest, path):
"""Load a single wheel, returning ...""" """Load a single wheel, returning ..."""
def _parse_email(msg): def _parse_email(msg):
return dict(Parser().parsestr(msg).items()) msg = Parser().parsestr(msg)
def _get(k):
v = msg.get_all(k)
if len(v) == 1:
return v[0]
else:
return v
return {k: _get(k) for k in msg.keys()}
# RECORD seems to just record file reference checksums for validation # RECORD seems to just record file reference checksums for validation
# with open(os.path.join(path, "RECORD")) as recordf: # with open(os.path.join(path, "RECORD")) as recordf:
@ -105,14 +114,16 @@ def load_wheel(opts, manifest, path):
} }
def wheel_name(wheel): def wheel_name(wheel):
"""Construct the "canonical" filename of the wheel.""" """Construct the "canonical" filename of the wheel."""
# https://www.python.org/dev/peps/pep-0425/
tags = wheel["wheel"].get("Tag") tags = wheel["wheel"].get("Tag")
if isinstance(tags, list): if isinstance(tags, list):
tags = "-" + ".".join(sorted(wheel["wheel"]["Tag"])) tags = "-" + compress_tags(chain(*[decompress_tag(t) for t in tags]))
elif isinstance(tags, str): elif isinstance(tags, str):
tags = "-" + wheel["wheel"]["Tag"] tags = "-" + tags
else: else:
tags = "" tags = ""
@ -155,17 +166,23 @@ def rezip_wheels(opts, manifest):
# Zip up the wheels and insert wheel records to the manifest # Zip up the wheels and insert wheel records to the manifest
for w in wheels: for w in wheels:
# Try to cheat and hit in the local cache first rather than building wheels every time # Try to cheat and hit in the local cache first rather than building wheels every time
wf = cache_wheel_path(wheel_name(w)) wn = wheel_name(w)
if wf.exists():
try:
wf.touch()
except OSError:
pass
else:
wf = zip_wheel(opts.tmpdir, w)
# Insert a new wheel source # We may have a double-path dependency.
manifest["wheels"][wheel_name(w)] = {"hashes": [], "source": wf} # If we DON'T, we have to zip
if wn not in manifest["wheels"]:
wf = cache_wheel_path(wn)
if wf.exists():
try:
wf.touch()
except OSError:
pass
wf = str(wf)
else:
wf = zip_wheel(opts.tmpdir, w)
# Insert a new wheel source
manifest["wheels"][wn] = {"hashes": [], "source": wf}
# Expunge sources available in the wheel # Expunge sources available in the wheel
manifest["sources"] = dsub(manifest["sources"], w["sources"]) manifest["sources"] = dsub(manifest["sources"], w["sources"])

36
zapp/support/pep425.py Normal file
View file

@ -0,0 +1,36 @@
"""An implementation of PEP-425 tag parsing, expansion and compression."""
import typing as t
class Tag(t.NamedTuple):
python: str
abi: str
arch: str # 'Platform' in the PEP
def decompress_tag(tag: str) -> t.Iterable[Tag]:
"""Decompress tag string into a sequence of compatible tuples."""
pytags, abitags, archtags = tag.split("-", 2)
for x in pytags.split('.'):
for y in abitags.split('.'):
for z in archtags.split('.'):
yield Tag(x, y, z)
def compress_tags(tags: t.Iterable[Tag]) -> str:
"""Compress a tag sequence into a string encoding compatible tuples."""
tags = set(tags)
pytags = set(t.python for t in tags)
abitags = set(t.abi for t in tags)
archtags = set(t.arch for t in tags)
tag = "-".join([
".".join(sorted(pytags)),
".".join(sorted(abitags)),
".".join(sorted(archtags)),
])
assert set(decompress_tag(tag)) == tags
return tag