Skip to content

Commit c11d022

Browse files
committed
simplify tagless
1 parent 30e924e commit c11d022

File tree

10 files changed

+58
-83
lines changed

10 files changed

+58
-83
lines changed

reflex/compiler/templates.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ def render(component: Any) -> str:
6767
return _RenderUtils.render_match_tag(component)
6868
if "cond" in component:
6969
return _RenderUtils.render_condition_tag(component)
70-
if component.get("children", []):
71-
return _RenderUtils.render_tag(component)
72-
return _RenderUtils.render_self_close_tag(component)
70+
if (contents := component.get("contents")) is not None:
71+
return contents
72+
return _RenderUtils.render_tag(component)
7373

7474
@staticmethod
7575
def render_self_close_tag(component: Mapping[str, Any]) -> str:
@@ -86,14 +86,13 @@ def render_self_close_tag(component: Mapping[str, Any]) -> str:
8686
def render_tag(component: Mapping[str, Any]) -> str:
8787
name = component.get("name") or "Fragment"
8888
props = f"{{{','.join(component['props'])}}}"
89-
contents = component.get("contents", "")
9089
rendered_children = [
9190
_RenderUtils.render(child)
9291
for child in component.get("children", [])
9392
if child
9493
]
9594

96-
return f"jsx({name},{props},{contents + ',' if contents else ''}{','.join([_RenderUtils.render(child) for child in rendered_children])})"
95+
return f"jsx({name},{props},{','.join(rendered_children)})"
9796

9897
@staticmethod
9998
def render_condition_tag(component: Any) -> str:

reflex/components/base/bare.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,23 @@ def _render(self) -> Tag:
188188
return Tagless(contents=f"{contents.to_string()!s}")
189189
return Tagless(contents=f"{contents!s}")
190190

191+
def render(self) -> dict:
192+
"""Render the component as a dictionary.
193+
194+
This is overridden to provide a short performant path for rendering.
195+
196+
Returns:
197+
The rendered component.
198+
"""
199+
contents = (
200+
Var.create(self.contents)
201+
if not isinstance(self.contents, Var)
202+
else self.contents
203+
)
204+
if isinstance(contents, (BooleanVar, ObjectVar)):
205+
return {"contents": f"{contents.to_string()!s}"}
206+
return {"contents": f"{contents!s}"}
207+
191208
def _add_style_recursive(
192209
self, style: ComponentStyle, theme: Component | None = None
193210
) -> Component:

reflex/components/component.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,7 +1270,6 @@ def render(self) -> dict:
12701270
rendered_dict = dict(
12711271
tag.set(
12721272
children=[child.render() for child in self.children],
1273-
contents=str(tag.contents),
12741273
)
12751274
)
12761275
self._replace_prop_names(rendered_dict)
@@ -2796,6 +2795,9 @@ def render_dict_to_var(tag: dict | Component | str) -> Var:
27962795
return render_dict_to_var(tag.render())
27972796
return Var.create(tag)
27982797

2798+
if "contents" in tag:
2799+
return Var(tag["contents"])
2800+
27992801
if "iterable" in tag:
28002802
function_return = LiteralArrayVar.create(
28012803
[render_dict_to_var(child.render()) for child in tag["children"]]
@@ -2842,8 +2844,6 @@ def render_dict_to_var(tag: dict | Component | str) -> Var:
28422844

28432845
props = Var("({" + ",".join(tag["props"]) + "})")
28442846

2845-
contents = tag["contents"] if tag["contents"] else None
2846-
28472847
raw_tag_name = tag.get("name")
28482848
tag_name = Var(raw_tag_name or "Fragment")
28492849

@@ -2852,7 +2852,6 @@ def render_dict_to_var(tag: dict | Component | str) -> Var:
28522852
).call(
28532853
tag_name,
28542854
props,
2855-
*([Var(contents)] if contents is not None else []),
28562855
*[render_dict_to_var(child) for child in tag["children"]],
28572856
)
28582857

reflex/components/tags/tag.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from __future__ import annotations
44

55
import dataclasses
6-
from collections.abc import Mapping, Sequence
6+
from collections.abc import Iterator, Mapping, Sequence
77
from typing import Any
88

99
from reflex.event import EventChain
@@ -41,9 +41,6 @@ class Tag:
4141
# The props of the tag.
4242
props: Mapping[str, Any] = dataclasses.field(default_factory=dict)
4343

