(root)/
Python-3.12.0/
PCbuild/
get_external.py
       1  #!/usr/bin/env python3
       2  
       3  import argparse
       4  import os
       5  import pathlib
       6  import sys
       7  import time
       8  import zipfile
       9  from urllib.request import urlretrieve
      10  
      11  
      12  def fetch_zip(commit_hash, zip_dir, *, org='python', binary=False, verbose):
      13      repo = f'cpython-{"bin" if binary else "source"}-deps'
      14      url = f'https://github.com/{org}/{repo}/archive/{commit_hash}.zip'
      15      reporthook = None
      16      if verbose:
      17          reporthook = print
      18      zip_dir.mkdir(parents=True, exist_ok=True)
      19      filename, headers = urlretrieve(
      20          url,
      21          zip_dir / f'{commit_hash}.zip',
      22          reporthook=reporthook,
      23      )
      24      return filename
      25  
      26  
      27  def extract_zip(externals_dir, zip_path):
      28      with zipfile.ZipFile(os.fspath(zip_path)) as zf:
      29          zf.extractall(os.fspath(externals_dir))
      30          return externals_dir / zf.namelist()[0].split('/')[0]
      31  
      32  
      33  def parse_args():
      34      p = argparse.ArgumentParser()
      35      p.add_argument('-v', '--verbose', action='store_true')
      36      p.add_argument('-b', '--binary', action='store_true',
      37                     help='Is the dependency in the binary repo?')
      38      p.add_argument('-O', '--organization',
      39                     help='Organization owning the deps repos', default='python')
      40      p.add_argument('-e', '--externals-dir', type=pathlib.Path,
      41                     help='Directory in which to store dependencies',
      42                     default=pathlib.Path(__file__).parent.parent / 'externals')
      43      p.add_argument('tag',
      44                     help='tag of the dependency')
      45      return p.parse_args()
      46  
      47  
      48  def main():
      49      args = parse_args()
      50      zip_path = fetch_zip(
      51          args.tag,
      52          args.externals_dir / 'zips',
      53          org=args.organization,
      54          binary=args.binary,
      55          verbose=args.verbose,
      56      )
      57      final_name = args.externals_dir / args.tag
      58      extracted = extract_zip(args.externals_dir, zip_path)
      59      for wait in [1, 2, 3, 5, 8, 0]:
      60          try:
      61              extracted.replace(final_name)
      62              break
      63          except PermissionError as ex:
      64              retry = f" Retrying in {wait}s..." if wait else ""
      65              print(f"Encountered permission error '{ex}'.{retry}", file=sys.stderr)
      66              time.sleep(wait)
      67      else:
      68          print(
      69              f"ERROR: Failed to extract {final_name}.",
      70              "You may need to restart your build",
      71              file=sys.stderr,
      72          )
      73          sys.exit(1)
      74  
      75  
      76  if __name__ == '__main__':
      77      main()