1 """Decorator for view methods to help with data validation."""
3 from __future__
import annotations
5 from collections.abc
import Awaitable, Callable, Coroutine
6 from functools
import wraps
7 from http
import HTTPStatus
9 from typing
import Any, Concatenate
11 from aiohttp
import web
12 import voluptuous
as vol
16 from .view
import HomeAssistantView
18 _LOGGER = logging.getLogger(__name__)
22 """Decorator that will validate the incoming data.
24 Takes in a voluptuous schema and adds 'data' as
25 keyword argument to the function call.
27 Will return a 400 if no JSON provided or doesn't match schema.
31 self, schema: VolDictType | vol.Schema, allow_empty: bool =
False
33 """Initialize the decorator."""
34 if isinstance(schema, dict):
35 schema = vol.Schema(schema)
40 def __call__[_HassViewT: HomeAssistantView, **_P](
43 Concatenate[_HassViewT, web.Request, dict[str, Any], _P],
44 Awaitable[web.Response],
47 Concatenate[_HassViewT, web.Request, _P],
48 Coroutine[Any, Any, web.Response],
50 """Decorate a function."""
54 view: _HassViewT, request: web.Request, *args: _P.args, **kwargs: _P.kwargs
56 """Wrap a request handler with data validation."""
59 raw_data = await request.json()
61 if not self.
_allow_empty_allow_empty
or (await request.content.read()) != b
"":
62 _LOGGER.error(
"Invalid JSON received")
63 return view.json_message(
"Invalid JSON.", HTTPStatus.BAD_REQUEST)
67 data: dict[str, Any] = self.
_schema_schema(raw_data)
68 except vol.Invalid
as err:
69 _LOGGER.error(
"Data does not match schema: %s", err)
70 return view.json_message(
71 f
"Message format incorrect: {err}", HTTPStatus.BAD_REQUEST
74 return await method(view, request, data, *args, **kwargs)
None __init__(self, VolDictType|vol.Schema schema, bool allow_empty=False)
web.Response wrapper(_HassViewT view, web.Request request, *_P.args args, **_P.kwargs kwargs)