python/hightrusted_capture/errors.py
Stefan Schmidt-Egermann fa81aba944
feat: initial python content (v0.1.0)
- Installierbares Package mit pyproject.toml
- Client-Klasse mit Sync, Async (mit Polling), Webhook, Verify, Download
- Typisierte Exception-Hierarchie
- Webhook-Signatur-Verifikation (HMAC-SHA-256)
- Pytest-Suite + Quickstart und Webhook-Receiver-Beispiel
2026-04-25 12:26:03 +02:00

87 lines
2.7 KiB
Python

"""Typisierte Exception-Hierarchie für SDK-Konsumenten."""
from __future__ import annotations
from typing import Any
class HightrustedError(Exception):
"""Basisklasse für alle hightrusted CAPTURE Fehler."""
def __init__(
self,
message: str,
*,
code: str | None = None,
request_id: str | None = None,
status_code: int | None = None,
raw: dict[str, Any] | None = None,
) -> None:
super().__init__(message)
self.message = message
self.code = code
self.request_id = request_id
self.status_code = status_code
self.raw = raw
def __str__(self) -> str:
parts = [self.message]
if self.code:
parts.append(f"code={self.code}")
if self.request_id:
parts.append(f"request_id={self.request_id}")
return " | ".join(parts)
class InvalidApiKeyError(HightrustedError):
"""HTTP 401 — invalid_api_key"""
class QuotaExceededError(HightrustedError):
"""HTTP 402 — quota_exceeded"""
class CaptureNotFoundError(HightrustedError):
"""HTTP 404 — capture_not_found"""
class CaptureNotReadyError(HightrustedError):
"""HTTP 409 — capture_not_ready"""
class UnreachableUrlError(HightrustedError):
"""HTTP 422 — unreachable_url"""
class RateLimitedError(HightrustedError):
"""HTTP 429 — rate_limited.
Attribut `retry_after_seconds` enthält den Wert aus dem `Retry-After`-Header.
"""
def __init__(self, *args: Any, retry_after_seconds: int | None = None, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.retry_after_seconds = retry_after_seconds
class TsaUnavailableError(HightrustedError):
"""HTTP 503 — tsa_unavailable"""
# ─────────────────────────────────────────────────────────────────────
# Code → Exception Mapping
# ─────────────────────────────────────────────────────────────────────
_ERROR_CODE_MAP: dict[str, type[HightrustedError]] = {
"invalid_api_key": InvalidApiKeyError,
"quota_exceeded": QuotaExceededError,
"capture_not_found": CaptureNotFoundError,
"capture_not_ready": CaptureNotReadyError,
"unreachable_url": UnreachableUrlError,
"rate_limited": RateLimitedError,
"tsa_unavailable": TsaUnavailableError,
}
def error_for_code(code: str) -> type[HightrustedError]:
"""Mappt einen Error-Code auf die passende Exception-Klasse."""
return _ERROR_CODE_MAP.get(code, HightrustedError)