diff --git a/Doc/library/http.rst b/Doc/library/http.rst index 5895a41d849..521fd1b7f50 100644 --- a/Doc/library/http.rst +++ b/Doc/library/http.rst @@ -137,6 +137,31 @@ equal to the constant name (i.e. ``http.HTTPStatus.OK`` is also available as .. versionadded:: 3.9 Added ``103 EARLY_HINTS``, ``418 IM_A_TEAPOT`` and ``425 TOO_EARLY`` status codes. +HTTP status category +-------------------- + +.. versionadded:: 3.11 + +The enum values have several properties to indicate the HTTP status category: + +==================== ======================== =============================== +Property Indicates that Details +==================== ======================== =============================== +``is_informational`` ``100 <= status <= 199`` HTTP/1.1 :rfc:`7231`, Section 6 +``is_success`` ``200 <= status <= 299`` HTTP/1.1 :rfc:`7231`, Section 6 +``is_redirection`` ``300 <= status <= 399`` HTTP/1.1 :rfc:`7231`, Section 6 +``is_client_error`` ``400 <= status <= 499`` HTTP/1.1 :rfc:`7231`, Section 6 +``is_server_error`` ``500 <= status <= 599`` HTTP/1.1 :rfc:`7231`, Section 6 +==================== ======================== =============================== + + Usage:: + + >>> from http import HTTPStatus + >>> HTTPStatus.OK.is_success + True + >>> HTTPStatus.OK.is_client_error + False + .. class:: HTTPMethod .. versionadded:: 3.11 diff --git a/Lib/enum.py b/Lib/enum.py index 8ef69589a14..e7375e1eae6 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -1887,7 +1887,7 @@ def _test_simple_enum(checked_enum, simple_enum): else: checked_value = checked_dict[key] simple_value = simple_dict[key] - if callable(checked_value): + if callable(checked_value) or isinstance(checked_value, bltns.property): continue if key == '__doc__': # remove all spaces/tabs diff --git a/Lib/http/__init__.py b/Lib/http/__init__.py index cd2885dc775..e093a1fec4d 100644 --- a/Lib/http/__init__.py +++ b/Lib/http/__init__.py @@ -31,6 +31,26 @@ def __new__(cls, value, phrase, description=''): obj.description = description return obj + @property + def is_informational(self): + return 100 <= self <= 199 + + @property + def is_success(self): + return 200 <= self <= 299 + + @property + def is_redirection(self): + return 300 <= self <= 399 + + @property + def is_client_error(self): + return 400 <= self <= 499 + + @property + def is_server_error(self): + return 500 <= self <= 599 + # informational CONTINUE = 100, 'Continue', 'Request received, please continue' SWITCHING_PROTOCOLS = (101, 'Switching Protocols', diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 15dab0356f5..b3d94e0a21c 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -553,6 +553,27 @@ def __new__(cls, value, phrase, description=''): obj.phrase = phrase obj.description = description return obj + + @property + def is_informational(self): + return 100 <= self <= 199 + + @property + def is_success(self): + return 200 <= self <= 299 + + @property + def is_redirection(self): + return 300 <= self <= 399 + + @property + def is_client_error(self): + return 400 <= self <= 499 + + @property + def is_server_error(self): + return 500 <= self <= 599 + # informational CONTINUE = 100, 'Continue', 'Request received, please continue' SWITCHING_PROTOCOLS = (101, 'Switching Protocols', @@ -669,6 +690,30 @@ def __new__(cls, value, phrase, description=''): 'The client needs to authenticate to gain network access') enum._test_simple_enum(CheckedHTTPStatus, HTTPStatus) + def test_httpstatus_range(self): + """Checks that the statuses are in the 100-599 range""" + + for member in HTTPStatus.__members__.values(): + self.assertGreaterEqual(member, 100) + self.assertLessEqual(member, 599) + + def test_httpstatus_category(self): + """Checks that the statuses belong to the standard categories""" + + categories = ( + ((100, 199), "is_informational"), + ((200, 299), "is_success"), + ((300, 399), "is_redirection"), + ((400, 499), "is_client_error"), + ((500, 599), "is_server_error"), + ) + for member in HTTPStatus.__members__.values(): + for (lower, upper), category in categories: + category_indicator = getattr(member, category) + if lower <= member <= upper: + self.assertTrue(category_indicator) + else: + self.assertFalse(category_indicator) def test_status_lines(self): # Test HTTP status lines diff --git a/Misc/NEWS.d/next/Library/2022-08-07-14-56-23.gh-issue-95149.U0c6Ib.rst b/Misc/NEWS.d/next/Library/2022-08-07-14-56-23.gh-issue-95149.U0c6Ib.rst new file mode 100644 index 00000000000..6393444b53f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-08-07-14-56-23.gh-issue-95149.U0c6Ib.rst @@ -0,0 +1,2 @@ +The :class:`HTTPStatus ` enum offers a couple of properties +to indicate the HTTP status category e.g. ``HTTPStatus.OK.is_success``.