"""Fetch a hash-pinned independent LGPL reference from its named upstream. The public teaching package contains our caller, not a copy of this library. """ from pathlib import Path import argparse import hashlib import json import urllib.parse import urllib.request def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--manifest', type=Path, default=Path(__file__).with_name('reference-sources.json')) parser.add_argument('--output', type=Path, required=True) arguments = parser.parse_args() manifest = json.loads(arguments.manifest.read_text()) arguments.output.mkdir(parents=True, exist_ok=True) receipt = {'commit': manifest['commit'], 'license': 'LGPL-3.0, retained in downloaded LICENSE', 'files': []} for item in manifest['files']: if item['path'] == 'setup.py': continue url = urllib.parse.urlsplit(item['url']) if url.scheme != 'https' or url.hostname != 'raw.githubusercontent.com' or not url.path.startswith('/valboz/VBBinaryLensing/' + manifest['commit'] + '/'): raise ValueError('Unexpected reference origin') destination = arguments.output / Path(item['path']).name mode = 'verified local cache; no HTTP' status = None if destination.exists(): data = destination.read_bytes() else: request = urllib.request.Request(item['url'], headers={'User-Agent': 'SandboxPhysics-Public-Tutorial/1.0'}) with urllib.request.urlopen(request, timeout=30) as response: status = response.status if status != 200: raise ValueError('Unexpected reference response') data = response.read(item['bytes'] + 1) mode = 'anonymous upstream HTTP' if len(data) != item['bytes'] or hashlib.sha256(data).hexdigest() != item['sha256']: raise ValueError('Reference changed; refuse silently updated input: ' + item['path']) if not destination.exists(): destination.write_bytes(data) receipt['files'].append({'name': destination.name, 'url': item['url'], 'mode': mode, 'status': status, 'bytes': len(data), 'sha256': item['sha256']}) (arguments.output / 'download-receipt.json').write_text(json.dumps(receipt, indent=2) + '\n') print('PASS:', len(receipt['files']), 'hash-pinned independent reference files') if __name__ == '__main__': main()