diff --git a/reflex/components/base/bare.py b/reflex/components/base/bare.py index 47d7043a0..24a3b9f6a 100644 --- a/reflex/components/base/bare.py +++ b/reflex/components/base/bare.py @@ -9,12 +9,23 @@ 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.decorator import once 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 +@once +def performace_mode(): + """Get the performance mode. + + Returns: + The performance mode. + """ + return environment.REFLEX_PERF_MODE.get() + + def validate_str(value: str): """Validate a string value. @@ -24,7 +35,7 @@ def validate_str(value: str): Raises: ValueError: If the value is a Var and the performance mode is set to raise. """ - perf_mode = environment.REFLEX_PERF_MODE.get() + perf_mode = performace_mode() if perf_mode != PerformanceMode.OFF and value.startswith("reflex___state"): if perf_mode == PerformanceMode.WARN: console.warn( diff --git a/reflex/utils/decorator.py b/reflex/utils/decorator.py new file mode 100644 index 000000000..5c9c0bf3a --- /dev/null +++ b/reflex/utils/decorator.py @@ -0,0 +1,25 @@ +"""Decorator utilities.""" + +from typing import Callable, TypeVar + +T = TypeVar("T") + + +def once(f: Callable[[], T]) -> Callable[[], T]: + """A decorator that calls the function once and caches the result. + + Args: + f: The function to call. + + Returns: + A function that calls the function once and caches the result. + """ + unset = object() + value: object | T = unset + + def wrapper() -> T: + nonlocal value + value = f() if value is unset else value + return value # pyright: ignore[reportReturnType] + + return wrapper diff --git a/tests/units/test_var.py b/tests/units/test_var.py index 35feb03d7..ff29d4290 100644 --- a/tests/units/test_var.py +++ b/tests/units/test_var.py @@ -1896,18 +1896,25 @@ def test_var_data_with_hooks_value(): 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) - +def test_str_var_in_components(mocker): class StateWithVar(rx.State): field: int = 1 + mocker.patch( + "reflex.components.base.bare.performace_mode", + lambda: PerformanceMode.RAISE, + ) + with pytest.raises(ValueError): rx.vstack( str(StateWithVar.field), ) - environment.REFLEX_PERF_MODE.set(current_performance_mode) + mocker.patch( + "reflex.components.base.bare.performace_mode", + lambda: PerformanceMode.OFF, + ) + + rx.vstack( + str(StateWithVar.field), + )