Coverage for /pythoncovmergedfiles/medio/medio/src/aiohttp/aiohttp/web_exceptions.py: 76%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import warnings
2from http import HTTPStatus
3from typing import Any, Iterable, Optional, Set, Tuple
5from multidict import CIMultiDict
6from yarl import URL
8from . import hdrs
9from .helpers import CookieMixin
10from .typedefs import LooseHeaders, StrOrURL
12__all__ = (
13 "HTTPException",
14 "HTTPError",
15 "HTTPRedirection",
16 "HTTPSuccessful",
17 "HTTPOk",
18 "HTTPCreated",
19 "HTTPAccepted",
20 "HTTPNonAuthoritativeInformation",
21 "HTTPNoContent",
22 "HTTPResetContent",
23 "HTTPPartialContent",
24 "HTTPMove",
25 "HTTPMultipleChoices",
26 "HTTPMovedPermanently",
27 "HTTPFound",
28 "HTTPSeeOther",
29 "HTTPNotModified",
30 "HTTPUseProxy",
31 "HTTPTemporaryRedirect",
32 "HTTPPermanentRedirect",
33 "HTTPClientError",
34 "HTTPBadRequest",
35 "HTTPUnauthorized",
36 "HTTPPaymentRequired",
37 "HTTPForbidden",
38 "HTTPNotFound",
39 "HTTPMethodNotAllowed",
40 "HTTPNotAcceptable",
41 "HTTPProxyAuthenticationRequired",
42 "HTTPRequestTimeout",
43 "HTTPConflict",
44 "HTTPGone",
45 "HTTPLengthRequired",
46 "HTTPPreconditionFailed",
47 "HTTPRequestEntityTooLarge",
48 "HTTPRequestURITooLong",
49 "HTTPUnsupportedMediaType",
50 "HTTPRequestRangeNotSatisfiable",
51 "HTTPExpectationFailed",
52 "HTTPMisdirectedRequest",
53 "HTTPUnprocessableEntity",
54 "HTTPFailedDependency",
55 "HTTPUpgradeRequired",
56 "HTTPPreconditionRequired",
57 "HTTPTooManyRequests",
58 "HTTPRequestHeaderFieldsTooLarge",
59 "HTTPUnavailableForLegalReasons",
60 "HTTPServerError",
61 "HTTPInternalServerError",
62 "HTTPNotImplemented",
63 "HTTPBadGateway",
64 "HTTPServiceUnavailable",
65 "HTTPGatewayTimeout",
66 "HTTPVersionNotSupported",
67 "HTTPVariantAlsoNegotiates",
68 "HTTPInsufficientStorage",
69 "HTTPNotExtended",
70 "HTTPNetworkAuthenticationRequired",
71)
74class NotAppKeyWarning(UserWarning):
75 """Warning when not using AppKey in Application."""
78############################################################
79# HTTP Exceptions
80############################################################
83class HTTPException(CookieMixin, Exception):
84 # You should set in subclasses:
85 # status = 200
87 status_code = -1
88 empty_body = False
89 default_reason = "" # Initialized at the end of the module
91 def __init__(
92 self,
93 *,
94 headers: Optional[LooseHeaders] = None,
95 reason: Optional[str] = None,
96 text: Optional[str] = None,
97 content_type: Optional[str] = None,
98 ) -> None:
99 if reason is None:
100 reason = self.default_reason
101 elif "\n" in reason:
102 raise ValueError("Reason cannot contain \\n")
104 if text is None:
105 if not self.empty_body:
106 text = f"{self.status_code}: {reason}"
107 else:
108 if self.empty_body:
109 warnings.warn(
110 "text argument is deprecated for HTTP status {} "
111 "since 4.0 and scheduled for removal in 5.0 (#3462),"
112 "the response should be provided without a body".format(
113 self.status_code
114 ),
115 DeprecationWarning,
116 stacklevel=2,
117 )
119 if headers is not None:
120 real_headers = CIMultiDict(headers)
121 else:
122 real_headers = CIMultiDict()
124 if content_type is not None:
125 if not text:
126 warnings.warn(
127 "content_type without text is deprecated "
128 "since 4.0 and scheduled for removal in 5.0 "
129 "(#3462)",
130 DeprecationWarning,
131 stacklevel=2,
132 )
133 real_headers[hdrs.CONTENT_TYPE] = content_type
134 elif hdrs.CONTENT_TYPE not in real_headers and text:
135 real_headers[hdrs.CONTENT_TYPE] = "text/plain"
137 self._reason = reason
138 self._text = text
139 self._headers = real_headers
140 self.args = ()
142 def __bool__(self) -> bool:
143 return True
145 @property
146 def status(self) -> int:
147 return self.status_code
149 @property
150 def reason(self) -> str:
151 return self._reason
153 @property
154 def text(self) -> Optional[str]:
155 return self._text
157 @property
158 def headers(self) -> "CIMultiDict[str]":
159 return self._headers
161 def __str__(self) -> str:
162 return self.reason
164 def __repr__(self) -> str:
165 return f"<{self.__class__.__name__}: {self.reason}>"
167 __reduce__ = object.__reduce__
169 def __getnewargs__(self) -> Tuple[Any, ...]:
170 return self.args
173class HTTPError(HTTPException):
174 """Base class for exceptions with status codes in the 400s and 500s."""
177class HTTPRedirection(HTTPException):
178 """Base class for exceptions with status codes in the 300s."""
181class HTTPSuccessful(HTTPException):
182 """Base class for exceptions with status codes in the 200s."""
185class HTTPOk(HTTPSuccessful):
186 status_code = 200
189class HTTPCreated(HTTPSuccessful):
190 status_code = 201
193class HTTPAccepted(HTTPSuccessful):
194 status_code = 202
197class HTTPNonAuthoritativeInformation(HTTPSuccessful):
198 status_code = 203
201class HTTPNoContent(HTTPSuccessful):
202 status_code = 204
203 empty_body = True
206class HTTPResetContent(HTTPSuccessful):
207 status_code = 205
208 empty_body = True
211class HTTPPartialContent(HTTPSuccessful):
212 status_code = 206
215############################################################
216# 3xx redirection
217############################################################
220class HTTPMove(HTTPRedirection):
221 def __init__(
222 self,
223 location: StrOrURL,
224 *,
225 headers: Optional[LooseHeaders] = None,
226 reason: Optional[str] = None,
227 text: Optional[str] = None,
228 content_type: Optional[str] = None,
229 ) -> None:
230 if not location:
231 raise ValueError("HTTP redirects need a location to redirect to.")
232 super().__init__(
233 headers=headers, reason=reason, text=text, content_type=content_type
234 )
235 self._location = URL(location)
236 self.headers["Location"] = str(self.location)
238 @property
239 def location(self) -> URL:
240 return self._location
243class HTTPMultipleChoices(HTTPMove):
244 status_code = 300
247class HTTPMovedPermanently(HTTPMove):
248 status_code = 301
251class HTTPFound(HTTPMove):
252 status_code = 302
255# This one is safe after a POST (the redirected location will be
256# retrieved with GET):
257class HTTPSeeOther(HTTPMove):
258 status_code = 303
261class HTTPNotModified(HTTPRedirection):
262 # FIXME: this should include a date or etag header
263 status_code = 304
264 empty_body = True
267class HTTPUseProxy(HTTPMove):
268 # Not a move, but looks a little like one
269 status_code = 305
272class HTTPTemporaryRedirect(HTTPMove):
273 status_code = 307
276class HTTPPermanentRedirect(HTTPMove):
277 status_code = 308
280############################################################
281# 4xx client error
282############################################################
285class HTTPClientError(HTTPError):
286 pass
289class HTTPBadRequest(HTTPClientError):
290 status_code = 400
293class HTTPUnauthorized(HTTPClientError):
294 status_code = 401
297class HTTPPaymentRequired(HTTPClientError):
298 status_code = 402
301class HTTPForbidden(HTTPClientError):
302 status_code = 403
305class HTTPNotFound(HTTPClientError):
306 status_code = 404
309class HTTPMethodNotAllowed(HTTPClientError):
310 status_code = 405
312 def __init__(
313 self,
314 method: str,
315 allowed_methods: Iterable[str],
316 *,
317 headers: Optional[LooseHeaders] = None,
318 reason: Optional[str] = None,
319 text: Optional[str] = None,
320 content_type: Optional[str] = None,
321 ) -> None:
322 allow = ",".join(sorted(allowed_methods))
323 super().__init__(
324 headers=headers, reason=reason, text=text, content_type=content_type
325 )
326 self.headers["Allow"] = allow
327 self._allowed: Set[str] = set(allowed_methods)
328 self._method = method
330 @property
331 def allowed_methods(self) -> Set[str]:
332 return self._allowed
334 @property
335 def method(self) -> str:
336 return self._method
339class HTTPNotAcceptable(HTTPClientError):
340 status_code = 406
343class HTTPProxyAuthenticationRequired(HTTPClientError):
344 status_code = 407
347class HTTPRequestTimeout(HTTPClientError):
348 status_code = 408
351class HTTPConflict(HTTPClientError):
352 status_code = 409
355class HTTPGone(HTTPClientError):
356 status_code = 410
359class HTTPLengthRequired(HTTPClientError):
360 status_code = 411
363class HTTPPreconditionFailed(HTTPClientError):
364 status_code = 412
367class HTTPRequestEntityTooLarge(HTTPClientError):
368 status_code = 413
370 def __init__(self, max_size: int, actual_size: int, **kwargs: Any) -> None:
371 kwargs.setdefault(
372 "text",
373 "Maximum request body size {} exceeded, "
374 "actual body size {}".format(max_size, actual_size),
375 )
376 super().__init__(**kwargs)
379class HTTPRequestURITooLong(HTTPClientError):
380 status_code = 414
383class HTTPUnsupportedMediaType(HTTPClientError):
384 status_code = 415
387class HTTPRequestRangeNotSatisfiable(HTTPClientError):
388 status_code = 416
391class HTTPExpectationFailed(HTTPClientError):
392 status_code = 417
395class HTTPMisdirectedRequest(HTTPClientError):
396 status_code = 421
399class HTTPUnprocessableEntity(HTTPClientError):
400 status_code = 422
403class HTTPFailedDependency(HTTPClientError):
404 status_code = 424
407class HTTPUpgradeRequired(HTTPClientError):
408 status_code = 426
411class HTTPPreconditionRequired(HTTPClientError):
412 status_code = 428
415class HTTPTooManyRequests(HTTPClientError):
416 status_code = 429
419class HTTPRequestHeaderFieldsTooLarge(HTTPClientError):
420 status_code = 431
423class HTTPUnavailableForLegalReasons(HTTPClientError):
424 status_code = 451
426 def __init__(
427 self,
428 link: Optional[StrOrURL],
429 *,
430 headers: Optional[LooseHeaders] = None,
431 reason: Optional[str] = None,
432 text: Optional[str] = None,
433 content_type: Optional[str] = None,
434 ) -> None:
435 super().__init__(
436 headers=headers, reason=reason, text=text, content_type=content_type
437 )
438 self._link = None
439 if link:
440 self._link = URL(link)
441 self.headers["Link"] = f'<{str(self._link)}>; rel="blocked-by"'
443 @property
444 def link(self) -> Optional[URL]:
445 return self._link
448############################################################
449# 5xx Server Error
450############################################################
451# Response status codes beginning with the digit "5" indicate cases in
452# which the server is aware that it has erred or is incapable of
453# performing the request. Except when responding to a HEAD request, the
454# server SHOULD include an entity containing an explanation of the error
455# situation, and whether it is a temporary or permanent condition. User
456# agents SHOULD display any included entity to the user. These response
457# codes are applicable to any request method.
460class HTTPServerError(HTTPError):
461 pass
464class HTTPInternalServerError(HTTPServerError):
465 status_code = 500
468class HTTPNotImplemented(HTTPServerError):
469 status_code = 501
472class HTTPBadGateway(HTTPServerError):
473 status_code = 502
476class HTTPServiceUnavailable(HTTPServerError):
477 status_code = 503
480class HTTPGatewayTimeout(HTTPServerError):
481 status_code = 504
484class HTTPVersionNotSupported(HTTPServerError):
485 status_code = 505
488class HTTPVariantAlsoNegotiates(HTTPServerError):
489 status_code = 506
492class HTTPInsufficientStorage(HTTPServerError):
493 status_code = 507
496class HTTPNotExtended(HTTPServerError):
497 status_code = 510
500class HTTPNetworkAuthenticationRequired(HTTPServerError):
501 status_code = 511
504def _initialize_default_reason() -> None:
505 for obj in globals().values():
506 if isinstance(obj, type) and issubclass(obj, HTTPException):
507 if obj.status_code >= 0:
508 try:
509 status = HTTPStatus(obj.status_code)
510 obj.default_reason = status.phrase
511 except ValueError:
512 pass
515_initialize_default_reason()
516del _initialize_default_reason