From c3fb1d99ca8376e8576cd6c2cf60c360ab7d9227 Mon Sep 17 00:00:00 2001 From: Aydeing Date: Tue, 16 Jun 2026 00:30:35 +0530 Subject: [PATCH] docs(recipes): add type hints to request_id and custom media handler examples Annotate the recipe snippet files referenced from the docs so they demonstrate the type-hinted style described in #1820: - examples/recipes/request_id_context.py - examples/recipes/request_id_log.py - examples/recipes/request_id_middleware.py - examples/recipes/request_id_structlog.py - examples/recipes/plain_text_main.py - examples/recipes/pretty_json_main.py No runtime behavior changes. Refs: #1820 --- docs/_newsfragments/1820.misc.rst | 1 + examples/recipes/plain_text_main.py | 9 ++++++--- examples/recipes/pretty_json_main.py | 9 ++++++--- examples/recipes/request_id_context.py | 11 +++++++---- examples/recipes/request_id_log.py | 2 +- examples/recipes/request_id_middleware.py | 12 ++++++++++-- examples/recipes/request_id_structlog.py | 12 ++++++++++-- 7 files changed, 41 insertions(+), 15 deletions(-) create mode 100644 docs/_newsfragments/1820.misc.rst diff --git a/docs/_newsfragments/1820.misc.rst b/docs/_newsfragments/1820.misc.rst new file mode 100644 index 000000000..918590d54 --- /dev/null +++ b/docs/_newsfragments/1820.misc.rst @@ -0,0 +1 @@ +Added type annotations to the recipe snippets covering ``request_id_*`` middleware/context examples and the ``plain_text_main`` / ``pretty_json_main`` custom media handler examples (see :ref:`recipes`). diff --git a/examples/recipes/plain_text_main.py b/examples/recipes/plain_text_main.py index aad21f997..17a77a404 100644 --- a/examples/recipes/plain_text_main.py +++ b/examples/recipes/plain_text_main.py @@ -1,4 +1,5 @@ import functools +from typing import IO import falcon @@ -8,13 +9,15 @@ class TextHandler(falcon.media.BaseHandler): @classmethod @functools.lru_cache - def _get_charset(cls, content_type): + def _get_charset(cls, content_type: str) -> str: _, params = falcon.parse_header(content_type) return params.get('charset') or cls.DEFAULT_CHARSET - def deserialize(self, stream, content_type, content_length): + def deserialize( + self, stream: IO[bytes], content_type: str, content_length: int + ) -> str: data = stream.read() return data.decode(self._get_charset(content_type)) - def serialize(self, media, content_type): + def serialize(self, media: str, content_type: str) -> bytes: return media.encode(self._get_charset(content_type)) diff --git a/examples/recipes/pretty_json_main.py b/examples/recipes/pretty_json_main.py index bd1a02d33..32dd8eb91 100644 --- a/examples/recipes/pretty_json_main.py +++ b/examples/recipes/pretty_json_main.py @@ -1,4 +1,5 @@ import json +from typing import Any, IO, Optional import falcon @@ -6,13 +7,15 @@ class CustomJSONHandler(falcon.media.BaseHandler): MAX_INDENT_LEVEL = 8 - def deserialize(self, stream, content_type, content_length): + def deserialize( + self, stream: IO[bytes], content_type: str, content_length: int + ) -> Any: data = stream.read() return json.loads(data.decode()) - def serialize(self, media, content_type): + def serialize(self, media: Any, content_type: str) -> bytes: _, params = falcon.parse_header(content_type) - indent = params.get('indent') + indent: Optional[int] = params.get('indent') if indent is not None: try: indent = int(indent) diff --git a/examples/recipes/request_id_context.py b/examples/recipes/request_id_context.py index f4b514d20..2b74c38a5 100644 --- a/examples/recipes/request_id_context.py +++ b/examples/recipes/request_id_context.py @@ -1,16 +1,19 @@ import contextvars +from typing import Optional class _Context: - def __init__(self): - self._request_id_var = contextvars.ContextVar('request_id', default=None) + def __init__(self) -> None: + self._request_id_var: contextvars.ContextVar[Optional[str]] = ( + contextvars.ContextVar('request_id', default=None) + ) @property - def request_id(self): + def request_id(self) -> Optional[str]: return self._request_id_var.get() @request_id.setter - def request_id(self, value): + def request_id(self, value: str) -> None: self._request_id_var.set(value) diff --git a/examples/recipes/request_id_log.py b/examples/recipes/request_id_log.py index 0dbf84044..f326e4470 100644 --- a/examples/recipes/request_id_log.py +++ b/examples/recipes/request_id_log.py @@ -4,7 +4,7 @@ from my_app.context import ctx -def create_widget_object(name: str): +def create_widget_object(name: str) -> None: request_id = f'request_id={ctx.request_id}' logging.debug('%s going to create widget: %s', request_id, name) diff --git a/examples/recipes/request_id_middleware.py b/examples/recipes/request_id_middleware.py index e3c0fa928..a2e3d7852 100644 --- a/examples/recipes/request_id_middleware.py +++ b/examples/recipes/request_id_middleware.py @@ -3,12 +3,20 @@ # Import the above context.py from my_app.context import ctx +import falcon + class RequestIDMiddleware: - def process_request(self, req, resp): + def process_request(self, req: falcon.Request, resp: falcon.Response) -> None: request_id = str(uuid4()) ctx.request_id = request_id # It may also be helpful to include the ID in the response - def process_response(self, req, resp, resource, req_succeeded): + def process_response( + self, + req: falcon.Request, + resp: falcon.Response, + resource: object, + req_succeeded: bool, + ) -> None: resp.set_header('X-Request-ID', ctx.request_id) diff --git a/examples/recipes/request_id_structlog.py b/examples/recipes/request_id_structlog.py index 61b36fa83..ebb283245 100644 --- a/examples/recipes/request_id_structlog.py +++ b/examples/recipes/request_id_structlog.py @@ -3,9 +3,11 @@ # Optional logging package (pip install structlog) import structlog +import falcon + class RequestIDMiddleware: - def process_request(self, req, resp): + def process_request(self, req: falcon.Request, resp: falcon.Response) -> None: request_id = str(uuid4()) # Using Falcon 2.0+ context style @@ -15,5 +17,11 @@ def process_request(self, req, resp): req.context.log = structlog.get_logger(request_id=request_id) # It may also be helpful to include the ID in the response - def process_response(self, req, resp, resource, req_succeeded): + def process_response( + self, + req: falcon.Request, + resp: falcon.Response, + resource: object, + req_succeeded: bool, + ) -> None: resp.set_header('X-Request-ID', req.context.request_id)