|
6 | 6 | import time |
7 | 7 | import yaml |
8 | 8 | import shlex |
9 | | -import tempfile |
| 9 | +import requests |
10 | 10 | import subprocess |
11 | | -import urllib.request |
| 11 | + |
12 | 12 | from pathlib import Path |
13 | 13 | from functools import lru_cache |
14 | 14 | from dataclasses import dataclass |
15 | 15 | from typing import Any, Optional, Tuple, Dict |
16 | 16 | from concurrent.futures import ThreadPoolExecutor, as_completed |
17 | 17 |
|
| 18 | +from ..utils import download_url |
| 19 | + |
18 | 20 | from .hailo_logger import get_logger |
19 | 21 | hailo_logger = get_logger(__name__) |
20 | 22 |
|
21 | | - |
22 | 23 | # Base Defaults |
23 | 24 | HAILO8_ARCH = "hailo8" |
24 | 25 | HAILO8L_ARCH = "hailo8l" |
@@ -303,35 +304,13 @@ def is_none_value(value: Any) -> bool: |
303 | 304 | def get_remote_file_size(url: str, timeout: int = 30) -> Optional[int]: |
304 | 305 | """Get Content-Length of a remote file via HEAD request.""" |
305 | 306 | try: |
306 | | - req = urllib.request.Request(url, method='HEAD', headers={'User-Agent': DEFAULT_USER_AGENT}) |
307 | | - with urllib.request.urlopen(req, timeout=timeout) as resp: |
308 | | - length = resp.headers.get('Content-Length') |
309 | | - return int(length) if length else None |
| 307 | + r = requests.head(url, headers={'User-Agent': DEFAULT_USER_AGENT}, timeout=timeout, allow_redirects=True) |
| 308 | + length = r.headers.get('Content-Length') |
| 309 | + return int(length) if length else None |
310 | 310 | except Exception: |
311 | 311 | return None |
312 | 312 |
|
313 | 313 |
|
314 | | -class ProgressTracker: |
315 | | - """Simple terminal progress bar for downloads.""" |
316 | | - def __init__(self, show_progress: bool = True): |
317 | | - self.show_progress = show_progress |
318 | | - self._last_percent = -1 |
319 | | - |
320 | | - def update(self, downloaded: int, total_size: int): |
321 | | - if not self.show_progress or total_size <= 0: |
322 | | - return |
323 | | - percent = min(100, (downloaded * 100) // total_size) |
324 | | - if percent == self._last_percent: |
325 | | - return |
326 | | - self._last_percent = percent |
327 | | - bar = '=' * (percent // 2.5) + '-' * (40 - int(percent // 2.5)) |
328 | | - print(f"\r[{bar}] {percent}% ({downloaded/1e6:.2f}/{total_size/1e6:.2f} MB)", end='', flush=True) |
329 | | - |
330 | | - def finish(self): |
331 | | - if self.show_progress: |
332 | | - print() |
333 | | - |
334 | | - |
335 | 314 | class ResourceDownloader: |
336 | 315 | """Manages downloading of models and resources from various sources.""" |
337 | 316 | RESOURCE_MAP = { |
@@ -373,37 +352,18 @@ def _download_file_with_retry(self, task: DownloadTask) -> DownloadResult: |
373 | 352 | task.dest_path.parent.mkdir(parents=True, exist_ok=True) |
374 | 353 | last_err = None |
375 | 354 | for attempt in range(self.download_config.max_retries): |
376 | | - temp_path = None |
377 | 355 | try: |
378 | | - fd, temp_path_str = tempfile.mkstemp(dir=task.dest_path.parent, prefix=f".{task.name}.", suffix=".tmp") |
379 | | - os.close(fd) |
380 | | - temp_path = Path(temp_path_str) |
381 | | - |
382 | | - req = urllib.request.Request(task.url, headers={'User-Agent': DEFAULT_USER_AGENT}) |
383 | | - progress = ProgressTracker(self.download_config.show_progress) |
384 | 356 | hailo_logger.info(f"Downloading: {task.url}") |
| 357 | + download_url(task.url, str(task.dest_path)) |
385 | 358 |
|
386 | | - with urllib.request.urlopen(req, timeout=self.download_config.timeout) as resp: |
387 | | - total = int(resp.headers.get('Content-Length', 0)) |
388 | | - with open(temp_path, 'wb') as f: |
389 | | - downloaded = 0 |
390 | | - while chunk := resp.read(8192): |
391 | | - f.write(chunk) |
392 | | - downloaded += len(chunk) |
393 | | - progress.update(downloaded, total) |
394 | | - progress.finish() |
395 | | - |
396 | | - if remote_size and temp_path.stat().st_size != remote_size: |
397 | | - raise ValueError(f"Size mismatch: got {temp_path.stat().st_size}, expected {remote_size}") |
| 359 | + if remote_size and task.dest_path.stat().st_size != remote_size: |
| 360 | + raise ValueError(f"Size mismatch: got {task.dest_path.stat().st_size}, expected {remote_size}") |
398 | 361 |
|
399 | | - if task.dest_path.exists(): |
400 | | - task.dest_path.unlink() |
401 | | - temp_path.rename(task.dest_path) |
402 | 362 | return DownloadResult(task, True, "Success", False, task.dest_path.stat().st_size) |
403 | 363 | except Exception as e: |
404 | 364 | last_err = e |
405 | | - if temp_path and temp_path.exists(): |
406 | | - temp_path.unlink() |
| 365 | + if task.dest_path.exists(): |
| 366 | + task.dest_path.unlink() |
407 | 367 | if attempt < self.download_config.max_retries - 1: |
408 | 368 | time.sleep(self.download_config.retry_delay * (2 ** attempt)) |
409 | 369 |
|
|
0 commit comments