diff --git a/docs/usage/error-handling.md b/docs/usage/error-handling.md index ed8d54e0d..42852be41 100644 --- a/docs/usage/error-handling.md +++ b/docs/usage/error-handling.md @@ -7,11 +7,11 @@ GitHubException ├── AuthCredentialError ├── AuthExpiredError ├── RequestError -├── RequestTimeout -├── RequestFailed -│ └── RateLimitExceeded -│ ├── PrimaryRateLimitExceeded -│ └── SecondaryRateLimitExceeded +│ ├── RequestTimeout +│ └── RequestFailed +│ └── RateLimitExceeded +│ ├── PrimaryRateLimitExceeded +│ └── SecondaryRateLimitExceeded ├── GraphQLError │ ├── GraphQLFailed │ └── GraphQLPaginationError diff --git a/githubkit/core.py b/githubkit/core.py index 134a46ff8..4ed6c3f00 100644 --- a/githubkit/core.py +++ b/githubkit/core.py @@ -283,9 +283,9 @@ def _request( cookies=cookies, ) except httpx.TimeoutException as e: - raise RequestTimeout(e.request) from e + raise RequestTimeout(e) from e except Exception as e: - raise RequestError(repr(e)) from e + raise RequestError(e) from e # async request async def _arequest( @@ -315,9 +315,9 @@ async def _arequest( cookies=cookies, ) except httpx.TimeoutException as e: - raise RequestTimeout(e.request) from e + raise RequestTimeout(e) from e except Exception as e: - raise RequestError(repr(e)) from e + raise RequestError(e) from e # check and parse response @overload diff --git a/githubkit/exception.py b/githubkit/exception.py index cf36659e5..c25dace3b 100644 --- a/githubkit/exception.py +++ b/githubkit/exception.py @@ -1,5 +1,5 @@ from datetime import timedelta -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Generic, TypeVar import httpx @@ -8,6 +8,9 @@ from .graphql import GraphQLResponse +E = TypeVar("E", bound=Exception) + + class GitHubException(Exception): ... @@ -19,15 +22,22 @@ class AuthExpiredError(GitHubException): """Auth Expired Error""" -class RequestError(GitHubException): +class RequestError(GitHubException, Generic[E]): """Simple API request failed with unknown error""" + def __init__(self, exc: E) -> None: + self.exc = exc + + def __repr__(self) -> str: + return f"{self.__class__.__name__}(origin_exc={self.exc!r})" + -class RequestTimeout(GitHubException): +class RequestTimeout(RequestError[httpx.TimeoutException]): """Simple API request timeout""" - def __init__(self, request: httpx.Request): - self.request = request + @property + def request(self) -> httpx.Request: + return self.exc.request def __repr__(self) -> str: return ( @@ -36,10 +46,17 @@ def __repr__(self) -> str: ) -class RequestFailed(GitHubException): +class RequestFailed(RequestError[httpx.HTTPStatusError]): """Simple API request failed with error status code""" def __init__(self, response: "Response"): + super().__init__( + httpx.HTTPStatusError( + "Request failed", + request=response.raw_request, + response=response.raw_response, + ) + ) self.request = response.raw_request self.response = response