From adfda8adfdf70f84140f73abf8754cde7e3a00da Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Thu, 12 Dec 2024 10:10:44 -0800 Subject: [PATCH] [ENG-4165] Consider default and default_factory for state vars (#4510) * [ENG-4165] Consider default and default_factory for state vars When determining whether a state var should be marked as optional, check that it is missing both default and default_factory and is not required. Fix #4471 * add test for default factory with rx.foreach (#4515) --------- Co-authored-by: benedikt-bartscher <31854409+benedikt-bartscher@users.noreply.github.com> --- reflex/state.py | 1 + tests/units/components/core/test_foreach.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/reflex/state.py b/reflex/state.py index f4a9d2d57..3e606bf57 100644 --- a/reflex/state.py +++ b/reflex/state.py @@ -1097,6 +1097,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow): if ( not field.required and field.default is None + and field.default_factory is None and not types.is_optional(prop._var_type) ): # Ensure frontend uses null coalescing when accessing. diff --git a/tests/units/components/core/test_foreach.py b/tests/units/components/core/test_foreach.py index 228165d3e..094f6029d 100644 --- a/tests/units/components/core/test_foreach.py +++ b/tests/units/components/core/test_foreach.py @@ -1,8 +1,10 @@ from typing import Dict, List, Set, Tuple, Union +import pydantic.v1 import pytest from reflex import el +from reflex.base import Base from reflex.components.component import Component from reflex.components.core.foreach import ( Foreach, @@ -18,6 +20,12 @@ from reflex.vars.number import NumberVar from reflex.vars.sequence import ArrayVar +class ForEachTag(Base): + """A tag for testing the ForEach component.""" + + name: str = "" + + class ForEachState(BaseState): """A state for testing the ForEach component.""" @@ -46,6 +54,8 @@ class ForEachState(BaseState): bad_annotation_list: list = [["red", "orange"], ["yellow", "blue"]] color_index_tuple: Tuple[int, str] = (0, "red") + default_factory_list: list[ForEachTag] = pydantic.v1.Field(default_factory=list) + class ComponentStateTest(ComponentState): """A test component state.""" @@ -290,3 +300,11 @@ def test_foreach_component_state(): ForEachState.colors_list, ComponentStateTest.create, ) + + +def test_foreach_default_factory(): + """Test that the default factory is called.""" + _ = Foreach.create( + ForEachState.default_factory_list, + lambda tag: text(tag.name), + )