Bläddra i källkod

handle default args

Khaleel Al-Adhami 4 månader sedan
förälder
incheckning
0d746bf762

+ 30 - 5
reflex/vars/function.py

@@ -1219,9 +1219,20 @@ class FunctionVar(
         args = tuple(map(LiteralVar.create, args))
         self._pre_check(*args)
         return_type = self._return_type(*args)
-        if arg_len == len(args) and isinstance(
-            self, (ArgsFunctionOperation, ArgsFunctionOperationBuilder)
-        ):
+        if isinstance(self, (ArgsFunctionOperation, ArgsFunctionOperationBuilder)):
+            default_args = self._default_args()
+            max_allowed_arguments = (
+                arg_len if arg_len is not None else len(args) + len(default_args)
+            )
+            provided_argument_count = len(args)
+
+            # we skip default args which we provided
+            default_args_provided = len(default_args) - (
+                max_allowed_arguments - provided_argument_count
+            )
+
+            full_args = args + tuple(default_args[default_args_provided:])
+
             if self._raw_js_function is not None:
                 return VarOperationCall.create(
                     FunctionStringVar.create(
@@ -1229,13 +1240,13 @@ class FunctionVar(
                         _var_type=self._var_type,
                         _var_data=self._get_all_var_data(),
                     ),
-                    *args,
+                    *full_args,
                     _var_type=return_type,
                 ).guess_type()
             if self._original_var_operation is not None:
                 return ExpressionCall.create(
                     self._original_var_operation,
-                    *args,
+                    *full_args,
                     _var_data=self._get_all_var_data(),
                     _var_type=return_type,
                 ).guess_type()
@@ -1316,6 +1327,20 @@ class FunctionVar(
             )
         return 0
 
+    def _default_args(self) -> list[Any]:
+        """Get the default arguments of the function.
+
+        Returns:
+            The default arguments of the function.
+        """
+        if isinstance(self, (ArgsFunctionOperation, ArgsFunctionOperationBuilder)):
+            return [
+                arg.default
+                for arg in self._default_values
+                if not isinstance(arg, inspect.Parameter.empty)
+            ]
+        return []
+
     def _return_type(self, *args: Var | Any) -> GenericType:
         """Override the type of the function call with the given arguments.
 

+ 1 - 4
tests/units/components/core/test_cond.py

@@ -21,10 +21,7 @@ def cond_state(request):
 def test_f_string_cond_interpolation():
     # make sure backticks inside interpolation don't get escaped
     var = LiteralVar.create(f"x {cond(True, 'a', 'b')}")
-    assert (
-        str(var)
-        == '("x "+(true ? "a" : "b"))'
-    )
+    assert str(var) == '("x "+(true ? "a" : "b"))'
 
 
 @pytest.mark.parametrize(

+ 2 - 2
tests/units/components/markdown/test_markdown.py

@@ -148,7 +148,7 @@ def test_create_map_fn_var_subclass(cls, fn_body, fn_args, explicit_return, expe
         (
             "code",
             {},
-            r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : '';   if (_language) {     (async () => {       try {         const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${_language}`);         SyntaxHighlighter.registerLanguage(_language, module.default);       } catch (error) {         console.error(`Error importing language module for ${_language}:`, error);       }     })();   }  ;             return inline ? (                 <RadixThemesCode {...props}>{children}</RadixThemesCode>             ) : (                 <SyntaxHighlighter children={((Array.isArray(children)) ? (((...args) => (((_array, _sep = "") => Array.prototype.join.apply(_array,[_sep]))(children, ...args)))("\n")) : children)} css={({ ["marginTop"] : "1em", ["marginBottom"] : "1em" })} customStyle={({ ["marginTop"] : "1em", ["marginBottom"] : "1em" })} language={_language} style={((resolvedColorMode === "light") ? oneLight : oneDark)} wrapLongLines={true} {...props}/>             );         })"""
+            r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : '';   if (_language) {     (async () => {       try {         const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${_language}`);         SyntaxHighlighter.registerLanguage(_language, module.default);       } catch (error) {         console.error(`Error importing language module for ${_language}:`, error);       }     })();   }  ;             return inline ? (                 <RadixThemesCode {...props}>{children}</RadixThemesCode>             ) : (                 <SyntaxHighlighter children={((Array.isArray(children)) ? (((...args) => (((_array, _sep = "") => Array.prototype.join.apply(_array,[_sep]))(children, ...args)))("\n")) : children)} css={({ ["marginTop"] : "1em", ["marginBottom"] : "1em" })} customStyle={({ ["marginTop"] : "1em", ["marginBottom"] : "1em" })} language={_language} style={((resolvedColorMode === "light") ? oneLight : oneDark)} wrapLongLines={true} {...props}/>             );         })""",
         ),
         (
             "code",
@@ -157,7 +157,7 @@ def test_create_map_fn_var_subclass(cls, fn_body, fn_args, explicit_return, expe
                     value, **props
                 )
             },
-            r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : '';  ;             return inline ? (                 <RadixThemesCode {...props}>{children}</RadixThemesCode>             ) : (                 <RadixThemesBox css={({ ["pre"] : ({ ["margin"] : "0", ["padding"] : "24px", ["background"] : "transparent", ["overflow-x"] : "auto", ["border-radius"] : "6px" }) })} {...props}><ShikiCode code={((Array.isArray(children)) ? (((...args) => (((_array, _sep = "") => Array.prototype.join.apply(_array,[_sep]))(children, ...args)))("\n")) : children)} decorations={[]} language={_language} theme={((resolvedColorMode === "light") ? "one-light" : "one-dark-pro")} transformers={[]}/></RadixThemesBox>             );         })"""
+            r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); const _language = match ? match[1] : '';  ;             return inline ? (                 <RadixThemesCode {...props}>{children}</RadixThemesCode>             ) : (                 <RadixThemesBox css={({ ["pre"] : ({ ["margin"] : "0", ["padding"] : "24px", ["background"] : "transparent", ["overflow-x"] : "auto", ["border-radius"] : "6px" }) })} {...props}><ShikiCode code={((Array.isArray(children)) ? (((...args) => (((_array, _sep = "") => Array.prototype.join.apply(_array,[_sep]))(children, ...args)))("\n")) : children)} decorations={[]} language={_language} theme={((resolvedColorMode === "light") ? "one-light" : "one-dark-pro")} transformers={[]}/></RadixThemesBox>             );         })""",
         ),
         (
             "h1",

+ 2 - 8
tests/units/test_var.py

@@ -1194,14 +1194,8 @@ def test_array_operations():
         str(array_var.reverse())
         == "(((...args) => (((_array) => _array.slice().reverse())([1, 2, 3, 4, 5], ...args)))())"
     )
-    assert (
-        str(ArrayVar.range(10))
-        == "(((_e1, _e2 = null, _step = 1) => [...range(_e1, _e2, _step)])(10))"
-    )
-    assert (
-        str(ArrayVar.range(1, 10))
-        == "(((_e1, _e2 = null, _step = 1) => [...range(_e1, _e2, _step)])(1, 10))"
-    )
+    assert str(ArrayVar.range(10)) == "[...range(10, null, 1)]"
+    assert str(ArrayVar.range(1, 10)) == "[...range(1, 10, 1)]"
     assert str(ArrayVar.range(1, 10, 2)) == "[...range(1, 10, 2)]"
     assert str(ArrayVar.range(1, 10, -1)) == "[...range(1, 10, -1)]"