/ exceptions.py
exceptions.py
1 """Custom exception hierarchy for the job-search application.""" 2 3 __all__ = [ 4 "JobSearchError", 5 "ConfigurationError", 6 "APIError", 7 "ParseError", 8 "DataError", 9 "UsageError", 10 ] 11 12 13 class JobSearchError(Exception): 14 """Base exception for all application errors.""" 15 16 17 class ConfigurationError(JobSearchError): 18 """Raised when a required configuration value is missing or invalid. 19 20 Args: 21 var_name: The name of the missing or invalid environment variable. 22 """ 23 24 def __init__(self, var_name: str) -> None: 25 self.var_name = var_name 26 super().__init__(f"Missing or invalid configuration: {var_name!r}") 27 28 29 class APIError(JobSearchError): 30 """Raised when an external API call fails with a non-retriable error. 31 32 Args: 33 service: Name of the external service (e.g. 'brightdata', 'anthropic'). 34 status_code: HTTP status code returned by the service. 35 message: Human-readable error detail. 36 """ 37 38 def __init__(self, service: str, status_code: int, message: str) -> None: 39 self.service = service 40 self.status_code = status_code 41 super().__init__(f"[{service}] HTTP {status_code}: {message}") 42 43 44 class ParseError(JobSearchError): 45 """Raised when response data cannot be parsed into the expected schema. 46 47 Args: 48 source: Where the data came from (e.g. 'brightdata snapshot'). 49 detail: Description of what failed. 50 raw: The raw response that failed validation (for diagnostics). 51 """ 52 53 def __init__(self, source: str, detail: str, *, raw: str | None = None) -> None: 54 self.source = source 55 self.raw = raw 56 super().__init__(f"Failed to parse response from {source!r}: {detail}") 57 58 59 class DataError(JobSearchError): 60 """Raised when input data is invalid or incomplete and cannot be processed. 61 62 Args: 63 detail: Human-readable description of the data problem. 64 """ 65 66 def __init__(self, detail: str) -> None: 67 super().__init__(f"Input data error: {detail}") 68 69 70 class UsageError(JobSearchError): 71 """Raised when the caller supplies an invalid combination of CLI arguments. 72 73 Args: 74 detail: Human-readable description of the invalid usage. 75 """ 76 77 def __init__(self, detail: str) -> None: 78 super().__init__(f"Invalid usage: {detail}")