forked from sigmavirus24/github3.py
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexceptions.py
More file actions
185 lines (130 loc) · 4.67 KB
/
exceptions.py
File metadata and controls
185 lines (130 loc) · 4.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# -*- coding: utf-8 -*-
"""All exceptions for the github3 library."""
class GitHubError(Exception):
"""The base exception class."""
def __init__(self, resp):
super(GitHubError, self).__init__(resp)
#: Response code that triggered the error
self.response = resp
self.code = resp.status_code
self.errors = []
try:
error = resp.json()
#: Message associated with the error
self.msg = error.get('message')
#: List of errors provided by GitHub
if error.get('errors'):
self.errors = error.get('errors')
except Exception: # Amazon S3 error
self.msg = resp.content or '[No message]'
def __repr__(self):
return '<{0} [{1}]>'.format(self.__class__.__name__,
self.msg or self.code)
def __str__(self):
return '{0} {1}'.format(self.code, self.msg)
@property
def message(self):
"""The actual message returned by the API."""
return self.msg
class IncompleteResponse(GitHubError):
"""Exception for a response that doesn't have everything it should."""
def __init__(self, json, exception):
self.response = None
self.code = None
self.json = json
self.errors = []
self.exception = exception
self.msg = (
"The library was expecting more data in the response (%r)."
" Either GitHub modified it's response body, or your token"
" is not properly scoped to retrieve this information."
) % (exception,)
class ResponseError(GitHubError):
"""The base exception for errors stemming from GitHub responses."""
pass
class TransportError(GitHubError):
"""Catch-all exception for errors coming from Requests."""
msg_format = 'An error occurred while making a request to GitHub: {0}'
def __init__(self, exception):
Exception.__init__(self, exception)
self.exception = exception
self.msg = self.msg_format.format(str(exception))
def __str__(self):
return '{0}: {1}'.format(type(self.exception), self.msg)
class ConnectionError(TransportError):
"""Exception for errors in connecting to or reading data from GitHub."""
msg_format = 'A connection-level exception occurred: {0}'
class UnprocessableResponseBody(ResponseError):
"""Exception class for response objects that cannot be handled."""
def __init__(self, message, body):
Exception.__init__(self, message)
self.body = body
self.msg = message
def __repr__(self):
return '<{0} [{1}]>'.format('UnprocessableResponseBody', self.body)
def __str__(self):
return self.message
class BadRequest(ResponseError):
"""Exception class for 400 responses."""
pass
class AuthenticationFailed(ResponseError):
"""Exception class for 401 responses.
Possible reasons:
- Need one time password (for two-factor authentication)
- You are not authorized to access the resource
"""
pass
class ForbiddenError(ResponseError):
"""Exception class for 403 responses.
Possible reasons:
- Too many requests (you've exceeded the ratelimit)
- Too many login failures
"""
pass
class NotFoundError(ResponseError):
"""Exception class for 404 responses."""
pass
class MethodNotAllowed(ResponseError):
"""Exception class for 405 responses."""
pass
class NotAcceptable(ResponseError):
"""Exception class for 406 responses."""
pass
class Conflict(ResponseError):
"""Exception class for 409 responses.
Possible reasons:
- Head branch was modified (SHA sums do not match)
"""
pass
class UnprocessableEntity(ResponseError):
"""Exception class for 422 responses."""
pass
class ClientError(ResponseError):
"""Catch-all for 400 responses that aren't specific errors."""
pass
class ServerError(ResponseError):
"""Exception class for 5xx responses."""
pass
class UnavailableForLegalReasons(ResponseError):
"""Exception class for 451 responses."""
pass
error_classes = {
400: BadRequest,
401: AuthenticationFailed,
403: ForbiddenError,
404: NotFoundError,
405: MethodNotAllowed,
406: NotAcceptable,
409: Conflict,
422: UnprocessableEntity,
451: UnavailableForLegalReasons,
}
def error_for(response):
"""Return the appropriate initialized exception class for a response."""
klass = error_classes.get(response.status_code)
if klass is None:
if 400 <= response.status_code < 500:
klass = ClientError
if 500 <= response.status_code < 600:
klass = ServerError
return klass(response)