From 487d7a23dcb00329b045474b97a8c1e8dd58ad4d Mon Sep 17 00:00:00 2001 From: ardevd Date: Wed, 30 Apr 2025 13:39:43 +0200 Subject: [PATCH] refactor: added consistent exception handling by having a single exception type it's a lot easier for SDK users to handle exceptions from the DIMO SDK. Rather than hunting down exception types from the requests library, ValueError, or any other possible exceptions, the caller can simply deal with the SDK's HTTPError and parse out the response code and response error body (if present). The caller therefore doesnt even need to know about the SDK's underlying use of `requests`. --- dimo/request.py | 50 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/dimo/request.py b/dimo/request.py index bd9fcb3..1bc6ad0 100644 --- a/dimo/request.py +++ b/dimo/request.py @@ -1,5 +1,15 @@ import json -from requests import Session +from typing import Any +from requests import Session, RequestException + + +class HTTPError(Exception): + """Http error wrapper with status code and (optional) response body""" + + def __init__(self, status: int, message: str, body: Any = None): + super().__init__(f"HTTP {status}: {message}") + self.status = status + self.body = body class Request: @@ -20,18 +30,28 @@ def __call__(self, headers=None, data=None, params=None, **kwargs): ): data = json.dumps(data) - response = self.session.request( - method=self.http_method, - url=self.url, - headers=headers, - params=params, - data=data, - **kwargs, - ) - - # TODO: Better error responses - response.raise_for_status() - - if response.content: + try: + response = self.session.request( + method=self.http_method, + url=self.url, + headers=headers, + params=params, + data=data, + **kwargs, + ) + + response.raise_for_status() + except RequestException as exc: + status = getattr(exc.response, "status_code", None) + body = None + try: + body = exc.response.json() + except Exception: + body = exc.response.txt if exc.response else None + raise HTTPError(status=status or -1, message=str(exc), body=body) + + content_type = response.headers.get("Content-Type", "") + if "application/json" in content_type: return response.json() - return None + + return response.content