1#!/usr/bin/env python3
2
3# We do not need to import built modules from PCbuild (duh), so
4# filter those out here to save Steve from debugging it yet again.
5import sys
6sys.path[:] = [p for p in sys.path if p and 'PCbuild' not in p]
7
8import argparse
9import os
10import pathlib
11import zipfile
12from urllib.request import urlretrieve
13
14def fetch_zip(commit_hash, zip_dir, *, org='python', binary=False, verbose):
15    repo = f'cpython-{"bin" if binary else "source"}-deps'
16    url = f'https://github.com/{org}/{repo}/archive/{commit_hash}.zip'
17    reporthook = None
18    if verbose:
19        reporthook = print
20    zip_dir.mkdir(parents=True, exist_ok=True)
21    filename, headers = urlretrieve(
22        url,
23        zip_dir / f'{commit_hash}.zip',
24        reporthook=reporthook,
25    )
26    return filename
27
28
29def extract_zip(externals_dir, zip_path):
30    with zipfile.ZipFile(os.fspath(zip_path)) as zf:
31        zf.extractall(os.fspath(externals_dir))
32        return externals_dir / zf.namelist()[0].split('/')[0]
33
34
35def parse_args():
36    p = argparse.ArgumentParser()
37    p.add_argument('-v', '--verbose', action='store_true')
38    p.add_argument('-b', '--binary', action='store_true',
39                   help='Is the dependency in the binary repo?')
40    p.add_argument('-O', '--organization',
41                   help='Organization owning the deps repos', default='python')
42    p.add_argument('-e', '--externals-dir', type=pathlib.Path,
43                   help='Directory in which to store dependencies',
44                   default=pathlib.Path(__file__).parent.parent / 'externals')
45    p.add_argument('tag',
46                   help='tag of the dependency')
47    return p.parse_args()
48
49
50def main():
51    args = parse_args()
52    zip_path = fetch_zip(
53        args.tag,
54        args.externals_dir / 'zips',
55        org=args.organization,
56        binary=args.binary,
57        verbose=args.verbose,
58    )
59    final_name = args.externals_dir / args.tag
60    extract_zip(args.externals_dir, zip_path).replace(final_name)
61
62
63if __name__ == '__main__':
64    main()
65