Source code for persidict.exceptions
"""Custom exception types for the persidict error-handling taxonomy.
Defines three exception classes:
- ``MutationPolicyError`` — mutation forbidden by dict policy.
- ``ConcurrencyConflictError`` — retries exhausted due to concurrent
modification.
- ``BackendError`` — backend infrastructure failure (not missing-key).
"""
from __future__ import annotations
from typing import Any
[docs]
class MutationPolicyError(TypeError):
"""The dict's mutation policy forbids the attempted mutation.
Messages name the policy (e.g. ``"append-only"``, ``"write-once"``),
not the operation.
Args:
policy: Name of the policy that rejected the mutation.
Attributes:
policy: Name of the policy that rejected the mutation.
"""
def __init__(self, policy: str) -> None:
super().__init__(policy)
self.policy = policy
[docs]
class ConcurrencyConflictError(RuntimeError):
"""An operation failed after exhausting retries due to concurrent modification.
Carries structured context for programmatic access.
Args:
key: The key on which the conflict occurred.
attempts: Total number of attempts made before giving up.
Attributes:
key: The key on which the conflict occurred.
attempts: Total number of attempts made before giving up.
"""
def __init__(self, key: Any, attempts: int) -> None:
super().__init__(
f"operation failed after {attempts} attempt(s) for key {key!r}")
self.key = key
self.attempts = attempts
[docs]
class BackendError(RuntimeError):
"""A backend/infrastructure condition prevents completion.
Not a missing-key condition — those are ``KeyError``. Must be raised
with exception chaining (``raise BackendError(...) from exc``).
Args:
message: Human-readable description of the failure.
backend: Name of the backend (e.g. ``"filesystem"``, ``"s3"``).
operation: Name of the operation that failed (e.g. ``"init"``,
``"put_object"``).
key: The key involved, or ``None`` if not applicable.
Attributes:
backend: Name of the backend.
operation: Name of the failed operation.
key: The key involved, or ``None``.
"""
def __init__(
self,
message: str,
*,
backend: str,
operation: str,
key: Any = None,
) -> None:
super().__init__(message)
self.backend = backend
self.operation = operation
self.key = key