Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential fix for #647 #649

Merged
merged 5 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions django_unicorn/typer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
parse_duration,
parse_time,
)
from pydantic import BaseModel

from django_unicorn.typing import QuerySetType

Expand Down Expand Up @@ -140,6 +141,9 @@ def cast_value(type_hint, value):
if issubclass(type_hint, Model):
continue

if issubclass(type_hint, BaseModel) or is_dataclass(type_hint):
value = type_hint(**value)
break
value = type_hint(value)
break

Expand Down
61 changes: 60 additions & 1 deletion tests/test_typer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from dataclasses import dataclass
import datetime
from typing import Optional
from typing import List, Optional
from typing import get_type_hints as typing_get_type_hints

from pydantic import BaseModel

from django_unicorn.components import UnicornView
from django_unicorn.typer import cast_attribute_value, cast_value, get_type_hints
from example.coffee.models import Flavor
Expand Down Expand Up @@ -111,3 +114,59 @@ def test_cast_value_model_int():
actual = cast_value(type_hint, 1)

assert actual == 1


@dataclass
class TestDataClass:
name: str


class PydanticDataClass(BaseModel):
name: str


class AnotherExampleClass:
data: TestDataClass
list_data: List[TestDataClass]
pydantic_data: PydanticDataClass
pydantic_list_data: List[PydanticDataClass]


def test_cast_value_dataclass():
example_class = AnotherExampleClass()
test_data = TestDataClass(name="foo")
example_class.data = test_data
type_hints = typing_get_type_hints(example_class)
type_hint = type_hints["data"]
actual = cast_value(type_hint, {"name": "foo"})
assert actual == test_data


def test_cast_value_pydantic():
example_class = AnotherExampleClass()
test_data = PydanticDataClass(name="foo")
example_class.pydantic_data = test_data
type_hints = typing_get_type_hints(example_class)
type_hint = type_hints["pydantic_data"]
actual = cast_value(type_hint, {"name": "foo"})
assert actual == test_data


def test_cast_value_list_dataclass():
example_class = AnotherExampleClass()
test_data = TestDataClass(name="foo")
example_class.pydantic_list_data = [test_data]
type_hints = typing_get_type_hints(example_class)
type_hint = type_hints["list_data"]
actual = cast_value(type_hint, [{"name": "foo"}])
assert actual == [test_data]


def test_cast_value_list_pydantic():
example_class = AnotherExampleClass()
test_data = PydanticDataClass(name="foo")
example_class.pydantic_list_data = [test_data]
type_hints = typing_get_type_hints(example_class)
type_hint = type_hints["pydantic_list_data"]
actual = cast_value(type_hint, [{"name": "foo"}])
assert actual == [test_data]