1 from __future__ import annotations 2 3 from enum import IntEnum 4 5 __all__ = ["codes"] 6 7 8 class 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. 161 for code in codes: 162 setattr(codes, code._name_.lower(), int(code)) 163