Skip to content

Commit 1cd6d39

Browse files
authored
Simplified regex expressions (#157)
- Clean up component regex, which can potentially increase regex performance. - Remove loops from component tests
1 parent a59e3a7 commit 1cd6d39

File tree

2 files changed

+115
-64
lines changed

2 files changed

+115
-64
lines changed

src/reactpy_django/utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727

2828
_logger = logging.getLogger(__name__)
2929
_component_tag = r"(?P<tag>component)"
30-
_component_path = r"(?P<path>(\"[^\"'\s]+\")|('[^\"'\s]+'))"
31-
_component_kwargs = r"(?P<kwargs>(.*?|\s*?)*)"
32-
COMMENT_REGEX = re.compile(r"(<!--)(.|\s)*?(-->)")
30+
_component_path = r"(?P<path>\"[^\"'\s]+\"|'[^\"'\s]+')"
31+
_component_kwargs = r"(?P<kwargs>[\s\S]*?)"
32+
COMMENT_REGEX = re.compile(r"<!--[\s\S]*?-->")
3333
COMPONENT_REGEX = re.compile(
3434
r"{%\s*"
3535
+ _component_tag

tests/test_app/tests/test_regex.py

Lines changed: 112 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -5,81 +5,132 @@
55

66
class RegexTests(TestCase):
77
def test_component_regex(self):
8-
for component in {
9-
r'{%component "my.component"%}',
10-
r'{%component "my.component"%}',
11-
r"{%component 'my.component'%}",
12-
r'{% component "my.component" %}',
13-
r"{% component 'my.component' %}",
14-
r'{% component "my.component" class="my_thing" %}',
8+
# Real component matches
9+
self.assertRegex(r'{%component "my.component"%}', COMPONENT_REGEX)
10+
self.assertRegex(r'{%component "my.component"%}', COMPONENT_REGEX)
11+
self.assertRegex(r"{%component 'my.component'%}", COMPONENT_REGEX)
12+
self.assertRegex(r'{% component "my.component" %}', COMPONENT_REGEX)
13+
self.assertRegex(r"{% component 'my.component' %}", COMPONENT_REGEX)
14+
self.assertRegex(
15+
r'{% component "my.component" class="my_thing" %}', COMPONENT_REGEX
16+
)
17+
self.assertRegex(
1518
r'{% component "my.component" class="my_thing" attr="attribute" %}',
19+
COMPONENT_REGEX,
20+
)
21+
self.assertRegex(
1622
r"""{%
23+
component
24+
"my.component"
25+
class="my_thing"
26+
attr="attribute"
1727
18-
component
19-
"my.component"
20-
class="my_thing"
21-
attr="attribute"
28+
%}""", # noqa: W291
29+
COMPONENT_REGEX,
30+
)
2231

23-
%}""", # noqa: W291
24-
}:
25-
self.assertRegex(component, COMPONENT_REGEX)
32+
# Fake component matches
33+
self.assertNotRegex(r'{% not_a_real_thing "my.component" %}', COMPONENT_REGEX)
34+
self.assertNotRegex(r"{% component my.component %}", COMPONENT_REGEX)
35+
self.assertNotRegex(r"""{% component 'my.component" %}""", COMPONENT_REGEX)
36+
self.assertNotRegex(r'{ component "my.component" }', COMPONENT_REGEX)
37+
self.assertNotRegex(r'{{ component "my.component" }}', COMPONENT_REGEX)
38+
self.assertNotRegex(r"component", COMPONENT_REGEX)
39+
self.assertNotRegex(r"{%%}", COMPONENT_REGEX)
40+
self.assertNotRegex(r" ", COMPONENT_REGEX)
41+
self.assertNotRegex(r"", COMPONENT_REGEX)
42+
self.assertNotRegex(r'{% component " my.component " %}', COMPONENT_REGEX)
43+
self.assertNotRegex(
44+
r"""{% component "my.component COMPONENT_REGEX)
45+
self.assertNotRegex( " %}""",
46+
COMPONENT_REGEX,
47+
)
48+
self.assertNotRegex(r'{{ component """ }}', COMPONENT_REGEX)
49+
self.assertNotRegex(r'{{ component "" }}', COMPONENT_REGEX)
2650

27-
for fake_component in {
28-
r'{% not_a_real_thing "my.component" %}',
29-
r"{% component my.component %}",
30-
r"""{% component 'my.component" %}""",
31-
r'{ component "my.component" }',
32-
r'{{ component "my.component" }}',
33-
r"component",
34-
r"{%%}",
35-
r" ",
36-
r"",
37-
r'{% component " my.component " %}',
38-
r"""{% component "my.component
39-
" %}""",
40-
r'{{ component """ }}',
41-
r'{{ component "" }}',
42-
}:
43-
self.assertNotRegex(fake_component, COMPONENT_REGEX)
51+
# Make sure back-to-back components are not merged into one match
52+
double_component_match = COMPONENT_REGEX.search(
53+
r'{% component "my.component" %} {% component "my.component" %}'
54+
)
55+
self.assertTrue(double_component_match[0] == r'{% component "my.component" %}') # type: ignore
4456

4557
def test_comment_regex(self):
46-
for comment in {
47-
r"<!-- comment -->",
58+
# Real comment matches
59+
self.assertRegex(r"<!-- comment -->", COMMENT_REGEX)
60+
self.assertRegex(
4861
r"""<!-- comment
49-
-->""",
62+
-->""",
63+
COMMENT_REGEX,
64+
)
65+
self.assertRegex(
5066
r"""<!--
51-
comment -->""",
67+
comment -->""",
68+
COMMENT_REGEX,
69+
)
70+
self.assertRegex(
5271
r"""<!--
53-
comment
54-
-->""",
72+
comment
73+
-->""",
74+
COMMENT_REGEX,
75+
)
76+
self.assertRegex(
5577
r"""<!--
56-
a comment
57-
another comments
58-
drink some cement
59-
-->""", # noqa: W291
60-
}:
61-
self.assertRegex(comment, COMMENT_REGEX)
78+
a comment
79+
another comments
80+
drink some cement
81+
-->""", # noqa: W291
82+
COMMENT_REGEX,
83+
)
6284

63-
for fake_comment in {
64-
r"<!-- a comment ",
65-
r"another comment -->",
66-
r"<! - - comment - - >",
67-
r'{% component "my.component" %}',
68-
}:
69-
self.assertNotRegex(fake_comment, COMMENT_REGEX)
85+
# Fake comment matches
86+
self.assertNotRegex(r"<!-- a comment ", COMMENT_REGEX)
87+
self.assertNotRegex(r"another comment -->", COMMENT_REGEX)
88+
self.assertNotRegex(r"<! - - comment - - >", COMMENT_REGEX)
89+
self.assertNotRegex(r'{% component "my.component" %}', COMMENT_REGEX)
7090

71-
for embedded_comment in {
72-
r'{% component "my.component" %} <!-- comment -->',
73-
r'<!-- comment --> {% component "my.component" %}',
74-
r'<!-- comment --> {% component "my.component" %} <!-- comment -->',
75-
r"""<!-- comment
91+
# Components surrounded by comments
92+
self.assertEquals(
93+
COMMENT_REGEX.sub(
94+
"", r'{% component "my.component" %} <!-- comment -->'
95+
).strip(),
96+
'{% component "my.component" %}',
97+
)
98+
self.assertEquals(
99+
COMMENT_REGEX.sub(
100+
"", r'<!-- comment --> {% component "my.component" %}'
101+
).strip(),
102+
'{% component "my.component" %}',
103+
)
104+
self.assertEquals(
105+
COMMENT_REGEX.sub(
106+
"", r'<!-- comment --> {% component "my.component" %} <!-- comment -->'
107+
).strip(),
108+
'{% component "my.component" %}',
109+
)
110+
self.assertEquals(
111+
COMMENT_REGEX.sub(
112+
"",
113+
r"""<!-- comment
76114
--> {% component "my.component" %}
77115
<!-- comment -->
78116
<!--
79117
comment -->""",
80-
}: # noqa: W291
81-
text = COMMENT_REGEX.sub("", embedded_comment)
82-
if text.strip() != '{% component "my.component" %}':
83-
raise self.failureException(
84-
f"Regex pattern {COMMENT_REGEX.pattern} failed to remove comment from {embedded_comment}"
85-
)
118+
).strip(),
119+
'{% component "my.component" %}',
120+
)
121+
122+
# Components surrounded by comments
123+
self.assertEquals(
124+
COMMENT_REGEX.sub("", r'<!-- {% component "my.component" %} -->'),
125+
"",
126+
)
127+
self.assertEquals(
128+
COMMENT_REGEX.sub(
129+
"",
130+
r"""<!--
131+
{% component "my.component" %}
132+
{% component "my.component" %}
133+
-->""", # noqa: W291
134+
),
135+
"",
136+
)

0 commit comments

Comments
 (0)