|
3 | 3 | import sys
|
4 | 4 | import warnings
|
5 | 5 | from abc import ABC, abstractmethod
|
| 6 | +from collections.abc import Sequence |
6 | 7 | from datetime import date, datetime, time
|
7 | 8 | from enum import Enum
|
8 | 9 | from functools import cached_property, partial
|
|
16 | 17 | from ..security import check, permissions_as_dict
|
17 | 18 | from ..types import ComponentState, InputState
|
18 | 19 |
|
| 20 | +if sys.version_info >= (3, 10): |
| 21 | + from typing import TypeAlias |
| 22 | +else: |
| 23 | + from typing_extensions import TypeAlias |
| 24 | + |
19 | 25 | if sys.version_info >= (3, 12):
|
20 | 26 | from typing import TypedDict
|
21 | 27 | else:
|
@@ -110,7 +116,7 @@ def __init__(self) -> None:
|
110 | 116 | if "id" in self.fields and self.primary_key != "id":
|
111 | 117 | warnings.warn("A non-PK 'id' column is likely to break the admin.", stacklevel=2)
|
112 | 118 |
|
113 |
| - d = {k: INPUT_TYPES.get(v["type"], str) for k, v in self.inputs.items()} |
| 119 | + d = {k: self._get_input_type(v) for k, v in self.inputs.items()} |
114 | 120 | # For runtime type checking only.
|
115 | 121 | self._record_type = TypedDict("RecordType", d, total=False) # type: ignore[misc]
|
116 | 122 |
|
@@ -313,6 +319,12 @@ async def _delete_many(self, request: web.Request) -> web.Response:
|
313 | 319 | raise web.HTTPNotFound()
|
314 | 320 | return json_response({"data": ids})
|
315 | 321 |
|
| 322 | + def _get_input_type(self, inp: InputState) -> TypeAlias: |
| 323 | + t = INPUT_TYPES.get(inp["type"], str) |
| 324 | + validators = inp.get("props", {}).get("validate", ()) |
| 325 | + assert isinstance(validators, Sequence) # noqa: S101 |
| 326 | + return t if any(v["name"] == "required" for v in validators) else Optional[t] |
| 327 | + |
316 | 328 | @cached_property
|
317 | 329 | def routes(self) -> tuple[web.RouteDef, ...]:
|
318 | 330 | """Routes to act on this resource.
|
|
0 commit comments