[REF-2682] Foreach over dict uses Tuple arg value (#3160)
* test_foreach: assert on arg _var_type * [REF-2682] Foreach over dict uses Tuple arg value When iterating over a Var with _var_type dict, the resulting arg value _var_type should be Tuple[key, value] so it can be correctly used with other var operations. Fix #3157 * Correct _var_type for iteration over Tuple of multiple types The arg value when iterating over a tuple could be any of the possible values mentioned in the annotation. When only one type is used, the Union collapses to the base type, at least in py3.11 * Add comments
This commit is contained in:
parent
ac36bfc6ea
commit
0a8aaea599
@ -2,7 +2,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
from typing import TYPE_CHECKING, Any, Callable, List, Type
|
from typing import TYPE_CHECKING, Any, Callable, List, Tuple, Type, Union, get_args
|
||||||
|
|
||||||
from reflex.components.tags.tag import Tag
|
from reflex.components.tags.tag import Tag
|
||||||
from reflex.vars import BaseVar, Var
|
from reflex.vars import BaseVar, Var
|
||||||
@ -33,11 +33,14 @@ class IterTag(Tag):
|
|||||||
The type of the iterable var.
|
The type of the iterable var.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return (
|
if self.iterable._var_type.mro()[0] == dict:
|
||||||
self.iterable._var_type
|
# Arg is a tuple of (key, value).
|
||||||
if self.iterable._var_type.mro()[0] == dict
|
return Tuple[get_args(self.iterable._var_type)] # type: ignore
|
||||||
else self.iterable._var_type.__args__[0]
|
elif self.iterable._var_type.mro()[0] == tuple:
|
||||||
)
|
# Arg is a union of any possible values in the tuple.
|
||||||
|
return Union[get_args(self.iterable._var_type)] # type: ignore
|
||||||
|
else:
|
||||||
|
return get_args(self.iterable._var_type)[0]
|
||||||
except Exception:
|
except Exception:
|
||||||
return Any
|
return Any
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
from typing import Dict, List, Set, Tuple
|
from typing import Dict, List, Set, Tuple, Union
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from reflex.components import box, foreach, text, theme
|
from reflex.components import box, foreach, text, theme
|
||||||
from reflex.components.core import Foreach
|
from reflex.components.core import Foreach
|
||||||
from reflex.state import BaseState
|
from reflex.state import BaseState
|
||||||
|
from reflex.vars import Var
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# When pydantic v2 is installed
|
# When pydantic v2 is installed
|
||||||
@ -39,29 +40,36 @@ class ForEachState(BaseState):
|
|||||||
)
|
)
|
||||||
colors_set: Set[str] = {"red", "green"}
|
colors_set: Set[str] = {"red", "green"}
|
||||||
bad_annotation_list: list = [["red", "orange"], ["yellow", "blue"]]
|
bad_annotation_list: list = [["red", "orange"], ["yellow", "blue"]]
|
||||||
|
color_index_tuple: Tuple[int, str] = (0, "red")
|
||||||
|
|
||||||
|
|
||||||
def display_color(color):
|
def display_color(color):
|
||||||
|
assert color._var_type == str
|
||||||
return box(text(color))
|
return box(text(color))
|
||||||
|
|
||||||
|
|
||||||
def display_color_name(color):
|
def display_color_name(color):
|
||||||
|
assert color._var_type == Dict[str, str]
|
||||||
return box(text(color["name"]))
|
return box(text(color["name"]))
|
||||||
|
|
||||||
|
|
||||||
def display_shade(color):
|
def display_shade(color):
|
||||||
|
assert color._var_type == Dict[str, List[str]]
|
||||||
return box(text(color["shades"][0]))
|
return box(text(color["shades"][0]))
|
||||||
|
|
||||||
|
|
||||||
def display_primary_colors(color):
|
def display_primary_colors(color):
|
||||||
|
assert color._var_type == Tuple[str, str]
|
||||||
return box(text(color[0]), text(color[1]))
|
return box(text(color[0]), text(color[1]))
|
||||||
|
|
||||||
|
|
||||||
def display_color_with_shades(color):
|
def display_color_with_shades(color):
|
||||||
|
assert color._var_type == Tuple[str, List[str]]
|
||||||
return box(text(color[0]), text(color[1][0]))
|
return box(text(color[0]), text(color[1][0]))
|
||||||
|
|
||||||
|
|
||||||
def display_nested_color_with_shades(color):
|
def display_nested_color_with_shades(color):
|
||||||
|
assert color._var_type == Tuple[str, Dict[str, List[Dict[str, str]]]]
|
||||||
return box(text(color[0]), text(color[1]["red"][0]["shade"]))
|
return box(text(color[0]), text(color[1]["red"][0]["shade"]))
|
||||||
|
|
||||||
|
|
||||||
@ -70,21 +78,31 @@ def show_shade(item):
|
|||||||
|
|
||||||
|
|
||||||
def display_nested_color_with_shades_v2(color):
|
def display_nested_color_with_shades_v2(color):
|
||||||
|
assert color._var_type == Tuple[str, Dict[str, List[Dict[str, str]]]]
|
||||||
return box(text(foreach(color[1], show_shade)))
|
return box(text(foreach(color[1], show_shade)))
|
||||||
|
|
||||||
|
|
||||||
def display_color_tuple(color):
|
def display_color_tuple(color):
|
||||||
|
assert color._var_type == str
|
||||||
return box(text(color, "tuple"))
|
return box(text(color, "tuple"))
|
||||||
|
|
||||||
|
|
||||||
def display_colors_set(color):
|
def display_colors_set(color):
|
||||||
|
assert color._var_type == str
|
||||||
return box(text(color, "set"))
|
return box(text(color, "set"))
|
||||||
|
|
||||||
|
|
||||||
def display_nested_list_element(element: str, index: int):
|
def display_nested_list_element(element: Var[str], index: Var[int]):
|
||||||
|
assert element._var_type == List[str]
|
||||||
|
assert index._var_type == int
|
||||||
return box(text(element[index]))
|
return box(text(element[index]))
|
||||||
|
|
||||||
|
|
||||||
|
def display_color_index_tuple(color):
|
||||||
|
assert color._var_type == Union[int, str]
|
||||||
|
return box(text(color, "index_tuple"))
|
||||||
|
|
||||||
|
|
||||||
seen_index_vars = set()
|
seen_index_vars = set()
|
||||||
|
|
||||||
|
|
||||||
@ -171,6 +189,14 @@ seen_index_vars = set()
|
|||||||
"iterable_type": "list",
|
"iterable_type": "list",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
ForEachState.color_index_tuple,
|
||||||
|
display_color_index_tuple,
|
||||||
|
{
|
||||||
|
"iterable_state": "for_each_state.color_index_tuple",
|
||||||
|
"iterable_type": "tuple",
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_foreach_render(state_var, render_fn, render_dict):
|
def test_foreach_render(state_var, render_fn, render_dict):
|
||||||
|
Loading…
Reference in New Issue
Block a user