/ test / download_utils.py
download_utils.py
 1  #!/usr/bin/env python3
 2  #
 3  # Copyright (c) The Bitcoin Core developers
 4  # Distributed under the MIT software license, see the accompanying
 5  # file COPYING or https://opensource.org/license/mit/.
 6  
 7  import sys
 8  import time
 9  import urllib.request
10  
11  
12  def download_from_url(url, archive):
13      print(f"Fetching: {url}")
14      last_print_time = time.time()
15  
16      def progress_hook(progress_bytes, total_size):
17          nonlocal last_print_time
18          now = time.time()
19          percent = min(100, (progress_bytes * 100) / total_size)
20          bar_length = 40
21          filled_length = int(bar_length * percent / 100)
22          bar = '#' * filled_length + '-' * (bar_length - filled_length)
23          if now - last_print_time >= 1 or percent >= 100:
24              print(f'\rDownloading: [{bar}] {percent:.1f}%', flush=True, end="")
25              last_print_time = now
26  
27      with urllib.request.urlopen(url) as response:
28          if response.status != 200:
29              raise RuntimeError(f"HTTP request failed with status code: {response.status}")
30  
31          sock_info = response.fp.raw._sock.getpeername()
32          print(f"Connected to {sock_info[0]}")
33  
34          total_size = int(response.getheader("Content-Length"))
35          progress_bytes = 0
36  
37          with open(archive, 'wb') as file:
38              while True:
39                  chunk = response.read(8192)
40                  if not chunk:
41                      break
42                  file.write(chunk)
43                  progress_bytes += len(chunk)
44                  progress_hook(progress_bytes, total_size)
45  
46          if progress_bytes < total_size:
47              raise RuntimeError(f"Download incomplete: expected {total_size} bytes, got {progress_bytes} bytes")
48  
49      print('\n', flush=True, end="") # Flush to avoid error output on the same line.
50  
51  
52  def download_script_assets(script_assets_dir):
53      script_assets_dir.mkdir(parents=True, exist_ok=True)
54      script_assets = script_assets_dir / "script_assets_test.json"
55      url = "https://github.com/bitcoin-core/qa-assets/raw/main/unit_test_data/script_assets_test.json"
56      try:
57          download_from_url(url, script_assets)
58      except Exception as e:
59          print(f"\nDownload failed: {e}", file=sys.stderr)
60          print("Retrying download after failure ...", file=sys.stderr)
61          time.sleep(12)
62          try:
63              download_from_url(url, script_assets)
64          except Exception as e2:
65              sys.exit(e2)