Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/reflex-base/news/+format-prop-dict.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Passing a plain `dict` to `format_prop` no longer raises `AttributeError`; the dict is JSON-encoded like any other literal.
20 changes: 3 additions & 17 deletions packages/reflex-base/src/reflex_base/utils/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from rich.markup import escape as escape_markup

from reflex_base import constants
from reflex_base.utils import exceptions
from reflex_base.utils.types import is_non_string_sequence

if TYPE_CHECKING:
Expand Down Expand Up @@ -369,7 +368,7 @@ def format_match(

def format_prop(
prop: Var | EventChain | ComponentStyle | str,
) -> int | float | str:
) -> str:
"""Format a prop.

Args:
Expand All @@ -379,13 +378,10 @@ def format_prop(
The formatted prop to display within a tag.

Raises:
exceptions.InvalidStylePropError: If the style prop value is not a valid type.
TypeError: If the prop is not valid.
ValueError: If the prop is not a string.
"""
# import here to avoid circular import.
from reflex_base.event import EventChain
from reflex_base.utils import serializers
from reflex_base.vars import Var

try:
Expand All @@ -403,23 +399,13 @@ def format_prop(
return prop
return json_dumps(prop)

# For dictionaries, convert any properties to strings.
if isinstance(prop, dict):
prop = serializers.serialize_dict(prop) # pyright: ignore [reportAttributeAccessIssue]

else:
# Dump the prop as JSON.
prop = json_dumps(prop)
except exceptions.InvalidStylePropError:
raise
# Dump the prop as JSON.
prop = json_dumps(prop)
except TypeError as e:
msg = f"Could not format prop: {prop} of type {type(prop)}"
raise TypeError(msg) from e

# Wrap the variable in braces.
if not isinstance(prop, str):
msg = f"Invalid prop: {prop}. Expected a string."
raise ValueError(msg)
return wrap(prop, "{", check_first=False)


Expand Down
19 changes: 19 additions & 0 deletions tests/units/utils/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,25 @@ def test_format_prop(prop: Var, formatted: str):
assert format.format_prop(LiteralVar.create(prop)) == formatted


@pytest.mark.parametrize(
("prop", "formatted"),
[
({"a": 1}, '{{"a": 1}}'),
({"nested": {"b": [1, 2]}}, '{{"nested": {"b": [1, 2]}}}'),
({}, "{{}}"),
({"d": datetime.date(2026, 1, 2)}, '{{"d": "2026-01-02"}}'),
],
)
def test_format_prop_raw_dict(prop: dict, formatted: str):
"""Test that a raw dict prop is JSON-dumped and wrapped in braces.

Args:
prop: The dict prop to test.
formatted: The expected formatted value.
"""
assert format.format_prop(prop) == formatted


@pytest.mark.parametrize(
("single_props", "key_value_props", "output"),
[
Expand Down
Loading