1from __future__ import annotations
2
3from enum import IntEnum
4
5__all__ = ["codes"]
6
7
8class codes(IntEnum):
9 """HTTP status codes and reason phrases
10
11 Status codes from the following RFCs are all observed:
12
13 * RFC 7231: Hypertext Transfer Protocol (HTTP/1.1), obsoletes 2616
14 * RFC 6585: Additional HTTP Status Codes
15 * RFC 3229: Delta encoding in HTTP
16 * RFC 4918: HTTP Extensions for WebDAV, obsoletes 2518
17 * RFC 5842: Binding Extensions to WebDAV
18 * RFC 7238: Permanent Redirect
19 * RFC 2295: Transparent Content Negotiation in HTTP
20 * RFC 2774: An HTTP Extension Framework
21 * RFC 7540: Hypertext Transfer Protocol Version 2 (HTTP/2)
22 * RFC 2324: Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0)
23 * RFC 7725: An HTTP Status Code to Report Legal Obstacles
24 * RFC 8297: An HTTP Status Code for Indicating Hints
25 * RFC 8470: Using Early Data in HTTP
26 """
27
28 def __new__(cls, value: int, phrase: str = "") -> codes:
29 obj = int.__new__(cls, value)
30 obj._value_ = value
31
32 obj.phrase = phrase # type: ignore[attr-defined]
33 return obj
34
35 def __str__(self) -> str:
36 return str(self.value)
37
38 @classmethod
39 def get_reason_phrase(cls, value: int) -> str:
40 try:
41 return codes(value).phrase # type: ignore
42 except ValueError:
43 return ""
44
45 @classmethod
46 def is_informational(cls, value: int) -> bool:
47 """
48 Returns `True` for 1xx status codes, `False` otherwise.
49 """
50 return 100 <= value <= 199
51
52 @classmethod
53 def is_success(cls, value: int) -> bool:
54 """
55 Returns `True` for 2xx status codes, `False` otherwise.
56 """
57 return 200 <= value <= 299
58
59 @classmethod
60 def is_redirect(cls, value: int) -> bool:
61 """
62 Returns `True` for 3xx status codes, `False` otherwise.
63 """
64 return 300 <= value <= 399
65
66 @classmethod
67 def is_client_error(cls, value: int) -> bool:
68 """
69 Returns `True` for 4xx status codes, `False` otherwise.
70 """
71 return 400 <= value <= 499
72
73 @classmethod
74 def is_server_error(cls, value: int) -> bool:
75 """
76 Returns `True` for 5xx status codes, `False` otherwise.
77 """
78 return 500 <= value <= 599
79
80 @classmethod
81 def is_error(cls, value: int) -> bool:
82 """
83 Returns `True` for 4xx or 5xx status codes, `False` otherwise.
84 """
85 return 400 <= value <= 599
86
87 # informational
88 CONTINUE = 100, "Continue"
89 SWITCHING_PROTOCOLS = 101, "Switching Protocols"
90 PROCESSING = 102, "Processing"
91 EARLY_HINTS = 103, "Early Hints"
92
93 # success
94 OK = 200, "OK"
95 CREATED = 201, "Created"
96 ACCEPTED = 202, "Accepted"
97 NON_AUTHORITATIVE_INFORMATION = 203, "Non-Authoritative Information"
98 NO_CONTENT = 204, "No Content"
99 RESET_CONTENT = 205, "Reset Content"
100 PARTIAL_CONTENT = 206, "Partial Content"
101 MULTI_STATUS = 207, "Multi-Status"
102 ALREADY_REPORTED = 208, "Already Reported"
103 IM_USED = 226, "IM Used"
104
105 # redirection
106 MULTIPLE_CHOICES = 300, "Multiple Choices"
107 MOVED_PERMANENTLY = 301, "Moved Permanently"
108 FOUND = 302, "Found"
109 SEE_OTHER = 303, "See Other"
110 NOT_MODIFIED = 304, "Not Modified"
111 USE_PROXY = 305, "Use Proxy"
112 TEMPORARY_REDIRECT = 307, "Temporary Redirect"
113 PERMANENT_REDIRECT = 308, "Permanent Redirect"
114
115 # client error
116 BAD_REQUEST = 400, "Bad Request"
117 UNAUTHORIZED = 401, "Unauthorized"
118 PAYMENT_REQUIRED = 402, "Payment Required"
119 FORBIDDEN = 403, "Forbidden"
120 NOT_FOUND = 404, "Not Found"
121 METHOD_NOT_ALLOWED = 405, "Method Not Allowed"
122 NOT_ACCEPTABLE = 406, "Not Acceptable"
123 PROXY_AUTHENTICATION_REQUIRED = 407, "Proxy Authentication Required"
124 REQUEST_TIMEOUT = 408, "Request Timeout"
125 CONFLICT = 409, "Conflict"
126 GONE = 410, "Gone"
127 LENGTH_REQUIRED = 411, "Length Required"
128 PRECONDITION_FAILED = 412, "Precondition Failed"
129 REQUEST_ENTITY_TOO_LARGE = 413, "Request Entity Too Large"
130 REQUEST_URI_TOO_LONG = 414, "Request-URI Too Long"
131 UNSUPPORTED_MEDIA_TYPE = 415, "Unsupported Media Type"
132 REQUESTED_RANGE_NOT_SATISFIABLE = 416, "Requested Range Not Satisfiable"
133 EXPECTATION_FAILED = 417, "Expectation Failed"
134 IM_A_TEAPOT = 418, "I'm a teapot"
135 MISDIRECTED_REQUEST = 421, "Misdirected Request"
136 UNPROCESSABLE_ENTITY = 422, "Unprocessable Entity"
137 LOCKED = 423, "Locked"
138 FAILED_DEPENDENCY = 424, "Failed Dependency"
139 TOO_EARLY = 425, "Too Early"
140 UPGRADE_REQUIRED = 426, "Upgrade Required"
141 PRECONDITION_REQUIRED = 428, "Precondition Required"
142 TOO_MANY_REQUESTS = 429, "Too Many Requests"
143 REQUEST_HEADER_FIELDS_TOO_LARGE = 431, "Request Header Fields Too Large"
144 UNAVAILABLE_FOR_LEGAL_REASONS = 451, "Unavailable For Legal Reasons"
145
146 # server errors
147 INTERNAL_SERVER_ERROR = 500, "Internal Server Error"
148 NOT_IMPLEMENTED = 501, "Not Implemented"
149 BAD_GATEWAY = 502, "Bad Gateway"
150 SERVICE_UNAVAILABLE = 503, "Service Unavailable"
151 GATEWAY_TIMEOUT = 504, "Gateway Timeout"
152 HTTP_VERSION_NOT_SUPPORTED = 505, "HTTP Version Not Supported"
153 VARIANT_ALSO_NEGOTIATES = 506, "Variant Also Negotiates"
154 INSUFFICIENT_STORAGE = 507, "Insufficient Storage"
155 LOOP_DETECTED = 508, "Loop Detected"
156 NOT_EXTENDED = 510, "Not Extended"
157 NETWORK_AUTHENTICATION_REQUIRED = 511, "Network Authentication Required"
158
159
160# Include lower-case styles for `requests` compatibility.
161for code in codes:
162 setattr(codes, code._name_.lower(), int(code))