Source code for cached_path.schemes.scheme_client

import io
from abc import ABC, abstractmethod
from typing import ClassVar, Optional, Tuple, Type, Union

import requests


[docs]class SchemeClient(ABC): """ A client used for caching remote resources corresponding to URLs with a particular scheme. Subclasses must define the :attr:`scheme` class variable and implement :meth:`get_etag()` and :meth:`get_resource()`. .. important:: Take care when implementing subclasses to raise the right error types from :meth:`get_etag()` and :meth:`get_resource()`. """ recoverable_errors: ClassVar[Tuple[Type[BaseException], ...]] = ( requests.exceptions.ConnectionError, requests.exceptions.Timeout, ) """ Subclasses can override this to define error types that will be treated as recoverable. If ``cached_path()`` catches of one these errors while calling :meth:`get_etag()`, it will log a warning and return the latest cached version if there is one, otherwise it will propogate the error. """ scheme: ClassVar[Union[str, Tuple[str, ...]]] = tuple() """ The scheme or schemes that the client will be used for (e.g. "http"). """ def __init__(self, resource: str) -> None: self.resource = resource
[docs] @abstractmethod def get_etag(self) -> Optional[str]: """ Get the Etag or an equivalent version identifier associated with the resource. Returns ------- ``Optional[str]`` The ETag as a ``str`` or ``None`` if there is no ETag associated with the resource. Raises ------ ``FileNotFoundError`` If the resource doesn't exist. ``Recoverable error`` Any error type defined in ``SchemeClient.recoverable_errors`` will be treated as a recoverable error. This means that when of these is caught by ``cached_path()``, it will look for cached versions of the given resource and return the latest version if there are any. Otherwise the error is propogated. ``Other errors`` Any other error type can be raised. These errors will be treated non-recoverable and will be propogated immediately by ``cached_path()``. """ raise NotImplementedError
[docs] @abstractmethod def get_size(self) -> Optional[int]: """ Get the size of the resource in bytes (if known). Returns ------- ``Optional[int]`` The size (in bytes). Raises ------ ``FileNotFoundError`` If the resource doesn't exist. ``Recoverable error`` Any error type defined in ``SchemeClient.recoverable_errors`` will be treated as a recoverable error. This means that when of these is caught by ``cached_path()``, the size will be ignored. ``Other errors`` Any other error type can be raised. These errors will be treated non-recoverable and will be propogated immediately by ``cached_path()``. """ raise NotImplementedError
[docs] @abstractmethod def get_resource(self, temp_file: io.BufferedWriter) -> None: """ Download the resource to the given temporary file. Raises ------ ``FileNotFoundError`` If the resource doesn't exist. ``Other errors`` Any other error type can be raised. These errors will be treated non-recoverable and will be propagated immediately by ``cached_path()``. """ raise NotImplementedError
[docs] def get_bytes_range(self, index: int, length: int) -> bytes: """ Get a sequence of ``length`` bytes from the resource, starting at ``index`` bytes. If a scheme provides a direct way of downloading a bytes range, the scheme client should implement that. Otherwise the entire file has to be downloaded. """ del index, length raise NotImplementedError