Coverage for src/dataknobs_data/exceptions.py: 48%
66 statements
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-13 11:23 -0700
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-13 11:23 -0700
1"""Custom exceptions for the dataknobs_data package.
3This module defines exception types for the data package,
4built on the common exception framework from dataknobs_common.
5"""
7from __future__ import annotations
9from typing import TYPE_CHECKING
11from dataknobs_common import (
12 ConfigurationError as BaseConfigurationError,
13 ConcurrencyError as BaseConcurrencyError,
14 DataknobsError,
15 NotFoundError,
16 OperationError,
17 ResourceError,
18 SerializationError as BaseSerializationError,
19 ValidationError,
20)
22if TYPE_CHECKING:
23 from dataknobs_data.query import Query
25# Create DataknobsDataError as alias to DataknobsError for backward compatibility
26DataknobsDataError = DataknobsError
29class RecordNotFoundError(NotFoundError):
30 """Raised when a requested record is not found."""
32 def __init__(self, id: str):
33 self.id = id
34 super().__init__(f"Record with ID '{id}' not found", context={"id": id})
37class RecordValidationError(ValidationError):
38 """Raised when record validation fails."""
40 def __init__(self, message: str, field_name: str | None = None):
41 self.field_name = field_name
42 if field_name:
43 message = f"Field '{field_name}': {message}"
44 super().__init__(message, context={"field_name": field_name} if field_name else None)
47class FieldTypeError(ValidationError):
48 """Raised when a field type operation fails."""
50 def __init__(self, field_name: str, expected_type: str, actual_type: str):
51 self.field_name = field_name
52 self.expected_type = expected_type
53 self.actual_type = actual_type
54 super().__init__(
55 f"Field '{field_name}' type mismatch: expected {expected_type}, got {actual_type}",
56 context={
57 "field_name": field_name,
58 "expected_type": expected_type,
59 "actual_type": actual_type,
60 },
61 )
64class DatabaseError(ResourceError):
65 """General database error."""
67 pass
70class DatabaseConnectionError(ResourceError):
71 """Raised when database connection fails."""
73 def __init__(self, backend: str, message: str):
74 self.backend = backend
75 super().__init__(
76 f"Failed to connect to {backend} backend: {message}", context={"backend": backend}
77 )
80class DatabaseOperationError(OperationError):
81 """Raised when a database operation fails."""
83 def __init__(self, operation: str, message: str):
84 self.operation = operation
85 super().__init__(
86 f"Database operation '{operation}' failed: {message}", context={"operation": operation}
87 )
90class QueryError(OperationError):
91 """Raised when query execution fails."""
93 def __init__(self, message: str, query: Query | None = None):
94 self.query = query
95 context = {"query": str(query)} if query else None
96 super().__init__(f"Query error: {message}", context=context)
99class SerializationError(BaseSerializationError):
100 """Raised when serialization/deserialization fails."""
102 def __init__(self, format: str, message: str):
103 self.format = format
104 super().__init__(f"Serialization error ({format}): {message}", context={"format": format})
107class DataFormatError(ValidationError):
108 """Raised when data format is invalid or unsupported."""
110 def __init__(self, format: str, message: str):
111 self.format = format
112 super().__init__(f"Data format error ({format}): {message}", context={"format": format})
115class BackendNotFoundError(NotFoundError):
116 """Raised when a requested backend is not available."""
118 def __init__(self, backend: str, available: list | None = None):
119 self.backend = backend
120 self.available = available or []
121 message = f"Backend '{backend}' not found"
122 if self.available:
123 message += f". Available backends: {', '.join(self.available)}"
124 super().__init__(message, context={"backend": backend, "available": self.available})
127class ConfigurationError(BaseConfigurationError):
128 """Raised when configuration is invalid."""
130 def __init__(self, parameter: str, message: str):
131 self.parameter = parameter
132 super().__init__(
133 f"Configuration error for '{parameter}': {message}", context={"parameter": parameter}
134 )
137class ConcurrencyError(BaseConcurrencyError):
138 """Raised when a concurrency conflict occurs."""
140 def __init__(self, message: str):
141 super().__init__(f"Concurrency error: {message}")
144class TransactionError(OperationError):
145 """Raised when a transaction fails."""
147 def __init__(self, message: str):
148 super().__init__(f"Transaction error: {message}")
151class MigrationError(OperationError):
152 """Raised when data migration fails."""
154 def __init__(self, source: str, target: str, message: str):
155 self.source = source
156 self.target = target
157 super().__init__(
158 f"Migration from {source} to {target} failed: {message}",
159 context={"source": source, "target": target},
160 )