""" Helper script to rebuild virtualenv_support. Downloads the wheel files using pip """ from __future__ import absolute_import, unicode_literals import os import shutil import subprocess import sys from collections import OrderedDict, defaultdict from pathlib import Path from tempfile import TemporaryDirectory from threading import Thread STRICT = "UPGRADE_ADVISORY" not in os.environ BUNDLED = ["pip", "setuptools", "wheel"] SUPPORT = list(reversed([(2, 7)] + [(3, i) for i in range(4, 10)])) DEST = Path(__file__).resolve().parents[1] / "src" / "virtualenv" / "seed" / "embed" / "wheels" def download(ver, dest, package): subprocess.call( [sys.executable, "-m", "pip", "download", "--only-binary=:all:", "--python-version", ver, "-d", dest, package] ) def run(): old_batch = {i.name for i in DEST.iterdir() if i.suffix == ".whl"} with TemporaryDirectory() as temp: temp_path = Path(temp) folders = {} targets = [] for support in SUPPORT: support_ver = ".".join(str(i) for i in support) into = temp_path / support_ver into.mkdir() folders[into] = support_ver for package in BUNDLED: thread = Thread(target=download, args=(support_ver, str(into), package)) targets.append(thread) thread.start() for thread in targets: thread.join() new_batch = {i.name: i for f in folders.keys() for i in Path(f).iterdir()} new_packages = new_batch.keys() - old_batch remove_packages = old_batch - new_batch.keys() for package in remove_packages: (DEST / package).unlink() for package in new_packages: shutil.copy2(str(new_batch[package]), DEST / package) added = collect_package_versions(new_packages) removed = collect_package_versions(remove_packages) outcome = (1 if STRICT else 0) if (added or removed) else 0 for key, versions in added.items(): text = "* upgrade embedded {} to {}".format(key, fmt_version(versions)) if key in removed: text += " from {}".format(removed[key]) del removed[key] print(text) for key, versions in removed.items(): print("* removed embedded {} of {}".format(key, fmt_version(versions))) support_table = OrderedDict((".".join(str(j) for j in i), list()) for i in SUPPORT) for package in sorted(new_batch.keys()): for folder, version in sorted(folders.items()): if (folder / package).exists(): support_table[version].append(package) support_table = {k: OrderedDict((i.split("-")[0], i) for i in v) for k, v in support_table.items()} msg = "from __future__ import absolute_import, unicode_literals; BUNDLE_SUPPORT = {{ {} }}; MAX = {!r}".format( ",".join( "{!r}: {{ {} }}".format(v, ",".join("{!r}: {!r}".format(p, f) for p, f in l.items())) for v, l in support_table.items() ), next(iter(support_table.keys())), ) dest_target = DEST / "__init__.py" dest_target.write_text(msg) subprocess.run([sys.executable, "-m", "black", str(dest_target)]) raise SystemExit(outcome) def fmt_version(versions): return ", ".join("``{}``".format(v) for v in versions) def collect_package_versions(new_packages): result = defaultdict(list) for package in new_packages: split = package.split("-") if len(split) < 2: raise ValueError(package) key, version = split[0:2] result[key].append(version) return result if __name__ == "__main__": run()