From da39caa1cf27375b25f8c1c98f3d59c5f82eaaa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fred=20Lef=C3=A9v=C3=A8re-Laoide?= <90181748+FredLL-Avaiga@users.noreply.github.com> Date: Thu, 11 Jul 2024 13:49:20 +0200 Subject: [PATCH] support f-strings in lambda (#1505) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fred Lefévère-Laoide --- taipy/gui/builder/_element.py | 2 +- taipy/gui/gui.py | 6 ++++-- taipy/gui/utils/_evaluator.py | 10 ++++++---- tests/gui/builder/test_lambda.py | 16 ++++++++++++++++ 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/taipy/gui/builder/_element.py b/taipy/gui/builder/_element.py index 49d96e4dab..45a09bd73e 100644 --- a/taipy/gui/builder/_element.py +++ b/taipy/gui/builder/_element.py @@ -69,7 +69,7 @@ def update(self, **kwargs): def _evaluate_lambdas(self, gui: Gui): for k, lmbd in self._lambdas.items(): - expr = gui._evaluate_expr(f"{{{lmbd}}}") + expr = gui._evaluate_expr(lmbd, lambda_expr=True) gui._bind_var_val(k, _getscopeattr(gui, expr)) # Convert property value to string/function diff --git a/taipy/gui/gui.py b/taipy/gui/gui.py index 908337576e..abd8a1d2da 100644 --- a/taipy/gui/gui.py +++ b/taipy/gui/gui.py @@ -1612,8 +1612,10 @@ def _is_in_brdcst_callback(self): return False # Proxy methods for Evaluator - def _evaluate_expr(self, expr: str, lazy_declare: t.Optional[bool] = False) -> t.Any: - return self.__evaluator.evaluate_expr(self, expr, lazy_declare) + def _evaluate_expr( + self, expr: str, lazy_declare: t.Optional[bool] = False, lambda_expr: t.Optional[bool] = False + ) -> t.Any: + return self.__evaluator.evaluate_expr(self, expr, lazy_declare, lambda_expr) def _re_evaluate_expr(self, var_name: str) -> t.Set[str]: return self.__evaluator.re_evaluate_expr(self, var_name) diff --git a/taipy/gui/utils/_evaluator.py b/taipy/gui/utils/_evaluator.py index 70306994e9..7ada827584 100644 --- a/taipy/gui/utils/_evaluator.py +++ b/taipy/gui/utils/_evaluator.py @@ -210,15 +210,17 @@ def __evaluate_holder(self, gui: Gui, holder: t.Type[_TaipyBase], expr: str) -> _warn(f"Cannot evaluate expression {holder.__name__}({expr_hash},'{expr_hash}') for {expr}", e) return None - def evaluate_expr(self, gui: Gui, expr: str, lazy_declare: t.Optional[bool] = False) -> t.Any: - if not self._is_expression(expr): + def evaluate_expr( + self, gui: Gui, expr: str, lazy_declare: t.Optional[bool] = False, lambda_expr: t.Optional[bool] = False + ) -> t.Any: + if not self._is_expression(expr) and not lambda_expr: return expr - var_val, var_map = self._analyze_expression(gui, expr, lazy_declare) + var_val, var_map = ({}, {}) if lambda_expr else self._analyze_expression(gui, expr, lazy_declare) expr_hash = None is_edge_case = False # The expr_string is placed here in case expr get replaced by edge case - expr_string = 'f"' + expr.replace('"', '\\"') + '"' + expr_string = expr if lambda_expr else 'f"' + expr.replace('"', '\\"') + '"' # simplify expression if it only contains var_name m = _Evaluator.__EXPR_IS_EDGE_CASE.match(expr) if m and not _Evaluator.__EXPR_EDGE_CASE_F_STRING.match(expr): diff --git a/tests/gui/builder/test_lambda.py b/tests/gui/builder/test_lambda.py index 18637398ac..5af9da0cdf 100644 --- a/tests/gui/builder/test_lambda.py +++ b/tests/gui/builder/test_lambda.py @@ -31,3 +31,19 @@ def test_builder_lambda_2(gui: Gui, test_client, helpers): tgb.text(lambda message: str(message.get(key)), mode=lambda message: "mode " + str(message.get(key))) # type: ignore[attr-defined] # noqa: B023 expected_list = ['defaultValue="value A"', 'defaultValue="value B"', 'mode="mode value A"', 'mode="mode value B"'] helpers.test_control_builder(gui, page, expected_list) + +def test_builder_lambda_f_string(gui: Gui, test_client, helpers): + value = 10 + gui._bind_var_val("value", value) + with tgb.Page(frame=None) as page: + tgb.text(lambda value: f"value is {value}") # type: ignore[attr-defined] # noqa: B023 + expected_list = ['defaultValue="value is 10"'] + helpers.test_control_builder(gui, page, expected_list) + +def test_builder_simple_lambda(gui: Gui, test_client, helpers): + value = 10 + gui._bind_var_val("value", value) + with tgb.Page(frame=None) as page: + tgb.text(lambda value: value) # type: ignore[attr-defined] # noqa: B023 + expected_list = ['defaultValue="10"'] + helpers.test_control_builder(gui, page, expected_list)