-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathexceptions.py
More file actions
147 lines (115 loc) · 4.18 KB
/
Copy pathexceptions.py
File metadata and controls
147 lines (115 loc) · 4.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"""
OilPriceAPI SDK Exceptions
Custom exceptions for better error handling and debugging.
"""
from datetime import datetime
from typing import Any, Dict, List, Optional
class OilPriceAPIError(Exception):
"""Base exception for all OilPriceAPI errors."""
def __init__(
self,
message: str,
status_code: Optional[int] = None,
response: Optional[Dict[str, Any]] = None,
request_id: Optional[str] = None,
):
super().__init__(message)
self.message = message
self.status_code = status_code
self.response = response
self.request_id = request_id
def __str__(self) -> str:
if self.status_code:
return f"[{self.status_code}] {self.message}"
return self.message
class AuthenticationError(OilPriceAPIError):
"""Raised when API authentication fails."""
def __init__(self, message: str = "Invalid API key or authentication failed"):
super().__init__(message, status_code=401)
class RateLimitError(OilPriceAPIError):
"""Raised when API rate limit is exceeded."""
def __init__(
self,
message: str = "Rate limit exceeded",
reset_time: Optional[datetime] = None,
limit: Optional[int] = None,
remaining: Optional[int] = None,
):
super().__init__(message, status_code=429)
self.reset_time = reset_time
self.limit = limit
self.remaining = remaining
@property
def seconds_until_reset(self) -> Optional[float]:
"""Calculate seconds until rate limit resets."""
if self.reset_time:
delta = self.reset_time - datetime.now(self.reset_time.tzinfo)
return max(0, delta.total_seconds())
return None
def __str__(self) -> str:
msg = super().__str__()
if self.seconds_until_reset:
msg += f" (resets in {self.seconds_until_reset:.0f}s)"
return msg
class DataNotFoundError(OilPriceAPIError):
"""Raised when requested data is not found."""
def __init__(
self,
message: str = "Data not found",
commodity: Optional[str] = None,
valid_commodities: Optional[List[str]] = None,
):
super().__init__(message, status_code=404)
self.commodity = commodity
self.valid_commodities = valid_commodities
def __str__(self) -> str:
msg = super().__str__()
if self.commodity:
msg = f"Commodity '{self.commodity}' not found"
if self.valid_commodities:
msg += f". Valid options: {', '.join(self.valid_commodities[:5])}"
if len(self.valid_commodities) > 5:
msg += f" (and {len(self.valid_commodities) - 5} more)"
return msg
class ValidationError(OilPriceAPIError):
"""Raised when request validation fails."""
def __init__(
self,
message: str = "Validation error",
field: Optional[str] = None,
value: Optional[Any] = None,
):
super().__init__(message, status_code=422)
self.field = field
self.value = value
def __str__(self) -> str:
msg = super().__str__()
if self.field:
msg = f"Validation error for '{self.field}'"
if self.value is not None:
msg += f": invalid value '{self.value}'"
return msg
class ServerError(OilPriceAPIError):
"""Raised when server returns 5xx error."""
def __init__(
self,
message: str = "Server error",
status_code: int = 500,
retry_after: Optional[int] = None,
):
super().__init__(message, status_code=status_code)
self.retry_after = retry_after
class TimeoutError(OilPriceAPIError):
"""Raised when request times out."""
def __init__(self, message: str = "Request timed out", timeout: Optional[float] = None):
super().__init__(message)
self.timeout = timeout
def __str__(self) -> str:
msg = super().__str__()
if self.timeout:
msg += f" (timeout: {self.timeout}s)"
return msg
class ConfigurationError(OilPriceAPIError):
"""Raised when client configuration is invalid."""
def __init__(self, message: str):
super().__init__(message)