[REF-2682] Foreach over dict gets incorrect arg type
masenf opened this issue · comments
Masen Furer commented
Describe the bug
The arg var resulting from iterating over a Var of type dict should be a tuple of the key and value types. But it's actually just the same type as the Var itself.
To Reproduce
import reflex as rx
class MyState(rx.State):
labels: dict[str, str] = {
"A": "Alpha",
"a": "alpha",
"b": "beta",
}
some_values: dict[str, str] = {
"A": "a",
}
some_values_dict: dict[str, list[str]] = {
"A": ["a", "b"],
}
def make_nice_label(entry: list[str, str]) -> rx.Component:
key = entry[0]
value = entry[1]
print(repr(entry), repr(key), repr(value))
labels = MyState.labels
return rx.vstack(rx.heading(labels[key]), rx.text(labels[value]))
def make_nice_label_dict(entry: list[str, str]) -> rx.Component:
key = entry[0]
values = entry[1]
print(repr(entry), repr(key), repr(values))
labels = MyState.labels
return rx.vstack(
rx.heading(labels[key]),
rx.foreach(
values,
lambda value: rx.text(labels[value]),
),
)
@rx.page(route="/")
def index() -> rx.Component:
return rx.foreach(
MyState.some_values,
make_nice_label,
), rx.foreach(
MyState.some_values_dict,
make_nice_label_dict,
)
app = rx.App()
Expected behavior
Should display
Alpha
alpha
Alpha
alpha
beta
Should print
BaseVar(_var_name='entry', _var_type=typing.Tuple[str, str], _var_is_local=False, _var_is_string=False, _var_full_name_needs_state_prefix=False, _var_data=None) BaseVar(_var_name='entry.at(0)', _var_type=<class 'str'>, _var_is_local=False, _var_is_string=False, _var_full_name_needs_state_prefix=False, _var_data=None) BaseVar(_var_name='entry.at(1)', _var_type=<class 'str'>, _var_is_local=False, _var_is_string=False, _var_full_name_needs_state_prefix=False, _var_data=None)
BaseVar(_var_name='entry', _var_type=typing.Tuple[str, list[str]], _var_is_local=False, _var_is_string=False, _var_full_name_needs_state_prefix=False, _var_data=None) BaseVar(_var_name='entry.at(0)', _var_type=<class 'str'>, _var_is_local=False, _var_is_string=False, _var_full_name_needs_state_prefix=False, _var_data=None) BaseVar(_var_name='entry.at(1)', _var_type=list[str], _var_is_local=False, _var_is_string=False, _var_full_name_needs_state_prefix=False, _var_data=None)
Instead, it crashes:
BaseVar(_var_name='entry', _var_type=dict[str, str], _var_is_local=False, _var_is_string=False, _var_full_name_needs_state_prefix=False, _var_data=None) BaseVar(_var_name='entry[0]', _var_type=<class 'str'>, _var_is_local=False, _var_is_string=False, _var_full_name_needs_state_prefix=False, _var_data=None) BaseVar(_var_name='entry[1]', _var_type=<class 'str'>, _var_is_local=False, _var_is_string=False, _var_full_name_needs_state_prefix=False, _var_data=None)
BaseVar(_var_name='entry', _var_type=dict[str, list[str]], _var_is_local=False, _var_is_string=False, _var_full_name_needs_state_prefix=False, _var_data=None) BaseVar(_var_name='entry[0]', _var_type=list[str], _var_is_local=False, _var_is_string=False, _var_full_name_needs_state_prefix=False, _var_data=None) BaseVar(_var_name='entry[1]', _var_type=list[str], _var_is_local=False, _var_is_string=False, _var_full_name_needs_state_prefix=False, _var_data=None)
Traceback (most recent call last):
File "/Users/masen/code/reflex-dev/VENV-dev311/bin/reflex", line 8, in <module>
sys.exit(cli())
^^^^^
File "/Users/masen/code/reflex-dev/VENV-dev311/lib/python3.11/site-packages/typer/main.py", line 326, in __call__
raise e
File "/Users/masen/code/reflex-dev/VENV-dev311/lib/python3.11/site-packages/typer/main.py", line 309, in __call__
return get_command(self)(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/masen/code/reflex-dev/VENV-dev311/lib/python3.11/site-packages/click/core.py", line 1157, in __call__
return self.main(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/masen/code/reflex-dev/VENV-dev311/lib/python3.11/site-packages/typer/core.py", line 723, in main
return _main(
^^^^^^
File "/Users/masen/code/reflex-dev/VENV-dev311/lib/python3.11/site-packages/typer/core.py", line 193, in _main
rv = self.invoke(ctx)
^^^^^^^^^^^^^^^^
File "/Users/masen/code/reflex-dev/VENV-dev311/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/masen/code/reflex-dev/VENV-dev311/lib/python3.11/site-packages/click/core.py", line 1434, in invoke
return ctx.invoke(self.callback, **ctx.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/masen/code/reflex-dev/VENV-dev311/lib/python3.11/site-packages/click/core.py", line 783, in invoke
return __callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/masen/code/reflex-dev/VENV-dev311/lib/python3.11/site-packages/typer/main.py", line 688, in wrapper
return callback(**use_params)
^^^^^^^^^^^^^^^^^^^^^^
File "/Users/masen/code/reflex-dev/reflex/reflex/reflex.py", line 256, in run
_run(env, frontend, backend, frontend_port, backend_port, backend_host, loglevel)
File "/Users/masen/code/reflex-dev/reflex/reflex/reflex.py", line 182, in _run
prerequisites.get_compiled_app()
File "/Users/masen/code/reflex-dev/reflex/reflex/utils/prerequisites.py", line 242, in get_compiled_app
app._apply_decorated_pages()
File "/Users/masen/code/reflex-dev/reflex/reflex/app.py", line 735, in _apply_decorated_pages
self.add_page(render, **kwargs)
File "/Users/masen/code/reflex-dev/reflex/reflex/app.py", line 455, in add_page
component = self._generate_component(component)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/masen/code/reflex-dev/reflex/reflex/app.py", line 406, in _generate_component
raise e
File "/Users/masen/code/reflex-dev/reflex/reflex/app.py", line 395, in _generate_component
return component if isinstance(component, Component) else component()
^^^^^^^^^^^
File "/Users/masen/code/reflex-dev/repro-complex-indexing/repro_complex_indexing/repro_complex_indexing.py", line 46, in index
), rx.foreach(
^^^^^^^^^^^
File "/Users/masen/code/reflex-dev/reflex/reflex/components/core/foreach.py", line 64, in create
component._render(props=dict(index_var_name="i")).render_component()
File "/Users/masen/code/reflex-dev/reflex/reflex/components/tags/iter_tag.py", line 117, in render_component
component = self.render_fn(arg)
^^^^^^^^^^^^^^^^^^^
File "/Users/masen/code/reflex-dev/repro-complex-indexing/repro_complex_indexing/repro_complex_indexing.py", line 33, in make_nice_label_dict
rx.heading(labels[key]),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^
File "/Users/masen/code/reflex-dev/reflex/reflex/vars.py", line 661, in __getitem__
raise TypeError(
TypeError: Index must be one of the following types: int, str, int or str Var
Specifics (please complete the following information):
- Python Version: 3.11.8
- Reflex Version: 0.4.9
- OS: macOS 14
- Browser (Optional):
Additional context
In IterTag.get_iterable_var_type
, we could use Tuple[self.iterable._var_type.__args__[0], self.iterable._var_type.__args__[1]]
if the _var_type is dict
From SyncLinear.com | REF-2682