44-
# The inner contents of the tag.
45-
contents: str = ""
46-
4744
# Special props that aren't key value pairs.
4845
special_props: Sequence[Var] = dataclasses.field(default_factory=list)
4946

@@ -69,7 +66,7 @@ def set(self, **kwargs: Any):
6966
"""
7067
return dataclasses.replace(self, **kwargs)
7168

72-
def __iter__(self):
69+
def __iter__(self) -> Iterator[tuple[str, Any]]:
7370
"""Iterate over the tag's fields.
7471
7572
Yields:

reflex/components/tags/tagless.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
"""A tag with no tag."""
22

3+
import dataclasses
4+
35
from reflex.components.tags import Tag
46
from reflex.utils import format
57

68

9+
@dataclasses.dataclass(frozen=True, kw_only=True)
710
class Tagless(Tag):
811
"""A tag with no tag."""
912

13+
# The inner contents of the tag.
14+
contents: str
15+
1016
def __str__(self) -> str:
1117
"""Return the string representation of the tag.
1218
@@ -20,3 +26,11 @@ def __str__(self) -> str:
2026
if len(self.contents) > 0 and self.contents[-1] == " ":
2127
out = out + space
2228
return out
29+
30+
def __iter__(self):
31+
"""Iterate over the tag's fields.
32+
33+
Yields:
34+
tuple[str, Any]: The field name and value.
35+
"""
36+
yield "contents", self.contents

tests/units/components/base/test_script.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ def test_script_inline():
1010
component = Script.create("let x = 42")
1111
render_dict = component.render()["children"][0]
1212
assert render_dict["name"] == '"script"'
13-
assert not render_dict["contents"]
1413
assert len(render_dict["children"]) == 1
1514
assert render_dict["children"][0]["contents"] == '"let x = 42"'
1615

@@ -20,7 +19,6 @@ def test_script_src():
2019
component = Script.create(src="foo.js")
2120
render_dict = component.render()["children"][0]
2221
assert render_dict["name"] == '"script"'
23-
assert not render_dict["contents"]
2422
assert not render_dict["children"]
2523
assert 'src:"foo.js"' in render_dict["props"]
2624

tests/units/components/core/test_debounce.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ def test_render_child_props():
6565
)
6666
assert len(tag.props["onChange"].events) == 1
6767
assert tag.props["onChange"].events[0].handler == S.on_change
68-
assert tag.contents == ""
6968

7069

7170
def test_render_with_class_name():
@@ -161,7 +160,6 @@ def test_render_child_props_recursive():
161160
assert tag.props["debounceTimeout"]._js_expr == "42"
162161
assert len(tag.props["onChange"].events) == 1
163162
assert tag.props["onChange"].events[0].handler == S.on_change
164-
assert tag.contents == ""
165163

166164

167165
def test_full_control_implicit_debounce():
@@ -173,7 +171,6 @@ def test_full_control_implicit_debounce():
173171
assert tag.props["debounceTimeout"]._js_expr == str(DEFAULT_DEBOUNCE_TIMEOUT)
174172
assert len(tag.props["onChange"].events) == 1
175173
assert tag.props["onChange"].events[0].handler == S.on_change
176-
assert tag.contents == ""
177174

178175

179176
def test_full_control_implicit_debounce_text_area():
@@ -185,4 +182,3 @@ def test_full_control_implicit_debounce_text_area():
185182
assert tag.props["debounceTimeout"]._js_expr == str(DEFAULT_DEBOUNCE_TIMEOUT)
186183
assert len(tag.props["onChange"].events) == 1
187184
assert tag.props["onChange"].events[0].handler == S.on_change
188-
assert tag.contents == ""

tests/units/components/test_component.py

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -684,18 +684,13 @@ def test_component_create_unallowed_types(children, test_component):
684684
{
685685
"name": "Fragment",
686686
"props": [],
687-
"contents": "",
688687
"children": [
689688
{
690689
"name": "RadixThemesText",
691690
"props": ['as:"p"'],
692-
"contents": "",
693691
"children": [
694692
{
695-
"name": "",
696-
"props": [],
697693
"contents": '"first_text"',
698-
"children": [],
699694
}
700695
],
701696
}
@@ -709,31 +704,22 @@ def test_component_create_unallowed_types(children, test_component):
709704
{
710705
"children": [
711706
{
712-
"children": [],
713707
"contents": '"first_text"',
714-
"name": "",
715-
"props": [],
716708
}
717709
],
718-
"contents": "",
719710
"name": "RadixThemesText",
720711
"props": ['as:"p"'],
721712
},
722713
{
723714
"children": [
724715
{
725-
"children": [],
726716
"contents": '"second_text"',
727-
"name": "",
728-
"props": [],
729717
}
730718
],
731-
"contents": "",
732719
"name": "RadixThemesText",
733720
"props": ['as:"p"'],
734721
},
735722
],
736-
"contents": "",
737723
"name": "Fragment",
738724
"props": [],
739725
},
@@ -745,13 +731,9 @@ def test_component_create_unallowed_types(children, test_component):
745731
{
746732
"children": [
747733
{
748-
"children": [],
749734
"contents": '"first_text"',
750-
"name": "",
751-
"props": [],
752735
}
753736
],
754-
"contents": "",
755737
"name": "RadixThemesText",
756738
"props": ['as:"p"'],
757739
},
@@ -762,28 +744,21 @@ def test_component_create_unallowed_types(children, test_component):
762744
{
763745
"children": [
764746
{
765-
"children": [],
766747
"contents": '"second_text"',
767-
"name": "",
768-
"props": [],
769748
}
770749
],
771-
"contents": "",
772750
"name": "RadixThemesText",
773751
"props": ['as:"p"'],
774752
}
775753
],
776-
"contents": "",
777754
"name": "Fragment",
778755
"props": [],
779756
}
780757
],
781-
"contents": "",
782758
"name": "RadixThemesBox",
783759
"props": [],
784760
},
785761
],
786-
"contents": "",
787762
"name": "Fragment",
788763
"props": [],
789764
},

tests/units/components/test_tag.py

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ def test_add_props():
6565
{
6666
"name": "",
6767
"children": [],
68-
"contents": "",
6968
"props": [],
7069
},
7170
),
@@ -74,47 +73,20 @@ def test_add_props():
7473
{
7574
"name": "br",
7675
"children": [],
77-
"contents": "",
7876
"props": [],
7977
},
8078
),
8179
(
82-
Tag(contents="hello"),
80+
tagless.Tagless(contents="hello"),
8381
{
84-
"name": "",
85-
"children": [],
8682
"contents": "hello",
87-
"props": [],
88-
},
89-
),
90-
(
91-
Tag(name="h1", contents="hello"),
92-
{
93-
"name": "h1",
94-
"children": [],
95-
"contents": "hello",
96-
"props": [],
9783
},
9884
),
9985
(
10086
Tag(name="box", props={"color": "red", "textAlign": "center"}),
10187
{
10288
"name": "box",
10389
"children": [],
104-
"contents": "",
105-
"props": ['color:"red"', 'textAlign:"center"'],
106-
},
107-
),
108-
(
109-
Tag(
110-
name="box",
111-
props={"color": "red", "textAlign": "center"},
112-
contents="text",
113-
),
114-
{
115-
"name": "box",
116-
"children": [],
117-
"contents": "text",
11890
"props": ['color:"red"', 'textAlign:"center"'],
11991
},
12092
),
@@ -134,8 +106,8 @@ def test_format_tag(tag: Tag, expected: dict):
134106
def test_format_cond_tag():
135107
"""Test that the cond tag dict is correct."""
136108
tag = CondTag(
137-
true_value=dict(Tag(name="h1", contents="True content")),
138-
false_value=dict(Tag(name="h2", contents="False content")),
109+
true_value=dict(tagless.Tagless(contents="True content")),
110+
false_value=dict(tagless.Tagless(contents="False content")),
139111
cond=Var("logged_in", _var_type=bool),
140112
)
141113
tag_dict = dict(tag)
@@ -147,10 +119,8 @@ def test_format_cond_tag():
147119
assert cond._js_expr == "logged_in"
148120
assert cond._var_type is bool
149121

150-
assert true_value["name"] == "h1"
151122
assert true_value["contents"] == "True content"
152123

153-
assert false_value["name"] == "h2"
154124
assert false_value["contents"] == "False content"
155125

156126

0 commit comments

Comments
 (0)