"""
Fetch content from the internet.
"""
import asyncio
from collections.abc import Callable, Awaitable
from dataclasses import dataclass
from json import loads
from logging import getLogger
from pathlib import Path
from time import time
from typing import Any, TypeVar
from aiohttp import ClientSession, ClientResponse, ClientError
from multidict import CIMultiDict
from betty.cache import Cache
from betty.cache.file import BinaryFileCache
from betty.error import UserFacingError
from betty.hashid import hashid
from betty.locale.localizable import plain
_CacheItemValueT = TypeVar("_CacheItemValueT")
[docs]
class FetchError(UserFacingError, RuntimeError):
"""
An error that occurred when fetching a URL.
"""
pass # pragma: no cover
[docs]
@dataclass
class FetchResponse:
"""
An HTTP response.
"""
headers: CIMultiDict[str]
body: bytes
encoding: str
@property
def text(self) -> str:
"""
The body as plain text.
This may raise an error if the response body cannot be represented as plain text.
"""
return self.body.decode(self.encoding)
@property
def json(self) -> Any:
"""
The body as JSON.
This may raise an error if the response body cannot be represented as JSON or plain text.
"""
return loads(self.text)
[docs]
class Fetcher:
"""
Fetch content from the internet.
"""