"""Authentication helpers."""
from __future__ import annotations
from abc import ABC, abstractmethod
from collections.abc import Callable
class Authenticator(ABC):
"""Base class for request authenticators."""
@abstractmethod
def auth_headers(self) -> dict[str, str]:
"""Return headers to attach to every request."""
...
class BearerAuth(Authenticator):
"""Bearer token authentication.
Accepts a static token string or a callable that returns the
current token (evaluated on every request).
"""
def __init__(self, token: str | Callable[[], str]) -> None:
self._token = token
def auth_headers(self) -> dict[str, str]:
token = self._token() if callable(self._token) else self._token
return {"Authorization": f"Bearer {token}"}
class ApiKeyAuth(Authenticator):
"""API key authentication via a custom header.
Accepts a static key string or a callable that returns the
current key (evaluated on every request).
"""
def __init__(self, header_name: str, api_key: str | Callable[[], str]) -> None:
self._header_name = header_name
self._api_key = api_key
def auth_headers(self) -> dict[str, str]:
key = self._api_key() if callable(self._api_key) else self._api_key
return {self._header_name: key}