Source code for pyfetcher.download.service
"""Download service for :mod:`pyfetcher`.
Purpose:
Provide file-oriented download helpers that reuse the shared fetch service
and streaming models.
Design:
- Downloads are async-first using streamed chunks.
- Files are written incrementally to avoid holding entire responses in memory.
- Parent directories are created automatically.
Examples:
::
>>> service = DownloadService()
>>> hasattr(service, "adownload_to_path")
True
"""
from __future__ import annotations
from pathlib import Path
from pyfetcher.contracts.request import FetchRequest
from pyfetcher.fetch.service import FetchService
[docs]
class DownloadService:
"""Async download service built on streamed fetches.
Wraps a :class:`~pyfetcher.fetch.service.FetchService` to provide
file-oriented download capabilities. Files are streamed incrementally
to disk to minimize memory usage for large downloads.
Args:
fetch_service: Optional fetch service instance. A default is created
if not provided.
Examples:
::
>>> service = DownloadService()
>>> hasattr(service, "adownload_to_path")
True
"""
def __init__(self, *, fetch_service: FetchService | None = None) -> None:
self.fetch_service = fetch_service or FetchService()
[docs]
async def adownload_to_path(self, request: FetchRequest, destination: str | Path) -> Path:
"""Download a resource to a destination file path.
Streams the response body in chunks and writes each chunk to disk
as it arrives. Parent directories are created automatically.
Args:
request: The fetch request for the resource to download.
destination: Target file path (string or ``Path``).
Returns:
The resolved :class:`Path` where the file was written.
Raises:
Exception: Any streaming or file I/O failure.
Examples:
::
>>> service = DownloadService()
>>> hasattr(service, "adownload_to_path")
True
"""
destination_path = Path(destination)
destination_path.parent.mkdir(parents=True, exist_ok=True)
with destination_path.open("wb") as handle:
async for chunk in self.fetch_service.astream(request):
handle.write(chunk.data)
return destination_path