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)