diff --git a/reflex/vars/base.py b/reflex/vars/base.py index 8dab07f86d6..97a2f975289 100644 --- a/reflex/vars/base.py +++ b/reflex/vars/base.py @@ -1135,17 +1135,14 @@ def _as_ref(self) -> Var: Returns: The reference to the var. """ - from .object import ObjectVar - - refs = Var( - _js_expr="refs", + return Var( + _js_expr=f"refs[{Var.create(str(self))}]", _var_data=VarData( imports={ f"$/{constants.Dirs.STATE_PATH}": [imports.ImportVar(tag="refs")] } ), - ).to(ObjectVar, Mapping[str, str]) - return refs[LiteralVar.create(str(self))] + ).to(str) def js_type(self) -> StringVar: """Returns the javascript type of the object. diff --git a/reflex/vars/object.py b/reflex/vars/object.py index ff7323f49d9..c068eb40a35 100644 --- a/reflex/vars/object.py +++ b/reflex/vars/object.py @@ -557,9 +557,7 @@ def _cached_var_name(self) -> str: Returns: The name of the operation. """ - if types.is_optional(self._object._var_type): - return f"{self._object!s}?.[{self._key!s}]" - return f"{self._object!s}[{self._key!s}]" + return f"{self._object!s}?.[{self._key!s}]" @classmethod def create( diff --git a/reflex/vars/sequence.py b/reflex/vars/sequence.py index 1e958cc4f3e..dc9018dd0c3 100644 --- a/reflex/vars/sequence.py +++ b/reflex/vars/sequence.py @@ -1056,7 +1056,7 @@ def string_item_operation(string: StringVar[Any], index: NumberVar | int): Returns: The item from the string. """ - return var_operation_return(js_expression=f"{string}.at({index})", var_type=str) + return var_operation_return(js_expression=f"{string}?.at?.({index})", var_type=str) @var_operation @@ -1619,7 +1619,7 @@ def array_item_operation(array: ArrayVar, index: NumberVar | int): ) return var_operation_return( - js_expression=f"{array!s}.at({index!s})", + js_expression=f"{array!s}?.at?.({index!s})", var_type=element_type, ) diff --git a/tests/units/test_app.py b/tests/units/test_app.py index 4fec88ef9cc..d77c9f804e7 100644 --- a/tests/units/test_app.py +++ b/tests/units/test_app.py @@ -1373,8 +1373,8 @@ def test_app_wrap_compile_theme( "return (" + ("jsx(StrictMode,{}," if react_strict_mode else "") + "jsx(ErrorBoundary,{" - """fallbackRender:((event_args) => (jsx("div", ({css:({ ["height"] : "100%", ["width"] : "100%", ["position"] : "absolute", ["backgroundColor"] : "#fff", ["color"] : "#000", ["display"] : "flex", ["alignItems"] : "center", ["justifyContent"] : "center" })}), (jsx("div", ({css:({ ["display"] : "flex", ["flexDirection"] : "column", ["gap"] : "1rem" })}), (jsx("div", ({css:({ ["display"] : "flex", ["flexDirection"] : "column", ["gap"] : "1rem", ["maxWidth"] : "50ch", ["border"] : "1px solid #888888", ["borderRadius"] : "0.25rem", ["padding"] : "1rem" })}), (jsx("h2", ({css:({ ["fontSize"] : "1.25rem", ["fontWeight"] : "bold" })}), "An error occurred while rendering this page.")), (jsx("p", ({css:({ ["opacity"] : "0.75" })}), "This is an error with the application itself.")), (jsx("details", ({}), (jsx("summary", ({css:({ ["padding"] : "0.5rem" })}), "Error message")), (jsx("div", ({css:({ ["width"] : "100%", ["maxHeight"] : "50vh", ["overflow"] : "auto", ["background"] : "#000", ["color"] : "#fff", ["borderRadius"] : "0.25rem" })}), (jsx("div", ({css:({ ["padding"] : "0.5rem", ["width"] : "fit-content" })}), (jsx("pre", ({}), event_args.error.name + \': \' + event_args.error.message + \'\\n\' + event_args.error.stack)))))), (jsx("button", ({css:({ ["padding"] : "0.35rem 0.75rem", ["margin"] : "0.5rem", ["background"] : "#fff", ["color"] : "#000", ["border"] : "1px solid #000", ["borderRadius"] : "0.25rem", ["fontWeight"] : "bold" }),onClick:((_e) => (addEvents([(ReflexEvent("_call_function", ({ ["function"] : (() => (navigator["clipboard"]["writeText"](event_args.error.name + \': \' + event_args.error.message + \'\\n\' + event_args.error.stack))), ["callback"] : null }), ({ })))], [_e], ({ }))))}), "Copy")))))), (jsx("hr", ({css:({ ["borderColor"] : "currentColor", ["opacity"] : "0.25" })}))), (jsx(ReactRouterLink, ({to:"https://reflex.dev"}), (jsx("div", ({css:({ ["display"] : "flex", ["alignItems"] : "baseline", ["justifyContent"] : "center", ["fontFamily"] : "monospace", ["--default-font-family"] : "monospace", ["gap"] : "0.5rem" })}), "Built with ", (jsx("svg", ({"aria-label":"Reflex",css:({ ["fill"] : "currentColor" }),height:"12",role:"img",width:"56",xmlns:"http://www.w3.org/2000/svg"}), (jsx("path", ({d:"M0 11.5999V0.399902H8.96V4.8799H6.72V2.6399H2.24V4.8799H6.72V7.1199H2.24V11.5999H0ZM6.72 11.5999V7.1199H8.96V11.5999H6.72Z"}))), (jsx("path", ({d:"M11.2 11.5999V0.399902H17.92V2.6399H13.44V4.8799H17.92V7.1199H13.44V9.3599H17.92V11.5999H11.2Z"}))), (jsx("path", ({d:"M20.16 11.5999V0.399902H26.88V2.6399H22.4V4.8799H26.88V7.1199H22.4V11.5999H20.16Z"}))), (jsx("path", ({d:"M29.12 11.5999V0.399902H31.36V9.3599H35.84V11.5999H29.12Z"}))), (jsx("path", ({d:"M38.08 11.5999V0.399902H44.8V2.6399H40.32V4.8799H44.8V7.1199H40.32V9.3599H44.8V11.5999H38.08Z"}))), (jsx("path", ({d:"M47.04 4.8799V0.399902H49.28V4.8799H47.04ZM53.76 4.8799V0.399902H56V4.8799H53.76ZM49.28 7.1199V4.8799H53.76V7.1199H49.28ZM47.04 11.5999V7.1199H49.28V11.5999H47.04ZM53.76 11.5999V7.1199H56V11.5999H53.76Z"}))), (jsx("title", ({}), "Reflex"))))))))))))),""" - """onError:((_error, _info) => (addEvents([(ReflexEvent("reflex___state____state.reflex___state____frontend_event_exception_state.handle_frontend_exception", ({ ["info"] : ((((_error["name"]+": ")+_error["message"])+"\\n")+_error["stack"]), ["component_stack"] : _info["componentStack"] }), ({ })))], [_error, _info], ({ }))))""" + """fallbackRender:((event_args) => (jsx("div", ({css:({ ["height"] : "100%", ["width"] : "100%", ["position"] : "absolute", ["backgroundColor"] : "#fff", ["color"] : "#000", ["display"] : "flex", ["alignItems"] : "center", ["justifyContent"] : "center" })}), (jsx("div", ({css:({ ["display"] : "flex", ["flexDirection"] : "column", ["gap"] : "1rem" })}), (jsx("div", ({css:({ ["display"] : "flex", ["flexDirection"] : "column", ["gap"] : "1rem", ["maxWidth"] : "50ch", ["border"] : "1px solid #888888", ["borderRadius"] : "0.25rem", ["padding"] : "1rem" })}), (jsx("h2", ({css:({ ["fontSize"] : "1.25rem", ["fontWeight"] : "bold" })}), "An error occurred while rendering this page.")), (jsx("p", ({css:({ ["opacity"] : "0.75" })}), "This is an error with the application itself.")), (jsx("details", ({}), (jsx("summary", ({css:({ ["padding"] : "0.5rem" })}), "Error message")), (jsx("div", ({css:({ ["width"] : "100%", ["maxHeight"] : "50vh", ["overflow"] : "auto", ["background"] : "#000", ["color"] : "#fff", ["borderRadius"] : "0.25rem" })}), (jsx("div", ({css:({ ["padding"] : "0.5rem", ["width"] : "fit-content" })}), (jsx("pre", ({}), event_args.error.name + \': \' + event_args.error.message + \'\\n\' + event_args.error.stack)))))), (jsx("button", ({css:({ ["padding"] : "0.35rem 0.75rem", ["margin"] : "0.5rem", ["background"] : "#fff", ["color"] : "#000", ["border"] : "1px solid #000", ["borderRadius"] : "0.25rem", ["fontWeight"] : "bold" }),onClick:((_e) => (addEvents([(ReflexEvent("_call_function", ({ ["function"] : (() => (navigator?.["clipboard"]?.["writeText"](event_args.error.name + \': \' + event_args.error.message + \'\\n\' + event_args.error.stack))), ["callback"] : null }), ({ })))], [_e], ({ }))))}), "Copy")))))), (jsx("hr", ({css:({ ["borderColor"] : "currentColor", ["opacity"] : "0.25" })}))), (jsx(ReactRouterLink, ({to:"https://reflex.dev"}), (jsx("div", ({css:({ ["display"] : "flex", ["alignItems"] : "baseline", ["justifyContent"] : "center", ["fontFamily"] : "monospace", ["--default-font-family"] : "monospace", ["gap"] : "0.5rem" })}), "Built with ", (jsx("svg", ({"aria-label":"Reflex",css:({ ["fill"] : "currentColor" }),height:"12",role:"img",width:"56",xmlns:"http://www.w3.org/2000/svg"}), (jsx("path", ({d:"M0 11.5999V0.399902H8.96V4.8799H6.72V2.6399H2.24V4.8799H6.72V7.1199H2.24V11.5999H0ZM6.72 11.5999V7.1199H8.96V11.5999H6.72Z"}))), (jsx("path", ({d:"M11.2 11.5999V0.399902H17.92V2.6399H13.44V4.8799H17.92V7.1199H13.44V9.3599H17.92V11.5999H11.2Z"}))), (jsx("path", ({d:"M20.16 11.5999V0.399902H26.88V2.6399H22.4V4.8799H26.88V7.1199H22.4V11.5999H20.16Z"}))), (jsx("path", ({d:"M29.12 11.5999V0.399902H31.36V9.3599H35.84V11.5999H29.12Z"}))), (jsx("path", ({d:"M38.08 11.5999V0.399902H44.8V2.6399H40.32V4.8799H44.8V7.1199H40.32V9.3599H44.8V11.5999H38.08Z"}))), (jsx("path", ({d:"M47.04 4.8799V0.399902H49.28V4.8799H47.04ZM53.76 4.8799V0.399902H56V4.8799H53.76ZM49.28 7.1199V4.8799H53.76V7.1199H49.28ZM47.04 11.5999V7.1199H49.28V11.5999H47.04ZM53.76 11.5999V7.1199H56V11.5999H53.76Z"}))), (jsx("title", ({}), "Reflex"))))))))))))),""" + """onError:((_error, _info) => (addEvents([(ReflexEvent("reflex___state____state.reflex___state____frontend_event_exception_state.handle_frontend_exception", ({ ["info"] : ((((_error?.["name"]+": ")+_error?.["message"])+"\\n")+_error?.["stack"]), ["component_stack"] : _info?.["componentStack"] }), ({ })))], [_error, _info], ({ }))))""" "}," "jsx(RadixThemesColorModeProvider,{}," "jsx(Fragment,{}," @@ -1447,8 +1447,8 @@ def page(): + ("jsx(StrictMode,{}," if react_strict_mode else "") + "jsx(RadixThemesBox,{}," "jsx(ErrorBoundary,{" - """fallbackRender:((event_args) => (jsx("div", ({css:({ ["height"] : "100%", ["width"] : "100%", ["position"] : "absolute", ["backgroundColor"] : "#fff", ["color"] : "#000", ["display"] : "flex", ["alignItems"] : "center", ["justifyContent"] : "center" })}), (jsx("div", ({css:({ ["display"] : "flex", ["flexDirection"] : "column", ["gap"] : "1rem" })}), (jsx("div", ({css:({ ["display"] : "flex", ["flexDirection"] : "column", ["gap"] : "1rem", ["maxWidth"] : "50ch", ["border"] : "1px solid #888888", ["borderRadius"] : "0.25rem", ["padding"] : "1rem" })}), (jsx("h2", ({css:({ ["fontSize"] : "1.25rem", ["fontWeight"] : "bold" })}), "An error occurred while rendering this page.")), (jsx("p", ({css:({ ["opacity"] : "0.75" })}), "This is an error with the application itself.")), (jsx("details", ({}), (jsx("summary", ({css:({ ["padding"] : "0.5rem" })}), "Error message")), (jsx("div", ({css:({ ["width"] : "100%", ["maxHeight"] : "50vh", ["overflow"] : "auto", ["background"] : "#000", ["color"] : "#fff", ["borderRadius"] : "0.25rem" })}), (jsx("div", ({css:({ ["padding"] : "0.5rem", ["width"] : "fit-content" })}), (jsx("pre", ({}), event_args.error.name + \': \' + event_args.error.message + \'\\n\' + event_args.error.stack)))))), (jsx("button", ({css:({ ["padding"] : "0.35rem 0.75rem", ["margin"] : "0.5rem", ["background"] : "#fff", ["color"] : "#000", ["border"] : "1px solid #000", ["borderRadius"] : "0.25rem", ["fontWeight"] : "bold" }),onClick:((_e) => (addEvents([(ReflexEvent("_call_function", ({ ["function"] : (() => (navigator["clipboard"]["writeText"](event_args.error.name + \': \' + event_args.error.message + \'\\n\' + event_args.error.stack))), ["callback"] : null }), ({ })))], [_e], ({ }))))}), "Copy")))))), (jsx("hr", ({css:({ ["borderColor"] : "currentColor", ["opacity"] : "0.25" })}))), (jsx(ReactRouterLink, ({to:"https://reflex.dev"}), (jsx("div", ({css:({ ["display"] : "flex", ["alignItems"] : "baseline", ["justifyContent"] : "center", ["fontFamily"] : "monospace", ["--default-font-family"] : "monospace", ["gap"] : "0.5rem" })}), "Built with ", (jsx("svg", ({"aria-label":"Reflex",css:({ ["fill"] : "currentColor" }),height:"12",role:"img",width:"56",xmlns:"http://www.w3.org/2000/svg"}), (jsx("path", ({d:"M0 11.5999V0.399902H8.96V4.8799H6.72V2.6399H2.24V4.8799H6.72V7.1199H2.24V11.5999H0ZM6.72 11.5999V7.1199H8.96V11.5999H6.72Z"}))), (jsx("path", ({d:"M11.2 11.5999V0.399902H17.92V2.6399H13.44V4.8799H17.92V7.1199H13.44V9.3599H17.92V11.5999H11.2Z"}))), (jsx("path", ({d:"M20.16 11.5999V0.399902H26.88V2.6399H22.4V4.8799H26.88V7.1199H22.4V11.5999H20.16Z"}))), (jsx("path", ({d:"M29.12 11.5999V0.399902H31.36V9.3599H35.84V11.5999H29.12Z"}))), (jsx("path", ({d:"M38.08 11.5999V0.399902H44.8V2.6399H40.32V4.8799H44.8V7.1199H40.32V9.3599H44.8V11.5999H38.08Z"}))), (jsx("path", ({d:"M47.04 4.8799V0.399902H49.28V4.8799H47.04ZM53.76 4.8799V0.399902H56V4.8799H53.76ZM49.28 7.1199V4.8799H53.76V7.1199H49.28ZM47.04 11.5999V7.1199H49.28V11.5999H47.04ZM53.76 11.5999V7.1199H56V11.5999H53.76Z"}))), (jsx("title", ({}), "Reflex"))))))))))))),""" - """onError:((_error, _info) => (addEvents([(ReflexEvent("reflex___state____state.reflex___state____frontend_event_exception_state.handle_frontend_exception", ({ ["info"] : ((((_error["name"]+": ")+_error["message"])+"\\n")+_error["stack"]), ["component_stack"] : _info["componentStack"] }), ({ })))], [_error, _info], ({ }))))""" + """fallbackRender:((event_args) => (jsx("div", ({css:({ ["height"] : "100%", ["width"] : "100%", ["position"] : "absolute", ["backgroundColor"] : "#fff", ["color"] : "#000", ["display"] : "flex", ["alignItems"] : "center", ["justifyContent"] : "center" })}), (jsx("div", ({css:({ ["display"] : "flex", ["flexDirection"] : "column", ["gap"] : "1rem" })}), (jsx("div", ({css:({ ["display"] : "flex", ["flexDirection"] : "column", ["gap"] : "1rem", ["maxWidth"] : "50ch", ["border"] : "1px solid #888888", ["borderRadius"] : "0.25rem", ["padding"] : "1rem" })}), (jsx("h2", ({css:({ ["fontSize"] : "1.25rem", ["fontWeight"] : "bold" })}), "An error occurred while rendering this page.")), (jsx("p", ({css:({ ["opacity"] : "0.75" })}), "This is an error with the application itself.")), (jsx("details", ({}), (jsx("summary", ({css:({ ["padding"] : "0.5rem" })}), "Error message")), (jsx("div", ({css:({ ["width"] : "100%", ["maxHeight"] : "50vh", ["overflow"] : "auto", ["background"] : "#000", ["color"] : "#fff", ["borderRadius"] : "0.25rem" })}), (jsx("div", ({css:({ ["padding"] : "0.5rem", ["width"] : "fit-content" })}), (jsx("pre", ({}), event_args.error.name + \': \' + event_args.error.message + \'\\n\' + event_args.error.stack)))))), (jsx("button", ({css:({ ["padding"] : "0.35rem 0.75rem", ["margin"] : "0.5rem", ["background"] : "#fff", ["color"] : "#000", ["border"] : "1px solid #000", ["borderRadius"] : "0.25rem", ["fontWeight"] : "bold" }),onClick:((_e) => (addEvents([(ReflexEvent("_call_function", ({ ["function"] : (() => (navigator?.["clipboard"]?.["writeText"](event_args.error.name + \': \' + event_args.error.message + \'\\n\' + event_args.error.stack))), ["callback"] : null }), ({ })))], [_e], ({ }))))}), "Copy")))))), (jsx("hr", ({css:({ ["borderColor"] : "currentColor", ["opacity"] : "0.25" })}))), (jsx(ReactRouterLink, ({to:"https://reflex.dev"}), (jsx("div", ({css:({ ["display"] : "flex", ["alignItems"] : "baseline", ["justifyContent"] : "center", ["fontFamily"] : "monospace", ["--default-font-family"] : "monospace", ["gap"] : "0.5rem" })}), "Built with ", (jsx("svg", ({"aria-label":"Reflex",css:({ ["fill"] : "currentColor" }),height:"12",role:"img",width:"56",xmlns:"http://www.w3.org/2000/svg"}), (jsx("path", ({d:"M0 11.5999V0.399902H8.96V4.8799H6.72V2.6399H2.24V4.8799H6.72V7.1199H2.24V11.5999H0ZM6.72 11.5999V7.1199H8.96V11.5999H6.72Z"}))), (jsx("path", ({d:"M11.2 11.5999V0.399902H17.92V2.6399H13.44V4.8799H17.92V7.1199H13.44V9.3599H17.92V11.5999H11.2Z"}))), (jsx("path", ({d:"M20.16 11.5999V0.399902H26.88V2.6399H22.4V4.8799H26.88V7.1199H22.4V11.5999H20.16Z"}))), (jsx("path", ({d:"M29.12 11.5999V0.399902H31.36V9.3599H35.84V11.5999H29.12Z"}))), (jsx("path", ({d:"M38.08 11.5999V0.399902H44.8V2.6399H40.32V4.8799H44.8V7.1199H40.32V9.3599H44.8V11.5999H38.08Z"}))), (jsx("path", ({d:"M47.04 4.8799V0.399902H49.28V4.8799H47.04ZM53.76 4.8799V0.399902H56V4.8799H53.76ZM49.28 7.1199V4.8799H53.76V7.1199H49.28ZM47.04 11.5999V7.1199H49.28V11.5999H47.04ZM53.76 11.5999V7.1199H56V11.5999H53.76Z"}))), (jsx("title", ({}), "Reflex"))))))))))))),""" + """onError:((_error, _info) => (addEvents([(ReflexEvent("reflex___state____state.reflex___state____frontend_event_exception_state.handle_frontend_exception", ({ ["info"] : ((((_error?.["name"]+": ")+_error?.["message"])+"\\n")+_error?.["stack"]), ["component_stack"] : _info?.["componentStack"] }), ({ })))], [_error, _info], ({ }))))""" "}," 'jsx(RadixThemesText,{as:"p"},' "jsx(RadixThemesColorModeProvider,{}," diff --git a/tests/units/test_event.py b/tests/units/test_event.py index c0def927ea2..c413a1f225e 100644 --- a/tests/units/test_event.py +++ b/tests/units/test_event.py @@ -207,21 +207,21 @@ def test_event_console_log(): assert spec.handler.fn.__qualname__ == "_call_function" assert spec.args[0][0].equals(Var(_js_expr="function")) assert spec.args[0][1].equals( - Var('(() => (console["log"]("message")))', _var_type=Callable) + Var('(() => (console?.["log"]("message")))', _var_type=Callable) ) assert ( format.format_event(spec) - == 'ReflexEvent("_call_function", {function:(() => (console["log"]("message"))),callback:null})' + == 'ReflexEvent("_call_function", {function:(() => (console?.["log"]("message"))),callback:null})' ) spec = event.console_log(Var(_js_expr="message")) assert ( format.format_event(spec) - == 'ReflexEvent("_call_function", {function:(() => (console["log"](message))),callback:null})' + == 'ReflexEvent("_call_function", {function:(() => (console?.["log"](message))),callback:null})' ) spec2 = event.console_log(Var(_js_expr="message2")).add_args(Var("throwaway")) assert ( format.format_event(spec2) - == 'ReflexEvent("_call_function", {function:(() => (console["log"](message2))),callback:null})' + == 'ReflexEvent("_call_function", {function:(() => (console?.["log"](message2))),callback:null})' ) @@ -232,21 +232,21 @@ def test_event_window_alert(): assert spec.handler.fn.__qualname__ == "_call_function" assert spec.args[0][0].equals(Var(_js_expr="function")) assert spec.args[0][1].equals( - Var('(() => (window["alert"]("message")))', _var_type=Callable) + Var('(() => (window?.["alert"]("message")))', _var_type=Callable) ) assert ( format.format_event(spec) - == 'ReflexEvent("_call_function", {function:(() => (window["alert"]("message"))),callback:null})' + == 'ReflexEvent("_call_function", {function:(() => (window?.["alert"]("message"))),callback:null})' ) spec = event.window_alert(Var(_js_expr="message")) assert ( format.format_event(spec) - == 'ReflexEvent("_call_function", {function:(() => (window["alert"](message))),callback:null})' + == 'ReflexEvent("_call_function", {function:(() => (window?.["alert"](message))),callback:null})' ) spec2 = event.window_alert(Var(_js_expr="message2")).add_args(Var("throwaway")) assert ( format.format_event(spec2) - == 'ReflexEvent("_call_function", {function:(() => (window["alert"](message2))),callback:null})' + == 'ReflexEvent("_call_function", {function:(() => (window?.["alert"](message2))),callback:null})' ) diff --git a/tests/units/test_state.py b/tests/units/test_state.py index 12db8328e8f..7394ff55703 100644 --- a/tests/units/test_state.py +++ b/tests/units/test_state.py @@ -431,29 +431,29 @@ def test_class_indexing_with_vars(): prop = TestState.array[TestState.num1] # pyright: ignore [reportCallIssue, reportArgumentType] assert ( str(prop) - == f"{TestState.get_name()}.array{FIELD_MARKER}.at({TestState.get_name()}.num1{FIELD_MARKER})" + == f"{TestState.get_name()}.array{FIELD_MARKER}?.at?.({TestState.get_name()}.num1{FIELD_MARKER})" ) prop = TestState.mapping["a"][TestState.num1] # pyright: ignore [reportCallIssue, reportArgumentType] assert ( str(prop) - == f'{TestState.get_name()}.mapping{FIELD_MARKER}["a"].at({TestState.get_name()}.num1{FIELD_MARKER})' + == f'{TestState.get_name()}.mapping{FIELD_MARKER}?.["a"]?.at?.({TestState.get_name()}.num1{FIELD_MARKER})' ) prop = TestState.mapping[TestState.map_key] assert ( str(prop) - == f"{TestState.get_name()}.mapping{FIELD_MARKER}[{TestState.get_name()}.map_key{FIELD_MARKER}]" + == f"{TestState.get_name()}.mapping{FIELD_MARKER}?.[{TestState.get_name()}.map_key{FIELD_MARKER}]" ) def test_class_attributes(): """Test that we can get class attributes.""" prop = TestState.obj.prop1 - assert str(prop) == f'{TestState.get_name()}.obj{FIELD_MARKER}["prop1"]' + assert str(prop) == f'{TestState.get_name()}.obj{FIELD_MARKER}?.["prop1"]' prop = TestState.complex[1].prop1 - assert str(prop) == f'{TestState.get_name()}.complex{FIELD_MARKER}[1]["prop1"]' + assert str(prop) == f'{TestState.get_name()}.complex{FIELD_MARKER}?.[1]?.["prop1"]' def test_get_parent_state(): @@ -2812,17 +2812,18 @@ class UnionState(BaseState): str(UnionState.c3.c2.c1.foo) == f'{UnionState.c3!s}?.["c2"]?.["c1"]?.["foo"]' # pyright: ignore [reportOptionalMemberAccess] ) assert ( - str(UnionState.c3.c2.c1r.foo) == f'{UnionState.c3!s}?.["c2"]?.["c1r"]["foo"]' # pyright: ignore [reportOptionalMemberAccess] + str(UnionState.c3.c2.c1r.foo) == f'{UnionState.c3!s}?.["c2"]?.["c1r"]?.["foo"]' # pyright: ignore [reportOptionalMemberAccess] ) - assert str(UnionState.c3.c2r.c1) == f'{UnionState.c3!s}?.["c2r"]["c1"]' # pyright: ignore [reportOptionalMemberAccess] + assert str(UnionState.c3.c2r.c1) == f'{UnionState.c3!s}?.["c2r"]?.["c1"]' # pyright: ignore [reportOptionalMemberAccess] assert ( - str(UnionState.c3.c2r.c1.foo) == f'{UnionState.c3!s}?.["c2r"]["c1"]?.["foo"]' # pyright: ignore [reportOptionalMemberAccess] + str(UnionState.c3.c2r.c1.foo) == f'{UnionState.c3!s}?.["c2r"]?.["c1"]?.["foo"]' # pyright: ignore [reportOptionalMemberAccess] ) assert ( - str(UnionState.c3.c2r.c1r.foo) == f'{UnionState.c3!s}?.["c2r"]["c1r"]["foo"]' # pyright: ignore [reportOptionalMemberAccess] + str(UnionState.c3.c2r.c1r.foo) # pyright: ignore [reportOptionalMemberAccess] + == f'{UnionState.c3!s}?.["c2r"]?.["c1r"]?.["foo"]' ) assert str(UnionState.c3i.c2) == f'{UnionState.c3i!s}?.["c2"]' - assert str(UnionState.c3r.c2) == f'{UnionState.c3r!s}["c2"]' + assert str(UnionState.c3r.c2) == f'{UnionState.c3r!s}?.["c2"]' assert UnionState.custom_union.foo is not None # pyright: ignore [reportAttributeAccessIssue] assert UnionState.custom_union.c1 is not None # pyright: ignore [reportAttributeAccessIssue] assert UnionState.custom_union.c1r is not None # pyright: ignore [reportAttributeAccessIssue] diff --git a/tests/units/test_var.py b/tests/units/test_var.py index 356efabd9f7..aed08e51051 100644 --- a/tests/units/test_var.py +++ b/tests/units/test_var.py @@ -311,10 +311,10 @@ def test_basic_operations(TestObj): assert str(LiteralNumberVar.create(1) ** 2) == "(1 ** 2)" assert str(LiteralNumberVar.create(1) & v(2)) == "(1 && 2)" assert str(LiteralNumberVar.create(1) | v(2)) == "(1 || 2)" - assert str(LiteralArrayVar.create([1, 2, 3])[0]) == "[1, 2, 3].at(0)" + assert str(LiteralArrayVar.create([1, 2, 3])[0]) == "[1, 2, 3]?.at?.(0)" assert ( str(LiteralObjectVar.create({"a": 1, "b": 2})["a"]) - == '({ ["a"] : 1, ["b"] : 2 })["a"]' + == '({ ["a"] : 1, ["b"] : 2 })?.["a"]' ) assert str(v("foo") == v("bar")) == '("foo"?.valueOf?.() === "bar"?.valueOf?.())' assert ( @@ -331,11 +331,11 @@ def test_basic_operations(TestObj): Var(_js_expr="foo").to(ObjectVar, TestObj)._var_set_state("state").bar == LiteralVar.create("bar") ) - == '(state.foo["bar"]?.valueOf?.() === "bar"?.valueOf?.())' + == '(state.foo?.["bar"]?.valueOf?.() === "bar"?.valueOf?.())' ) assert ( str(Var(_js_expr="foo").to(ObjectVar, TestObj)._var_set_state("state").bar) - == 'state.foo["bar"]' + == 'state.foo?.["bar"]' ) assert str(abs(LiteralNumberVar.create(1))) == "Math.abs(1)" assert str(LiteralArrayVar.create([1, 2, 3]).length()) == "[1, 2, 3].length" @@ -480,11 +480,11 @@ def test_var_indexing_lists(var): var : The str, list or tuple base var. """ # Test basic indexing. - assert str(var[0]) == f"{var._js_expr}.at(0)" - assert str(var[1]) == f"{var._js_expr}.at(1)" + assert str(var[0]) == f"{var._js_expr}?.at?.(0)" + assert str(var[1]) == f"{var._js_expr}?.at?.(1)" # Test negative indexing. - assert str(var[-1]) == f"{var._js_expr}.at(-1)" + assert str(var[-1]) == f"{var._js_expr}?.at?.(-1)" @pytest.mark.parametrize( @@ -519,11 +519,11 @@ def test_var_indexing_str(): assert str_var[0]._var_type is str # Test basic indexing. - assert str(str_var[0]) == "str.at(0)" - assert str(str_var[1]) == "str.at(1)" + assert str(str_var[0]) == "str?.at?.(0)" + assert str(str_var[1]) == "str?.at?.(1)" # Test negative indexing. - assert str(str_var[-1]) == "str.at(-1)" + assert str(str_var[-1]) == "str?.at?.(-1)" @pytest.mark.parametrize( @@ -669,8 +669,8 @@ def test_dict_indexing(): dct = Var(_js_expr="dct").to(ObjectVar, dict[str, str]) # Check correct indexing. - assert str(dct["a"]) == 'dct["a"]' - assert str(dct["asdf"]) == 'dct["asdf"]' + assert str(dct["a"]) == 'dct?.["a"]' + assert str(dct["asdf"]) == 'dct?.["asdf"]' @pytest.mark.parametrize( @@ -1025,7 +1025,7 @@ def test_boolify_operations(var, expected): def test_index_operation(): array_var = LiteralArrayVar.create([1, 2, 3, 4, 5]) - assert str(array_var[0]) == "[1, 2, 3, 4, 5].at(0)" + assert str(array_var[0]) == "[1, 2, 3, 4, 5]?.at?.(0)" assert str(array_var[1:2]) == "[1, 2, 3, 4, 5].slice(1, 2)" assert ( str(array_var[1:4:2]) @@ -1036,7 +1036,7 @@ def test_index_operation(): == "[1, 2, 3, 4, 5].slice(0, [1, 2, 3, 4, 5].length).slice().reverse().slice(undefined, undefined).filter((_, i) => i % 1 === 0)" ) assert str(array_var.reverse()) == "[1, 2, 3, 4, 5].slice().reverse()" - assert str(array_var[0].to(NumberVar) + 9) == "([1, 2, 3, 4, 5].at(0) + 9)" + assert str(array_var[0].to(NumberVar) + 9) == "([1, 2, 3, 4, 5]?.at?.(0) + 9)" @pytest.mark.parametrize( @@ -1094,8 +1094,8 @@ def test_object_operations(): str(object_var.entries()) == 'Object.entries(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 }) ?? {})' ) - assert str(object_var.a) == '({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })["a"]' - assert str(object_var["a"]) == '({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })["a"]' + assert str(object_var.a) == '({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })?.["a"]' + assert str(object_var["a"]) == '({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })?.["a"]' assert ( str(object_var.merge(LiteralObjectVar.create({"c": 4, "d": 5}))) == '({...({ ["a"] : 1, ["b"] : 2, ["c"] : 3 }), ...({ ["c"] : 4, ["d"] : 5 })})' @@ -1134,15 +1134,15 @@ def test_type_chains(): ) assert ( str(object_var.keys()[0].upper()) - == 'Object.keys(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 }) ?? {}).at(0).toUpperCase()' + == 'Object.keys(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 }) ?? {})?.at?.(0).toUpperCase()' ) assert ( str(object_var.entries()[1][1] - 1) - == '(Object.entries(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 }) ?? {}).at(1).at(1) - 1)' + == '(Object.entries(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 }) ?? {})?.at?.(1)?.at?.(1) - 1)' ) assert ( str(object_var["c"] + object_var["b"]) # pyright: ignore [reportCallIssue, reportOperatorIssue] - == '(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })["c"] + ({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })["b"])' + == '(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })?.["c"] + ({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })?.["b"])' ) @@ -1150,7 +1150,8 @@ def test_nested_dict(): arr = LiteralArrayVar.create([{"bar": ["foo", "bar"]}], list[dict[str, list[str]]]) assert ( - str(arr[0]["bar"][0]) == '[({ ["bar"] : ["foo", "bar"] })].at(0)["bar"].at(0)' # pyright: ignore [reportIndexIssue] + str(arr[0]["bar"][0]) + == '[({ ["bar"] : ["foo", "bar"] })]?.at?.(0)?.["bar"]?.at?.(0)' # pyright: ignore [reportIndexIssue] ) diff --git a/tests/units/utils/test_format.py b/tests/units/utils/test_format.py index 8ac6b1fa929..387cb6d0e98 100644 --- a/tests/units/utils/test_format.py +++ b/tests/units/utils/test_format.py @@ -395,7 +395,7 @@ def test_format_match( ], args_spec=lambda e: [e.target.value], ), - '((_e) => (addEvents([(ReflexEvent("mock_event", ({ ["arg"] : _e["target"]["value"] }), ({ })))], [_e], ({ }))))', + '((_e) => (addEvents([(ReflexEvent("mock_event", ({ ["arg"] : _e?.["target"]?.["value"] }), ({ })))], [_e], ({ }))))', ), ( EventChain(