From 773969a264d12dbf416889d9f0d27eccf0dec47e Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Thu, 6 Feb 2025 17:59:39 -0800 Subject: [PATCH] raise error when passing a str(var) --- reflex/components/base/bare.py | 29 +++++++++++++++++++++++++++++ reflex/config.py | 2 +- tests/units/test_var.py | 18 ++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/reflex/components/base/bare.py b/reflex/components/base/bare.py index 0f0bef8b9..47d7043a0 100644 --- a/reflex/components/base/bare.py +++ b/reflex/components/base/bare.py @@ -7,9 +7,33 @@ from typing import Any, Iterator from reflex.components.component import Component, LiteralComponentVar from reflex.components.tags import Tag from reflex.components.tags.tagless import Tagless +from reflex.config import PerformanceMode, environment +from reflex.utils import console from reflex.utils.imports import ParsedImportDict from reflex.vars import BooleanVar, ObjectVar, Var from reflex.vars.base import VarData +from reflex.vars.sequence import LiteralStringVar + + +def validate_str(value: str): + """Validate a string value. + + Args: + value: The value to validate. + + Raises: + ValueError: If the value is a Var and the performance mode is set to raise. + """ + perf_mode = environment.REFLEX_PERF_MODE.get() + if perf_mode != PerformanceMode.OFF and value.startswith("reflex___state"): + if perf_mode == PerformanceMode.WARN: + console.warn( + f"Output includes {value!s} which will be displayed as a string. If you are calling `str` on a Var, consider using .to_string() instead." + ) + elif perf_mode == PerformanceMode.RAISE: + raise ValueError( + f"Output includes {value!s} which will be displayed as a string. If you are calling `str` on a Var, consider using .to_string() instead." + ) class Bare(Component): @@ -28,9 +52,14 @@ class Bare(Component): The component. """ if isinstance(contents, Var): + if isinstance(contents, LiteralStringVar): + validate_str(contents._var_value) return cls(contents=contents) else: + if isinstance(contents, str): + validate_str(contents) contents = str(contents) if contents is not None else "" + return cls(contents=contents) def _get_all_hooks_internal(self) -> dict[str, VarData | None]: diff --git a/reflex/config.py b/reflex/config.py index f3d40dc37..7d26eaeba 100644 --- a/reflex/config.py +++ b/reflex/config.py @@ -563,7 +563,7 @@ class EnvironmentVariables: REFLEX_CHECK_LATEST_VERSION: EnvVar[bool] = env_var(True) # In which performance mode to run the app. - REFLEX_PERF_MODE: EnvVar[Optional[PerformanceMode]] = env_var(PerformanceMode.WARN) + REFLEX_PERF_MODE: EnvVar[PerformanceMode] = env_var(PerformanceMode.WARN) # The maximum size of the reflex state in kilobytes. REFLEX_STATE_SIZE_LIMIT: EnvVar[int] = env_var(1000) diff --git a/tests/units/test_var.py b/tests/units/test_var.py index a72242814..35feb03d7 100644 --- a/tests/units/test_var.py +++ b/tests/units/test_var.py @@ -8,6 +8,7 @@ from pandas import DataFrame import reflex as rx from reflex.base import Base +from reflex.config import PerformanceMode from reflex.constants.base import REFLEX_VAR_CLOSING_TAG, REFLEX_VAR_OPENING_TAG from reflex.state import BaseState from reflex.utils.exceptions import ( @@ -1893,3 +1894,20 @@ def test_var_data_hooks(): def test_var_data_with_hooks_value(): var_data = VarData(hooks={"what": VarData(hooks={"whot": VarData(hooks="whott")})}) assert var_data == VarData(hooks=["what", "whot", "whott"]) + + +def test_str_var_in_components(): + from reflex.config import environment + + current_performance_mode = environment.REFLEX_PERF_MODE.get() + environment.REFLEX_PERF_MODE.set(PerformanceMode.RAISE) + + class StateWithVar(rx.State): + field: int = 1 + + with pytest.raises(ValueError): + rx.vstack( + str(StateWithVar.field), + ) + + environment.REFLEX_PERF_MODE.set(current_performance_mode)