Coverage for src / dataknobs_common / exceptions.py: 87%
23 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-08 17:37 -0700
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-08 17:37 -0700
1"""Common exception hierarchy for all dataknobs packages.
3This module provides a unified exception framework that all dataknobs packages
4can extend. It supports both simple exceptions and context-rich exceptions with
5detailed error information.
7The exception hierarchy supports:
8- Simple error messages for straightforward cases
9- Context dictionaries for rich error information
10- Details dictionaries (FSM-style) for structured error data
11- Package-specific extensions
13Example:
14 ```python
15 from dataknobs_common.exceptions import ValidationError, NotFoundError
17 # Simple exception
18 raise ValidationError("Invalid email format")
20 # Context-rich exception
21 raise NotFoundError(
22 "User not found",
23 context={"user_id": "123", "attempted_at": "2024-11-08"}
24 )
26 # Catch any dataknobs error
27 try:
28 operation()
29 except DataknobsError as e:
30 logger.error(f"Error: {e}")
31 if e.context:
32 logger.error(f"Context: {e.context}")
33 ```
35Package-Specific Extensions:
36 ```python
37 from dataknobs_common.exceptions import DataknobsError
39 class MyPackageError(DataknobsError):
40 '''Base exception for mypackage.'''
41 pass
43 class SpecificError(MyPackageError):
44 '''Specific error with custom context.'''
45 def __init__(self, item_id: str, message: str):
46 super().__init__(
47 f"Item '{item_id}': {message}",
48 context={"item_id": item_id}
49 )
50 ```
51"""
53from typing import Any, Dict
56class DataknobsError(Exception):
57 """Base exception for all dataknobs packages.
59 This is the root exception that all dataknobs packages should extend.
60 It supports optional context data for rich error information, making
61 debugging and error handling more effective.
63 Attributes:
64 context: Dictionary containing contextual information about the error
65 details: Alias for context (FSM-style compatibility)
67 Args:
68 message: Human-readable error message
69 context: Optional dictionary with error context (field names, IDs, etc.)
70 details: Alternative to context (both are supported for compatibility)
72 Example:
73 ```python
74 error = DataknobsError(
75 "Operation failed",
76 context={"operation": "save", "item_id": "123"}
77 )
78 str(error)
79 # 'Operation failed'
80 error.context
81 # {'operation': 'save', 'item_id': '123'}
82 ```
83 """
85 def __init__(
86 self,
87 message: str,
88 context: Dict[str, Any] | None = None,
89 details: Dict[str, Any] | None = None,
90 ):
91 """Initialize the exception with optional context.
93 Args:
94 message: Error message
95 context: Optional context dictionary
96 details: Optional details dictionary (merged with context)
97 """
98 super().__init__(message)
99 # Support both context and details parameters
100 # Details takes precedence if both are provided
101 self.context = details or context or {}
102 # Alias for FSM-style compatibility
103 self.details = self.context
106class ValidationError(DataknobsError):
107 """Raised when validation fails.
109 Use this exception when data or configuration fails validation checks.
110 Common scenarios include:
111 - Invalid input data
112 - Schema validation failures
113 - Constraint violations
114 - Type mismatches
116 Example:
117 ```python
118 raise ValidationError(
119 "Email format invalid",
120 context={"field": "email", "value": "not-an-email"}
121 )
122 ```
123 """
125 pass
128class ConfigurationError(DataknobsError):
129 """Raised when configuration is invalid or missing.
131 Use this exception for configuration-related errors including:
132 - Missing required configuration
133 - Invalid configuration values
134 - Configuration file not found
135 - Circular references in configuration
137 Example:
138 ```python
139 raise ConfigurationError(
140 "Database configuration missing",
141 context={"config_key": "database.primary", "available_keys": ["cache", "auth"]}
142 )
143 ```
144 """
146 pass
149class ResourceError(DataknobsError):
150 """Raised when resource operations fail.
152 Use this exception for resource management failures including:
153 - Resource acquisition failures
154 - Connection errors
155 - Resource pool exhaustion
156 - Timeout errors
158 Example:
159 ```python
160 raise ResourceError(
161 "Failed to acquire database connection",
162 context={"pool_size": 10, "active_connections": 10, "timeout": 30}
163 )
164 ```
165 """
167 pass
170class NotFoundError(DataknobsError):
171 """Raised when a requested item is not found.
173 Use this exception when looking up items by ID, name, or key and they
174 don't exist. Common scenarios include:
175 - Record not found in database
176 - Configuration key not found
177 - File not found
178 - Resource not registered
180 Example:
181 ```python
182 raise NotFoundError(
183 "Record not found",
184 context={"record_id": "user-123", "table": "users"}
185 )
186 ```
187 """
189 pass
192class OperationError(DataknobsError):
193 """Raised when an operation fails.
195 Use this exception for general operation failures that don't fit
196 other categories. Common scenarios include:
197 - Database operation failures
198 - File I/O errors
199 - Network operation failures
200 - State transition errors
202 Example:
203 ```python
204 raise OperationError(
205 "Failed to save record",
206 context={"operation": "update", "backend": "postgres", "error": "connection lost"}
207 )
208 ```
209 """
211 pass
214class ConcurrencyError(DataknobsError):
215 """Raised when concurrent operation conflicts occur.
217 Use this exception for concurrency-related failures including:
218 - Lock acquisition failures
219 - Transaction conflicts
220 - Race conditions
221 - Optimistic locking failures
223 Example:
224 ```python
225 raise ConcurrencyError(
226 "Record modified by another process",
227 context={"record_id": "123", "expected_version": 5, "actual_version": 6}
228 )
229 ```
230 """
232 pass
235class SerializationError(DataknobsError):
236 """Raised when serialization or deserialization fails.
238 Use this exception for data format conversion errors including:
239 - JSON encoding/decoding failures
240 - Invalid data format
241 - Schema mismatch
242 - Type conversion errors
244 Example:
245 ```python
246 raise SerializationError(
247 "Cannot deserialize data",
248 context={"format": "json", "field": "created_at", "value": "invalid-date"}
249 )
250 ```
251 """
253 pass
256class TimeoutError(DataknobsError):
257 """Raised when an operation times out.
259 Use this exception when operations exceed their time limit including:
260 - Connection timeouts
261 - Query timeouts
262 - Resource acquisition timeouts
263 - Operation execution timeouts
265 Example:
266 ```python
267 raise TimeoutError(
268 "Database query timed out",
269 context={"query": "SELECT * FROM large_table", "timeout_seconds": 30}
270 )
271 ```
272 """
274 pass
277__all__ = [
278 "DataknobsError",
279 "ValidationError",
280 "ConfigurationError",
281 "ResourceError",
282 "NotFoundError",
283 "OperationError",
284 "ConcurrencyError",
285 "SerializationError",
286 "TimeoutError",
287]