Skip to content

Commit

Permalink
Fix rejecting null on optional fields (#761)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dreamsorcerer authored Jul 31, 2023
1 parent 0ee079b commit ed98578
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
14 changes: 13 additions & 1 deletion aiohttp_admin/backends/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import sys
import warnings
from abc import ABC, abstractmethod
from collections.abc import Sequence
from datetime import date, datetime, time
from enum import Enum
from functools import cached_property, partial
Expand All @@ -16,6 +17,11 @@
from ..security import check, permissions_as_dict
from ..types import ComponentState, InputState

if sys.version_info >= (3, 10):
from typing import TypeAlias
else:
from typing_extensions import TypeAlias

if sys.version_info >= (3, 12):
from typing import TypedDict
else:
Expand Down Expand Up @@ -110,7 +116,7 @@ def __init__(self) -> None:
if "id" in self.fields and self.primary_key != "id":
warnings.warn("A non-PK 'id' column is likely to break the admin.", stacklevel=2)

d = {k: INPUT_TYPES.get(v["type"], str) for k, v in self.inputs.items()}
d = {k: self._get_input_type(v) for k, v in self.inputs.items()}
# For runtime type checking only.
self._record_type = TypedDict("RecordType", d, total=False) # type: ignore[misc]

Expand Down Expand Up @@ -313,6 +319,12 @@ async def _delete_many(self, request: web.Request) -> web.Response:
raise web.HTTPNotFound()
return json_response({"data": ids})

def _get_input_type(self, inp: InputState) -> TypeAlias:
t = INPUT_TYPES.get(inp["type"], str)
validators = inp.get("props", {}).get("validate", ())
assert isinstance(validators, Sequence) # noqa: S101
return t if any(v["name"] == "required" for v in validators) else Optional[t]

@cached_property
def routes(self) -> tuple[web.RouteDef, ...]:
"""Routes to act on this resource.
Expand Down
16 changes: 16 additions & 0 deletions tests/test_backends_abc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import json
from collections.abc import Awaitable, Callable

from aiohttp.test_utils import TestClient

_Login = Callable[[TestClient], Awaitable[dict[str, str]]]


async def test_create_with_null(admin_client: TestClient, login: _Login) -> None:
h = await login(admin_client)
assert admin_client.app
url = admin_client.app["admin"].router["dummy2_create"].url_for()
p = {"data": json.dumps({"msg": None})}
async with admin_client.post(url, params=p, headers=h) as resp:
assert resp.status == 200, await resp.text()
assert await resp.json() == {"data": {"id": 4, "msg": None}}

0 comments on commit ed98578

Please sign in to comment.