Source code for imdbio.exceptions
"""
imdbio exception hierarchy
============================
ImdbioError
├── HTTPError — any non-200 HTTP response (status_code, url, response_text)
│ └── WAFError — HTTP 202 from AWS WAF enforcement
├── GraphQLError — non-200 or {"errors": …} from the GraphQL endpoint
└── ParseError — __NEXT_DATA__ script not found in HTML response
"""
from typing import Optional, List, Dict, Any
[docs]
class ImdbioError(Exception):
"""Base class for all imdbio exceptions."""
[docs]
class HTTPError(ImdbioError):
"""Raised when the IMDb HTML endpoint returns a non-200 status code.
Attributes
----------
status_code : int
The HTTP status code returned by the server.
url : str
The full URL that was requested.
response_text : str
The first 500 characters of the response body (may be empty).
"""
def __init__(
self, message: str, status_code: int, url: str, response_text: str = ""
):
super().__init__(message)
self.status_code: int = status_code
self.url: str = url
self.response_text: str = response_text
def __repr__(self) -> str:
return (
f"{self.__class__.__name__}("
f"status_code={self.status_code!r}, "
f"url={self.url!r}, "
f"message={str(self)!r})"
)
[docs]
class WAFError(HTTPError):
"""Raised when AWS WAF returns HTTP 202, blocking the request.
This is a subclass of :class:`HTTPError` so callers that catch
``HTTPError`` will also catch ``WAFError``. Callers that want to handle
WAF enforcement specifically (e.g. to rotate proxies or back off) can
catch ``WAFError`` directly.
Attributes
----------
status_code : int
Always ``202`` for WAF-blocked responses.
url : str
The full URL that was blocked.
response_text : str
The first 500 characters of the WAF challenge response body.
"""
[docs]
class GraphQLError(ImdbioError):
"""Raised when the IMDb GraphQL API returns a non-200 status or
an ``{"errors": […]}`` payload.
Attributes
----------
url : str
The GraphQL endpoint URL.
query_term : str
The search term / entity ID used in the query.
status_code : Optional[int]
HTTP status code when the failure is transport-level; ``None`` when
the response was 200 but contained GraphQL ``errors``.
errors : List[Dict[str, Any]]
Parsed GraphQL error objects from the response body (empty list for
transport-level failures).
response_text : str
First 500 characters of the raw response body.
"""
def __init__(
self,
message: str,
url: str,
query_term: str,
status_code: Optional[int] = None,
errors: Optional[List[Dict[str, Any]]] = None,
response_text: str = "",
):
super().__init__(message)
self.url: str = url
self.query_term: str = query_term
self.status_code: Optional[int] = status_code
self.errors: List[Dict[str, Any]] = errors or []
self.response_text: str = response_text
def __repr__(self) -> str:
return (
f"{self.__class__.__name__}("
f"status_code={self.status_code!r}, "
f"url={self.url!r}, "
f"query_term={self.query_term!r}, "
f"message={str(self)!r})"
)
[docs]
class ParseError(ImdbioError):
"""Raised when the expected ``__NEXT_DATA__`` JSON script tag is absent
from the IMDb HTML response.
Attributes
----------
url : str
The URL whose response could not be parsed.
"""
def __init__(self, message: str, url: str = ""):
super().__init__(message)
self.url: str = url
def __repr__(self) -> str:
return f"{self.__class__.__name__}(url={self.url!r}, message={str(self)!r})"