diff --git a/github/GithubException.py b/github/GithubException.py index 4708047f..f406a413 100644 --- a/github/GithubException.py +++ b/github/GithubException.py @@ -38,11 +38,12 @@ class GithubException(Exception): Some other types of exceptions might be raised by underlying libraries, for example for network-related issues. """ - def __init__(self, status, data): + def __init__(self, status, data, headers): super().__init__() self.__status = status self.__data = data - self.args = [status, data] + self.__headers = headers + self.args = [status, data, headers] @property def status(self): @@ -58,6 +59,13 @@ class GithubException(Exception): """ return self.__data + @property + def headers(self): + """ + The headers returned by the Github API + """ + return self.__headers + def __str__(self): return "{status} {data}".format(status=self.status, data=json.dumps(self.data)) diff --git a/github/GithubException.pyi b/github/GithubException.pyi index 4ba59450..8c767b9e 100644 --- a/github/GithubException.pyi +++ b/github/GithubException.pyi @@ -1,13 +1,16 @@ from typing import Any, Dict, List, Optional, Tuple, Type, Union class GithubException(Exception): - def __init__(self, status: Union[int, str], data: Any,) -> None: ... + def __init__(self, status: Union[int, str], data: Any, headers: Optional[Dict[str, str]]) -> None: ... def __str__(self) -> str: ... @property def data(self) -> Dict[str, Union[str, List[str], List[Dict[str, str]]]]: ... @property def status(self) -> int: ... + @property + def headers(self) -> Union[None, Dict[str, str]]: ... + class BadAttributeException(GithubException): def __init__( self, diff --git a/github/GithubObject.py b/github/GithubObject.py index 3916153e..21705e66 100644 --- a/github/GithubObject.py +++ b/github/GithubObject.py @@ -300,7 +300,7 @@ class CompletableGithubObject(GithubObject): def __complete(self): if self._url.value is None: raise GithubException.IncompletableObject( - 400, "Returned object contains no URL" + 400, "Returned object contains no URL", None ) headers, data = self._requester.requestJsonAndCheck("GET", self._url.value) self._storeAndUseAttributes(headers, data) diff --git a/github/Requester.py b/github/Requester.py index 67d3d123..a508c386 100644 --- a/github/Requester.py +++ b/github/Requester.py @@ -435,7 +435,7 @@ class Requester: cls = GithubException.UnknownObjectException else: cls = GithubException.GithubException - return cls(status, output) + return cls(status, output, headers) def __structuredFromJson(self, data): if len(data) == 0: diff --git a/tests/Exceptions.py b/tests/Exceptions.py index 6b9edc5e..34205a84 100644 --- a/tests/Exceptions.py +++ b/tests/Exceptions.py @@ -90,7 +90,7 @@ class Exceptions(Framework.TestCase): self.assertEqual(str(raisedexp.exception), '401 {"message": "Bad credentials"}') def testExceptionPickling(self): - pickle.loads(pickle.dumps(github.GithubException("foo", "bar"))) + pickle.loads(pickle.dumps(github.GithubException("foo", "bar", None))) class SpecificExceptions(Framework.TestCase): @@ -134,7 +134,9 @@ class SpecificExceptions(Framework.TestCase): res = self.g.search_code("jacquev6") res.get_page(0) - self.assertRaises(github.RateLimitExceededException, exceed) + with self.assertRaises(github.RateLimitExceededException) as raised: + exceed() + self.assertEqual(raised.exception.headers.get("retry-after"), "60") def testIncompletableObject(self): github.UserKey.UserKey.setCheckAfterInitFlag(False)