diff --git a/docs/_newsfragments/1947.newandimproved.rst b/docs/_newsfragments/1947.newandimproved.rst index 8ea9675c2..b52bbe539 100644 --- a/docs/_newsfragments/1947.newandimproved.rst +++ b/docs/_newsfragments/1947.newandimproved.rst @@ -1,4 +1,4 @@ -Basic typing annotations have been added to the most commonly used functions of -Falcon's public interface to the package itself in order to better support -`mypy `_ users without having to install any -third-party typeshed packages. +Type annotations have been added to Falcon's public interface to the package +itself in order to better support `Mypy `__ +(or other type checkers) users without having to install any third-party +typeshed packages. diff --git a/docs/_newsfragments/2023.newandimproved.rst b/docs/_newsfragments/2023.newandimproved.rst index b5001079c..baa31624d 100644 --- a/docs/_newsfragments/2023.newandimproved.rst +++ b/docs/_newsfragments/2023.newandimproved.rst @@ -1,4 +1,4 @@ The default error serializer will now use the response media handlers -to better negotiate the response serialization with the client. +to better negotiate the response content type with the client. The implementation still defaults to JSON if the client does not indicate any preference. diff --git a/docs/_newsfragments/2090.breakingchange.rst b/docs/_newsfragments/2090.breakingchange.rst index 6e16920ca..34dbfe9fa 100644 --- a/docs/_newsfragments/2090.breakingchange.rst +++ b/docs/_newsfragments/2090.breakingchange.rst @@ -1,5 +1,4 @@ The deprecated ``api_helpers`` was removed in favor of the ``app_helpers`` -module. In addition, the deprecated ``body`` -attributes for the :class:`~falcon.Response`, -:class:`asgi.Response `, -and :class:`~falcon.HTTPStatus` classes. +module. In addition, the deprecated ``body`` attributes of the +:class:`~falcon.Response`, :class:`asgi.Response `, and +:class:`~falcon.HTTPStatus` classes were removed. diff --git a/docs/_newsfragments/2124.newandimproved.rst b/docs/_newsfragments/2124.newandimproved.rst index edcaa0bdd..d83c19c02 100644 --- a/docs/_newsfragments/2124.newandimproved.rst +++ b/docs/_newsfragments/2124.newandimproved.rst @@ -1 +1,3 @@ -Added kwarg samesite to :meth:`~falcon.Response.unset_cookie` to allow override of default ``Lax`` setting of `SameSite` on the unset cookie \ No newline at end of file +A new keyword argument, `samesite`, was added to +:meth:`~falcon.Response.unset_cookie` that allows to override the default +``Lax`` setting of `SameSite` on the unset cookie. diff --git a/docs/_newsfragments/2213.newandimproved.rst b/docs/_newsfragments/2213.newandimproved.rst index 981fc0ac6..de889090b 100644 --- a/docs/_newsfragments/2213.newandimproved.rst +++ b/docs/_newsfragments/2213.newandimproved.rst @@ -1,6 +1,6 @@ -Added kwarg ``partitioned`` to :meth:`~falcon.Response.set_cookie` -to opt a cookie into partitioned storage, with a separate cookie jar per -top-level site. -See also +A new keyword argument, `partitioned`, was added to +:meth:`~falcon.Response.set_cookie` to opt a cookie into partitioned storage, +with a separate cookie jar per each top-level site. +(See also `CHIPS `__ -for a more detailed description of this experimental web technology. +for a more detailed description of this web technology.) diff --git a/docs/_newsfragments/228.newandimproved.rst b/docs/_newsfragments/228.newandimproved.rst index 5198a9d18..e76561191 100644 --- a/docs/_newsfragments/228.newandimproved.rst +++ b/docs/_newsfragments/228.newandimproved.rst @@ -1,2 +1,4 @@ -Add link-extension to :meth:`falcon.Response.append_link` as specified in -`RFC 8288 Sec. 3.4.2 `__. +A new keyword argument, `link_extension`, was added to +:meth:`falcon.Response.append_link` as specified in +`RFC 8288, Section 3.4.2 +`__. diff --git a/docs/_newsfragments/2301.misc.rst b/docs/_newsfragments/2301.misc.rst index e6d2c8f89..8186a207e 100644 --- a/docs/_newsfragments/2301.misc.rst +++ b/docs/_newsfragments/2301.misc.rst @@ -1,2 +1,2 @@ -The ``falcon.TimezoneGMT`` class was deprecated. Use the UTC timezone +The :class:`falcon.TimezoneGMT` class was deprecated. Use the UTC timezone (:attr:`datetime.timezone.utc`) from the standard library instead. diff --git a/docs/_newsfragments/2325.newandimproved.rst b/docs/_newsfragments/2325.newandimproved.rst index 62a61b81e..7515e79e1 100644 --- a/docs/_newsfragments/2325.newandimproved.rst +++ b/docs/_newsfragments/2325.newandimproved.rst @@ -1,4 +1,4 @@ -The :class:`~CORSMiddleware` now properly handles the missing ``Allow`` +The :class:`~falcon.CORSMiddleware` now properly handles the missing ``Allow`` header case, by denying the preflight CORS request. -The static resource has been updated to properly support CORS request, -by allowing GET requests. +The static file route has been updated to properly support CORS preflight, +by allowing ``GET`` requests. diff --git a/docs/_newsfragments/2343.breakingchange.rst b/docs/_newsfragments/2343.breakingchange.rst index ba2284e25..4e6fa7fb9 100644 --- a/docs/_newsfragments/2343.breakingchange.rst +++ b/docs/_newsfragments/2343.breakingchange.rst @@ -1,5 +1,8 @@ -Removed ``is_async`` argument from :meth:`~falcon.media.validators.jsonschema.validate` -and the hooks :meth:`~falcon.before` and :meth:`~falcon.after` since it's -no longer needed. -Cython from 3.0 will correctly mark ``asnyc def`` as coroutine, making -this argument no longer useful. +The ``is_async`` keyword argument was removed from +:meth:`~falcon.media.validators.jsonschema.validate`, as well as the hooks +:meth:`~falcon.before` and :meth:`~falcon.after`, since it represented a niche +use case that is even less relevant with the recent advances in the ecosystem: +Cython 3.0+ will now correctly mark cythonized ``async def`` functions as +coroutines, and pure-Python factory functions that return a coroutine can now +be marked as such using :func:`inspect.markcoroutinefunction` +(Python 3.12+ is required). diff --git a/docs/_newsfragments/2355.newandimproved.rst b/docs/_newsfragments/2355.newandimproved.rst index 8cbc812ec..c708de094 100644 --- a/docs/_newsfragments/2355.newandimproved.rst +++ b/docs/_newsfragments/2355.newandimproved.rst @@ -1,10 +1,14 @@ -Added a new flag :attr:`~falcon.ResponseOptions.xml_error_serialization` that -can be used to disable XML serialization of :class:`~falcon.HTTPError` when -using the default error serializer (and the client preferred it). -This flag currently defaults to ``True``, keeping the same behavior as the previous -Falcon series; Falcon 5.0 will change the default to ``False``, with the objective of -completely removing support for it in a future version. -User that whish to retain support for XML serialization of the errors in the default -error serializer should add an XML media handler. +A new flag, :attr:`~falcon.ResponseOptions.xml_error_serialization`, has been +added to :attr:`~falcon.ResponseOptions` that can be used to disable automatic +XML serialization of :class:`~falcon.HTTPError` when using the default error +serializer (and the client prefers it). -Deprecated the :meth:`~falcon.HTTPError.to_xml` method. +This new flag currently defaults to ``True``, preserving the same behavior as +the previous Falcon versions. Falcon 5.0 will either change the default to +``False``, or remove the automatic XML error serialization altogether. +If you wish to retain support for XML serialization in the default error +serializer, you should add a +:ref:`response media handler for XML `. + +In accordance with this change, the :meth:`falcon.HTTPError.to_xml` method was +deprecated. diff --git a/docs/api/testing.rst b/docs/api/testing.rst index 67357cb52..abce080a3 100644 --- a/docs/api/testing.rst +++ b/docs/api/testing.rst @@ -18,8 +18,10 @@ Main Interface :members: .. autoclass:: Result :members: + :inherited-members: .. autoclass:: StreamedResult :members: + :inherited-members: .. autoclass:: ResultBodyStream :members: .. autoclass:: ASGIWebSocketSimulator diff --git a/falcon/app.py b/falcon/app.py index 9c764f557..f74083693 100644 --- a/falcon/app.py +++ b/falcon/app.py @@ -1273,8 +1273,9 @@ class API(App): reflect the breadth of applications that :class:`App `, and its ASGI counterpart in particular, can now be used for. - This compatibility alias is deprecated; it will be removed entirely in - Falcon 5.0. + .. deprecated:: 3.0 + This compatibility alias is deprecated; it will be removed entirely in + Falcon 5.0. """ @deprecation.deprecated( diff --git a/falcon/app_helpers.py b/falcon/app_helpers.py index 68ccc28d9..1248d280b 100644 --- a/falcon/app_helpers.py +++ b/falcon/app_helpers.py @@ -321,9 +321,9 @@ def default_serialize_error(req: Request, resp: Response, exception: HTTPError) if '+json' in accept: preferred = MEDIA_JSON elif '+xml' in accept: - # NOTE(caselit): ignore xml_error_serialization when - # checking if the media should be xml. This gives a chance to - # a xml media handler, if any, to be used + # NOTE(caselit): Ignore xml_error_serialization when + # checking if the media should be XML. This gives a chance to + # an XML media handler, if any, to be used. preferred = MEDIA_XML if preferred is not None: @@ -331,14 +331,14 @@ def default_serialize_error(req: Request, resp: Response, exception: HTTPError) preferred, MEDIA_JSON, raise_not_found=False ) if preferred == MEDIA_JSON: - # NOTE(caselit): special case json to ensure that it's always possible to - # serialize an error in json even if no handler is set in the - # media_handlers. + # NOTE(caselit): Special case JSON to ensure that it's always + # possible to serialize an error in JSON even if no JSON handler + # is set in the media_handlers. resp.data = exception.to_json(handler) elif handler: - # NOTE(caselit): Let the app serialize the response even if it needs - # to re-get the handler, since async handlers may not have a sync - # version available. + # NOTE(caselit): Let the app serialize the response even if it + # needs to re-get the handler, since async handlers may not have + # a sync version available. resp.media = exception.to_dict() elif options.xml_error_serialization: resp.data = exception._to_xml() diff --git a/falcon/errors.py b/falcon/errors.py index 092fff2e5..f47e82b07 100644 --- a/falcon/errors.py +++ b/falcon/errors.py @@ -1016,6 +1016,8 @@ class HTTPContentTooLarge(HTTPError): code (int): An internal code that customers can reference in their support request or to help them when searching for knowledge base articles related to this error (default ``None``). + + .. versionadded:: 4.0 """ def __init__( diff --git a/falcon/http_error.py b/falcon/http_error.py index 26a6b18f9..30b0050a5 100644 --- a/falcon/http_error.py +++ b/falcon/http_error.py @@ -19,7 +19,7 @@ import xml.etree.ElementTree as et from falcon.constants import MEDIA_JSON -from falcon.util import deprecated +from falcon.util import deprecation from falcon.util import misc from falcon.util import uri @@ -237,15 +237,19 @@ def _to_xml(self) -> bytes: error_element, encoding='utf-8' ) - @deprecated( - 'The internal serialization to xml is deprecated. A similar output can be ' - 'obtained by serializing to xml the output of ``.to_dict()``' + @deprecation.deprecated( + 'The internal error serialization to XML is deprecated. ' + 'Please serialize the output of to_dict() to XML instead.' ) def to_xml(self) -> bytes: """Return an XML-encoded representation of the error. Returns: bytes: An XML document for the error. + + .. deprecated:: 4.0 + Automatic error serialization to XML is deprecated. + Please serialize the output of :meth:`to_dict` to XML instead. """ return self._to_xml() diff --git a/falcon/request.py b/falcon/request.py index 64f9312e1..a3f690e1b 100644 --- a/falcon/request.py +++ b/falcon/request.py @@ -886,7 +886,10 @@ def headers(self) -> Mapping[str, str]: @property def headers_lower(self) -> Mapping[str, str]: - """Same as :attr:`headers` except header names are normalized to lowercase.""" + """Same as :attr:`headers` except header names are normalized to lowercase. + + .. versionadded:: 4.0 + """ if self._cached_headers_lower is None: self._cached_headers_lower = { key.lower(): value for key, value in self.headers.items() @@ -1283,6 +1286,8 @@ def get_header_as_int(self, header: str, required: bool = False) -> Optional[int HTTPBadRequest: The header was not found in the request, but it was required. HttpInvalidHeader: The header contained a malformed/invalid value. + + .. versionadded:: 4.0 """ http_int = self.get_header(header, required=required) @@ -2426,11 +2431,11 @@ def auto_parse_form_urlencoded(self) -> bool: via :attr:`~falcon.Request.params`, :meth:`~falcon.Request.get_param`, etc. - Warning: + .. deprecated:: 3.0 The `auto_parse_form_urlencoded` option is not supported for ASGI apps, and is considered deprecated for WSGI apps as of Falcon 3.0, in favor of accessing URL-encoded forms - through :attr:`~Request.media`. + through :meth:`~falcon.Request.get_media`. The attribute and the auto-parsing functionality will be removed entirely in Falcon 5.0. diff --git a/falcon/response.py b/falcon/response.py index afcc8941a..b60529deb 100644 --- a/falcon/response.py +++ b/falcon/response.py @@ -456,6 +456,9 @@ def set_cookie( # noqa: C901 standardized, it is already used by Chrome. (See also: `CHIPS`_) + + .. versionadded:: 4.0 + Raises: KeyError: `name` is not a valid cookie name. ValueError: `value` is not a valid cookie value. @@ -574,6 +577,8 @@ def unset_cookie( samesite (str): Allows to override the default 'Lax' same_site setting for the unset cookie. + .. versionadded:: 4.0 + domain (str): Restricts the cookie to a specific domain and any subdomains of that domain. By default, the user agent will return the cookie only to the origin server. @@ -898,10 +903,9 @@ def append_link( Can take values 'anonymous' or 'use-credentials' or None. (See: https://www.w3.org/TR/html50/infrastructure.html#cors-settings-attribute) - link_extension(iterable): Provides additional custom attributes, as - described in RFC 8288, Section 3.4.2. Each member of the iterable + link_extension: Provides additional custom attributes, as + described in RFC 8288, Section 3.4.2; each member of the iterable must be a two-tuple in the form of (*param*, *value*). - (See: https://datatracker.ietf.org/doc/html/rfc8288#section-3.4.2) """ @@ -1371,7 +1375,7 @@ class ResponseOptions: secure_cookies_by_default: bool """Set to ``False`` in development environments to make the ``secure`` attribute - for all cookies. (default ``False``). + for all cookies. (default ``True``). This can make testing easier by not requiring HTTPS. Note, however, that this setting can be overridden via :meth:`~.Response.set_cookie()`'s ``secure`` kwarg. @@ -1397,19 +1401,22 @@ class ResponseOptions: """ xml_error_serialization: bool """Set to ``False`` to disable automatic inclusion of the XML handler - in the default error serializer (:ref:`errors`) (default ``True``). + in the :ref:`default error serializer ` (default ``True``). - Enabling this option does not automatically render all error response in XML, - but only if the client prefers (via the ``Accept`` request header) XML to JSON - and other configured media handlers. + Enabling this option does not make Falcon automatically render all error + responses in XML, but it is used only in the case the client prefers + (via the ``Accept`` request header) XML to JSON and other configured media + handlers. Note: - This option will default to ``False`` in Falcon 5.0 disabling XML error - serialization by default). + Falcon 5.0 will either change the default to ``False``, or remove the + automatic XML error serialization altogether. Note: This option has no effect when a custom error serializer, set using :meth:`~falcon.App.set_error_serializer`, is in use. + + .. versionadded:: 4.0 """ __slots__ = ( diff --git a/falcon/routing/converters.py b/falcon/routing/converters.py index d50d6b85e..d012a412d 100644 --- a/falcon/routing/converters.py +++ b/falcon/routing/converters.py @@ -24,6 +24,7 @@ 'DateTimeConverter', 'FloatConverter', 'IntConverter', + 'PathConverter', 'UUIDConverter', ) @@ -140,7 +141,9 @@ class FloatConverter(BaseConverter): max (float): Reject the value if it is greater than this number. finite (bool) : Determines whether or not to only match ordinary finite numbers (default: ``True``). Set to ``False`` to match - nan, inf, and -inf in addition to finite numbers. + ``nan``, ``inf``, and ``-inf`` in addition to finite numbers. + + .. versionadded:: 4.0 """ __slots__ = '_finite', '_min', '_max' @@ -228,6 +231,8 @@ class PathConverter(BaseConverter): (the default), while it will *not* match when that option is ``True``. (See also: :ref:`trailing_slash_in_path`) + + .. versionadded:: 4.0 """ CONSUME_MULTIPLE_SEGMENTS = True diff --git a/falcon/util/mediatypes.py b/falcon/util/mediatypes.py index 1d5218d5c..1fd4983a6 100644 --- a/falcon/util/mediatypes.py +++ b/falcon/util/mediatypes.py @@ -78,6 +78,8 @@ def parse_header(line: str) -> Tuple[str, Dict[str, str]]: This function replaces an equivalent method previously available in the stdlib as ``cgi.parse_header()``. It was removed from the stdlib in Python 3.13. + + .. versionadded:: 4.0 """ if '"' not in line and '\\' not in line: key, semicolon, parts = line.partition(';') @@ -279,6 +281,8 @@ def quality(media_type: str, header: str) -> float: Returns: Quality of the most specific media range matching the provided `media_type`. (If none matches, 0.0 is returned.) + + .. versionadded:: 4.0 """ parsed_media_type = _parse_media_type(media_type) most_specific = max( @@ -300,6 +304,8 @@ def best_match(media_types: Iterable[str], header: str) -> str: Returns: Best match from the supported candidates, or an empty string if the provided header value does not match any of the given types. + + .. versionadded:: 4.0 """ # PERF(vytas): Using the default parameter, i.e., max(..., default='', 0.0) # would be much nicer than EAFP, but for some reason it is quite slow diff --git a/falcon/util/time.py b/falcon/util/time.py index 741ad8fe5..c7b714460 100644 --- a/falcon/util/time.py +++ b/falcon/util/time.py @@ -20,7 +20,12 @@ class TimezoneGMT(datetime.tzinfo): - """GMT timezone class implementing the :class:`datetime.tzinfo` interface.""" + """GMT timezone class implementing the :class:`datetime.tzinfo` interface. + + .. deprecated:: 4.0 + :class:`TimezoneGMT` is deprecated, use :attr:`datetime.timezone.utc` + instead. (This class will be removed in Falcon 5.0.) + """ GMT_ZERO = datetime.timedelta(hours=0) diff --git a/tests/test_httperror.py b/tests/test_httperror.py index 9441f32b3..873aa3020 100644 --- a/tests/test_httperror.py +++ b/tests/test_httperror.py @@ -41,7 +41,6 @@ def enable_xml(request): def go(app): if request.param is not None: app.resp_options.xml_error_serialization = request.param - # return bool(request.param) return request.param is not False return go @@ -360,7 +359,8 @@ def test_xml_enable(self, client, enable_xml, custom_xml): def test_to_xml_deprecated(self): with pytest.warns( - DeprecatedWarning, match='The internal serialization to xml is deprecated.' + DeprecatedWarning, + match='The internal error serialization to XML is deprecated.', ): res = falcon.HTTPGone().to_xml() assert res == falcon.HTTPGone()._to_xml()