Repository navigation
fix: raise BackendVarFormatError for a backend var in a LiteralVar - #7651
darshjoshi wants to merge 3 commits into
Conversation
Field.__format__ now raises an error built by Field._no_frontend_var_error, so other code paths that reject a Field can reuse the same message.
A backend var (or a mixin field) passed where a Var is built from a Python value, such as rx.Var.create([State._secret]), rx.toast(State._secret) or rx.image(src=State._secret), reached the generic fallthrough of LiteralVar.create and _get_all_var_data_without_creating_var_dispatch and failed with TypeError: Unsupported type ... for LiteralVar. Both now raise the same BackendVarFormatError that formatting the field raises.
[Medium impact] The PR appears safe to merge. SummaryThe PR gives unsupported
darshjoshi explicitly deferred paths outside Reviews (1) · Last reviewed commit: "docs: add news fragment for backend vars..." · Reviewed by Greptile |
There was a problem hiding this comment.
1 issue found across 5 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/reflex-base/news/+backend-var-literal-var.bugfix.md">
<violation number="1" location="packages/reflex-base/news/+backend-var-literal-var.bugfix.md:1">
P3: This release-note example claims `rx.Var.create([State._secret])` itself raises, but array creation defers nested-field traversal until rendering or var-data collection. Qualify the examples with the operation that triggers rendering/collection.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
| @@ -0,0 +1 @@ | |||
| Passing a backend var where a Var is built from a Python value, e.g. `rx.Var.create([State._secret])`, `rx.toast(State._secret)` or `rx.image(src=State._secret)`, now raises `BackendVarFormatError` with the same explanation as `f"{State._secret}"`, instead of a generic `TypeError: Unsupported type ... for LiteralVar`. | |||
There was a problem hiding this comment.
P3: This release-note example claims rx.Var.create([State._secret]) itself raises, but array creation defers nested-field traversal until rendering or var-data collection. Qualify the examples with the operation that triggers rendering/collection.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/reflex-base/news/+backend-var-literal-var.bugfix.md, line 1:
<comment>This release-note example claims `rx.Var.create([State._secret])` itself raises, but array creation defers nested-field traversal until rendering or var-data collection. Qualify the examples with the operation that triggers rendering/collection.</comment>
<file context>
@@ -0,0 +1 @@
+Passing a backend var where a Var is built from a Python value, e.g. `rx.Var.create([State._secret])`, `rx.toast(State._secret)` or `rx.image(src=State._secret)`, now raises `BackendVarFormatError` with the same explanation as `f"{State._secret}"`, instead of a generic `TypeError: Unsupported type ... for LiteralVar`.
</file context>
| Passing a backend var where a Var is built from a Python value, e.g. `rx.Var.create([State._secret])`, `rx.toast(State._secret)` or `rx.image(src=State._secret)`, now raises `BackendVarFormatError` with the same explanation as `f"{State._secret}"`, instead of a generic `TypeError: Unsupported type ... for LiteralVar`. | |
| Passing a backend var into a Var-building path now raises `BackendVarFormatError` when the resulting Var is rendered or its var data is collected, e.g. `str(rx.Var.create([State._secret]))`, rendering `rx.toast(State._secret)` or `rx.image(src=State._secret)`, with the same explanation as `f"{State._secret}"` instead of a generic `TypeError: Unsupported type ... for LiteralVar`. |
Merging this PR will improve performance by 5%2 warnings
Performance Changes
Tip Curious why performance improved? Comment Comparing |
All Submissions:
Type of change
Changes To Core Features:
Description
Class access to a field with no frontend Var (a backend var such as
State._secret, anis_var=Falsefield, or any field of a mixin state) returns the rawField. When thatFieldis passed where a Var gets built from a Python value, it reaches the end ofLiteralVar.create(_create_literal_var), or of its var-data twin_get_all_var_data_without_creating_var_dispatch. Neither recognises aField, so both fall through to the genericTypeError: Unsupported type ... for LiteralVar. That coversrx.Var.create([F]),rx.Var.create({"a": F}),rx.toast(F),rx.console_log(F),rx.image(src=F)andrx.data_table(data=F)from the issue. Formatting the same field withf"{F}"already raises a clearBackendVarFormatErrorfromField.__format__.This PR follows the proposal in the issue and gives the
LiteralVarpath the same wording:Field.__format__now builds its message in a small helper,Field._no_frontend_var_error(). The text is unchanged.LiteralVarfallthroughs checkisinstance(value, Field)right before the genericTypeErrorand raise that error. The check runs only on the path that was about to fail, so supported values pay nothing.BackendVarFormatErroris aVarTypeError, which is aTypeError, soexcept TypeErrorcode still catches it.test_backend_field_literal_var_reports_reprasserted the old generic message, so it is replaced by tests that expectBackendVarFormatError.Before / After (
F = S._secret,Sa state with_secret: str = "x"):The error still comes up where the Var is built (stringified or rendered), not at the
rx.toast(...)/rx.image(...)call. That is the same place as before, but now with the explanation. Not covered here, and better left as follow-ups:rx.upload_files(on_upload_progress=F)andapp.add_page(title=F, ...)never reachLiteralVar, so they keep their current errors.str(F) + "px"silently embedding the repr, andrx.box(id=F)) are also on other code paths.rx.get_upload_url(F)/reflex/experimental/hooks.pytest suggestion.Tests:
tests/units/reflex_base/vars/test_base.py:LiteralVar.create(F),str(Var.create([F])),str(Var.create({"a": F})), and_get_all_var_data()on the list and dict literals (this reaches the var-data twin). Plus a mixin field case for the mixin wording.tests/units/test_event.py:rx.toast(F)andrx.console_log(F).tests/units/components/test_component.py:rx.image(src=F)andrx.data_table(data=F)rendered.With
vars/base.pyreverted tomain, all 10 new cases fail with the genericTypeError: Unsupported type <class 'reflex_base.vars.base.Field'> for LiteralVar(8 raised at base.py:1932, 2 at :2011). With the fix they pass:ruff format,ruff check,codespell,update-pyi-files,hash-examples,unasync-reflex-build-sdk,ty,biome formatandmake_pyi.py --checkpass.pyright --pythonplatform Linuxreports 0 errors. Thereflex-release changelog-checkandcheck-headingschecks pass with the news fragmentpackages/reflex-base/news/+backend-var-literal-var.bugfix.md.Closes #7459