Explorar o código

support f-strings in lambda (#1505)

Co-authored-by: Fred Lefévère-Laoide <Fred.Lefevere-Laoide@Taipy.io>
Fred Lefévère-Laoide hai 10 meses
pai
achega
da39caa1cf

+ 1 - 1
taipy/gui/builder/_element.py

@@ -69,7 +69,7 @@ class _Element(ABC):
 
     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

+ 4 - 2
taipy/gui/gui.py

@@ -1612,8 +1612,10 @@ class Gui:
             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)

+ 6 - 4
taipy/gui/utils/_evaluator.py

@@ -210,15 +210,17 @@ class _Evaluator:
             _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):

+ 16 - 0
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)