Download HTTP/HTTPS file with cancellation support.
(
url: str, temp_path: Path, cancel_event: threading.Event
)
| 167 | |
| 168 | |
| 169 | def _download_with_progress( |
| 170 | url: str, temp_path: Path, cancel_event: threading.Event |
| 171 | ) -> DownloadResult: |
| 172 | """Download HTTP/HTTPS file with cancellation support.""" |
| 173 | try: |
| 174 | # HTTP/HTTPS download using httpx with streaming |
| 175 | with httpx.Client(follow_redirects=True, timeout=30.0) as client: |
| 176 | with client.stream( |
| 177 | "GET", url, headers={"User-Agent": "PlatformIO-Cache/1.0"} |
| 178 | ) as response: |
| 179 | response.raise_for_status() |
| 180 | |
| 181 | with open(temp_path, "wb") as f: |
| 182 | for chunk in response.iter_bytes(chunk_size=8192): |
| 183 | # Check for cancellation periodically |
| 184 | if cancel_event.is_set(): |
| 185 | cancelled_error = RuntimeError( |
| 186 | f"Download cancelled for {url}" |
| 187 | ) |
| 188 | logger.warning( |
| 189 | f"Download cancelled for {url}", |
| 190 | exc_info=cancelled_error, |
| 191 | ) |
| 192 | return DownloadResult(url, temp_path, cancelled_error) |
| 193 | f.write(chunk) |
| 194 | |
| 195 | return DownloadResult(url, temp_path) # Success |
| 196 | |
| 197 | except KeyboardInterrupt as e: |
| 198 | # Set cancel event and interrupt main thread |
| 199 | cancel_event.set() |
| 200 | _thread.interrupt_main() |
| 201 | logger.warning( |
| 202 | f"Download interrupted by KeyboardInterrupt for {url}", exc_info=e |
| 203 | ) |
| 204 | return DownloadResult(url, temp_path, e) |
| 205 | except Exception as e: |
| 206 | if not cancel_event.is_set(): |
| 207 | logger.error(f"Download failed for {url}: {e}", exc_info=e) |
| 208 | else: |
| 209 | logger.warning(f"Download failed for {url} (cancelled): {e}", exc_info=e) |
| 210 | return DownloadResult(url, temp_path, e) |
| 211 | |
| 212 | |
| 213 | def _copy_file_with_progress( |
no test coverage detected