Open pa-hqt opened 10 months ago
Oh shoot, I'm sorry you ran into this issue. I will release a hot-fix tonight to at least prevent this from crashing your component. Thanks again for the bug report.
Unfortunately, I cannot replicate this using Django 4.2.9 and Python 3.10.12. However, I added a catch for NameError
anyway in the hopes that it solves your problem. I also wrote a test to show that the key
for the dictionary is a class and not a string for me. 🤷 Maybe you can look at my test and see if it breaks for you? I'm curious what else might be going on.
My fix has been merged into main
and 0.58.1 has published (https://pypi.org/project/django-unicorn/). Please let me know if that solves your problem or if you are still running into an issue.
Thank you very much for providing this hotfix instantly! Yes, that helps me, because the component can be constructed without exception now.
I do not understand what is different with that component, I descriped above, than others that have similar class attribute definitions and worked without error. Also your new test case does not fail on my maschine. So this seams to be an issue of category "unpredictable".
But inspired by your test case, I wrote some more that pass with 0.58.1 and do not with 0.58.0. Maybe you should check, if that test expectations match your personal expectation what should happen in a component.
import datetime
from django_unicorn.components import UnicornView
from django_unicorn.typer import get_type_hints
def test_get_type_hints_gh_639_hint():
class MyComponentView(UnicornView):
a_date: datetime.date
expected = {"a_date": datetime.date}
actual = get_type_hints(MyComponentView(component_name="test", component_id="123"))
assert actual == expected
def test_get_type_hints_gh_639_hint_with_default():
class MyComponentView(UnicornView):
a_date: datetime.date = None
expected = {"a_date": datetime.date}
actual = get_type_hints(MyComponentView(component_name="test", component_id="123"))
assert actual == expected
def test_get_type_hints_gh_639_ref():
class MyComponentView(UnicornView):
a_date: "datetime.date"
expected = {}
actual = get_type_hints(MyComponentView(component_name="test", component_id="123"))
assert actual == expected
def test_get_type_hints_gh_639_ref_with_default():
class MyComponentView(UnicornView):
a_date: "datetime.date" = None
expected = {}
actual = get_type_hints(MyComponentView(component_name="test", component_id="123"))
assert actual == expected
def test_get_type_hints_gh_639_ref_with_kwarg():
class MyComponentView(UnicornView):
a_date: "datetime.date"
expected = {}
actual = get_type_hints(MyComponentView(component_name="test", component_id="123", a_date=datetime.date.fromisoformat("2024-01-05")))
assert actual == expected
def test_component_attribute_names_gh_639_hint():
class MyComponentView(UnicornView):
a_date: datetime.date
expected = ["a_date"]
actual = MyComponentView(component_name="test", component_id="123")._attribute_names()
assert actual == expected
def test_component_attribute_names_gh_639_hint_with_default():
class MyComponentView(UnicornView):
a_date: datetime.date = None
expected = ["a_date"]
actual = MyComponentView(component_name="test", component_id="123")._attribute_names()
assert actual == expected
def test_component_attribute_names_gh_639_ref():
class MyComponentView(UnicornView):
a_date: "datetime.date"
expected = []
actual = MyComponentView(component_name="test", component_id="123")._attribute_names()
assert actual == expected
def test_component_attribute_names_gh_639_ref_with_default():
class MyComponentView(UnicornView):
a_date: "datetime.date" = None
expected = ["a_date"]
actual = MyComponentView(component_name="test", component_id="123")._attribute_names()
assert actual == expected
def test_component_attribute_names_gh_639_ref_with_kwarg():
class MyComponentView(UnicornView):
a_date: "datetime.date"
expected = ["a_date"]
actual = MyComponentView(component_name="test", component_id="123", a_date=datetime.date.fromisoformat("2024-01-05"))._attribute_names()
assert actual == expected
Thanks for these test cases! Looking through them, I think there are some gaps in how unicorn deals with certain type annotations for sure.
One of my components crashes on page load due to recent type hint changes in
django_unicorn.components.unicorn_view.UnicornView._attribute_names()
of version 0.58.0 (commit 8a9448793)The head of my component looks like
Exception:
In
typing.get_type_hints()#L1859
the hints dictionary has following values:Since the values are strings, they are used to construct
ForwardRef
, but they cannot be solved, becauseglobalns
andlocalns
are empty.Any ideas, why the imports fail? May it be a solution to add NameError to catch block in django_unicorn.typer#L81?
(same happens with 'datetime' if I remove the type hint of my custom class 'AggregatSt')
I am using python 3.10, Django 4.2.9 and django-unicorn 0.58.0, here.