Skip to content

Commit 042a63f

Browse files
jjgalvezzzzeek
authored andcommitted
Update parsetree.py removed "?" from for x in re.compile(r"(\${.+})" …
Fixed issue where a parsed expression which contained sub-brackets, such as dictionary literals, would fail to be interpreted correctly even though the initial parsing is correct. Pull request courtesy Jose Galvez. Fixes: #400 Closes: #397 Pull-request: #397 Pull-request-sha: 33a85f2 Change-Id: I9c523c86f847622252a6bc34bcc72713065acde6
1 parent af80cbd commit 042a63f

File tree

4 files changed

+176
-3
lines changed

4 files changed

+176
-3
lines changed

doc/build/unreleased/400.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.. change::
2+
:tags: bug, lexer
3+
:tickets: 400
4+
5+
Fixed issue where a parsed expression which contained sub-brackets, such as
6+
dictionary literals, would fail to be interpreted correctly even though the
7+
initial parsing is correct. Pull request courtesy Jose Galvez.

mako/parsetree.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,10 @@ def _parse_attributes(self, expressions, nonexpressions):
322322
for key in self.attributes:
323323
if key in expressions:
324324
expr = []
325-
for x in re.compile(r"(\${.+?})", re.S).split(
325+
for x in re.compile(r"(\${.+})", re.S).split(
326326
self.attributes[key]
327327
):
328-
m = re.compile(r"^\${(.+?)}$", re.S).match(x)
328+
m = re.compile(r"^\${(.+)}$", re.S).match(x)
329329
if m:
330330
code = ast.PythonCode(
331331
m.group(1).rstrip(), **self.exception_kwargs

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ show-source = true
8989
enable-extensions = G
9090
# E203 is due to https://github.com/PyCQA/pycodestyle/issues/373
9191
ignore =
92-
A003,
92+
A003,A005
9393
D,
9494
E203,E305,E711,E712,E721,E722,E741,
9595
N801,N802,N806,

test/test_lexer.py

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,172 @@ def test_tricky_expression(self):
810810
),
811811
)
812812

813+
def test_dict_expression(self):
814+
template = """
815+
<%def name="dtest(d)">
816+
% for k,v in d.items():
817+
${k} = ${v}
818+
% endfor
819+
</%def>
820+
821+
<%self:dtest d="${
822+
{
823+
'id':'4',
824+
'foo':'barr'
825+
}
826+
}" />
827+
"""
828+
nodes = Lexer(template).parse()
829+
self._compare(
830+
nodes,
831+
TemplateNode(
832+
{},
833+
[
834+
Text("\n ", (1, 1)),
835+
DefTag(
836+
"def",
837+
{"name": "dtest(d)"},
838+
(2, 9),
839+
[
840+
Text("\n", (2, 31)),
841+
ControlLine(
842+
"for", "for k,v in d.items():", False, (3, 1)
843+
),
844+
Text(" ", (4, 1)),
845+
Expression("k", [], (4, 13)),
846+
Text(" = ", (4, 17)),
847+
Expression("v", [], (4, 20)),
848+
Text("\n", (4, 24)),
849+
ControlLine("for", "endfor", True, (5, 1)),
850+
Text(" ", (6, 1)),
851+
],
852+
),
853+
Text("\n\n ", (6, 16)),
854+
CallNamespaceTag(
855+
"self:dtest",
856+
{
857+
"d": "${\n "
858+
"{\n 'id':'4',\n"
859+
" 'foo':'barr'\n"
860+
" }\n"
861+
" }"
862+
},
863+
(8, 9),
864+
[],
865+
),
866+
Text("\n ", (13, 30)),
867+
],
868+
),
869+
)
870+
871+
def test_dict_expression_2(self):
872+
template = """
873+
<%def name="thing(thing)">
874+
${type(thing)}
875+
</%def>
876+
877+
<%self:thing thing="foo" />
878+
879+
<%self:thing thing="${5}" />
880+
881+
<%self:thing thing="${[1,2,3]}" />
882+
883+
<%self:thing thing="${{'id':'4'}, {'id': 5}}" />
884+
885+
886+
<%
887+
foo="this is foo"
888+
g=False
889+
%>
890+
891+
<%def name="bar(x, y)">
892+
${x} ${y}
893+
</%def>
894+
895+
<%self:bar x=" ${{'id':4}} " y="x${g and '1' or '2'}y"/>
896+
897+
<%self:dtest d="${ {
898+
'x-on:click':foo,
899+
'foo':'bar'
900+
} }" />
901+
"""
902+
nodes = Lexer(template).parse()
903+
self._compare(
904+
nodes,
905+
TemplateNode(
906+
{},
907+
[
908+
Text("\n ", (1, 1)),
909+
DefTag(
910+
"def",
911+
{"name": "thing(thing)"},
912+
(2, 9),
913+
[
914+
Text("\n ", (2, 35)),
915+
Expression("type(thing)", [], (3, 13)),
916+
Text("\n ", (3, 27)),
917+
],
918+
),
919+
Text("\n\n ", (4, 16)),
920+
CallNamespaceTag(
921+
"self:thing", {"thing": "foo"}, (6, 9), []
922+
),
923+
Text("\n\n ", (6, 36)),
924+
CallNamespaceTag(
925+
"self:thing", {"thing": "${5}"}, (8, 9), []
926+
),
927+
Text("\n\n ", (8, 37)),
928+
CallNamespaceTag(
929+
"self:thing", {"thing": "${[1,2,3]}"}, (10, 9), []
930+
),
931+
Text("\n\n ", (10, 43)),
932+
CallNamespaceTag(
933+
"self:thing",
934+
{"thing": "${{'id':'4'}, {'id': 5}}"},
935+
(12, 9),
936+
[],
937+
),
938+
Text("\n\n\n ", (12, 57)),
939+
Code(
940+
'\nfoo="this is foo"\ng=False\n \n',
941+
False,
942+
(15, 9),
943+
),
944+
Text("\n\n ", (18, 11)),
945+
DefTag(
946+
"def",
947+
{"name": "bar(x, y)"},
948+
(20, 9),
949+
[
950+
Text("\n ", (20, 32)),
951+
Expression("x", [], (21, 13)),
952+
Text(" ", (21, 17)),
953+
Expression("y", [], (21, 18)),
954+
Text("\n ", (21, 22)),
955+
],
956+
),
957+
Text("\n\n ", (22, 16)),
958+
CallNamespaceTag(
959+
"self:bar",
960+
{"x": " ${{'id':4}} ", "y": "x${g and '1' or '2'}y"},
961+
(24, 9),
962+
[],
963+
),
964+
Text("\n\n ", (24, 65)),
965+
CallNamespaceTag(
966+
"self:dtest",
967+
{
968+
"d": "${ {\n 'x-on:click':foo,\n"
969+
" 'foo':'bar'\n } }"
970+
},
971+
(26, 9),
972+
[],
973+
),
974+
Text("\n ", (29, 16)),
975+
],
976+
),
977+
)
978+
813979
def test_tricky_code(self):
814980
template = """<% print('hi %>') %>"""
815981
nodes = Lexer(template).parse()

0 commit comments

Comments
 (0)