-
-
Notifications
You must be signed in to change notification settings - Fork 131
Description
Bug Description
If I inherit from a base class the method typer.get_type_hints does not include the type hints of the properties that are defined in the base class. As a result, the properties are not casted to correct data type when used with unicorn:model="property" in template.
In my case it was an HTML select, where the option values are numerical IDs that are always transmitted as strings and should be converted in the unicorn component.
Suggested fix: change line type_hints = typing_get_type_hints(obj) in django_unicorn.typer.get_type_hints to
if hasattr(obj, "__class__"):
# Should be called with class object (instead of instance) to get type hints of parent classes. From docs:
# "If obj is a class C, the function returns a dictionary that merges annotations from C’s base classes with those on C directly.
# This is done by traversing C.__mro__ and iteratively combining __annotations__ dictionaries." (https://docs.python.org/3/library/typing.html#typing.get_type_hints)
type_hints = typing_get_type_hints(obj.__class__)
else:
type_hints = typing_get_type_hints(obj)External references:
https://discuss.python.org/t/behavior-of-get-type-hints-differs-on-classes-and-instances/70491
https://docs.python.org/3/library/typing.html#typing.get_type_hints
Expected behaviour
If I have defined data type hints in a base class of my current view, these type hints should be considered when the property, that is defined in the base class, is set in child view via the unicorn:model mechanism. (at least for primitive data types)
Screenshots / Screenrecords
N/A
Steps to reproduce
from django_unicorn.components import UnicornView
from django_unicorn.typer import get_type_hints
class BaseView(UnicornView):
base_property: int = 0
class ChildView(BaseView):
child_property: int = 0
# Tests that fail
def test_set_property_value_with_casting():
view = ChildView(component_name="test", component_id="test_get_type_hints_base_class")
view._set_property("child_property", "1") # value is transmitted as string, but should be an int
assert view.child_property == 1, "child_property should be of type int and have value 1" # works as expected
view._set_property("base_property", "1") # value is transmitted as string, but should be an int
assert view.base_property == 1, "base_property should be of type int and have value 1" # fails, because no type hint is returned for the base class properties
def test_get_type_hints_base_class():
expected = {"base_property": int, "child_property": str}
actual = get_type_hints(ChildView(component_name="test", component_id="test_get_type_hints_base_class"))
assert actual == expected
What browsers are you seeing the problem on?
No response
👀 Have you checked for similar open issues?
- I checked and didn't find similar issue
Code of Conduct
- I agree to follow this project's Code of Conduct
Are you willing to work on this issue ?
No, someone else can work on it