From 1efbc0327aa00b5bdda724c9e76094826ae15a3f Mon Sep 17 00:00:00 2001 From: Mike Bayer <mike_mp@zzzcomputing.com> Date: Thu, 2 Feb 2012 11:41:34 -0500 Subject: [PATCH] Fix for [ticket:20] and [ticket:86] much thanks to Eevee --- CHANGES | 6 ++++++ mako/__init__.py | 2 +- mako/lexer.py | 41 +++++++++++++++++++++-------------------- test/test_lexer.py | 17 +++++++++++++++++ 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/CHANGES b/CHANGES index 9a34681..cab28ad 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +0.6.2 +- [bug] The ${{"foo":"bar"}} parsing issue is fixed!! + The legendary Eevee has slain the dragon! + [ticket:20]. Also fixes quoting issue + at [ticket:86]. + 0.6.1 - [bug] Added special compatibility for the 0.5.0 Cache() constructor, which was preventing file diff --git a/mako/__init__.py b/mako/__init__.py index 0740ac1..40033ee 100644 --- a/mako/__init__.py +++ b/mako/__init__.py @@ -5,5 +5,5 @@ # the MIT License: http://www.opensource.org/licenses/mit-license.php -__version__ = '0.6.1' +__version__ = '0.6.2' diff --git a/mako/lexer.py b/mako/lexer.py index 217674f..9e0bc5e 100644 --- a/mako/lexer.py +++ b/mako/lexer.py @@ -91,31 +91,32 @@ class Lexer(object): def parse_until_text(self, *text): startpos = self.match_position + text_re = r'|'.join(text) + brace_level = 0 while True: match = self.match(r'#.*\n') if match: continue - match = self.match(r'(\"\"\"|\'\'\'|\"|\')') + match = self.match(r'(\"\"\"|\'\'\'|\"|\')((?<!\\)\\\1|.)*?\1', re.S) if match: - m = self.match(r'.*?%s' % match.group(1), re.S) - if not m: - raise exceptions.SyntaxException( - "Unmatched '%s'" % - match.group(1), - **self.exception_kwargs) - else: - match = self.match(r'(%s)' % r'|'.join(text)) - if match: - return \ - self.text[startpos:self.match_position-len(match.group(1))],\ - match.group(1) - else: - match = self.match(r".*?(?=\"|\'|#|%s)" % r'|'.join(text), re.S) - if not match: - raise exceptions.SyntaxException( - "Expected: %s" % - ','.join(text), - **self.exception_kwargs) + continue + match = self.match(r'(%s)' % text_re) + if match: + if match.group(1) == '}' and brace_level > 0: + brace_level -= 1 + continue + return \ + self.text[startpos:self.match_position-len(match.group(1))],\ + match.group(1) + match = self.match(r"(.*?)(?=\"|\'|#|%s)" % text_re, re.S) + if match: + brace_level += match.group(1).count('{') + brace_level -= match.group(1).count('}') + continue + raise exceptions.SyntaxException( + "Expected: %s" % + ','.join(text), + **self.exception_kwargs) def append_node(self, nodecls, *args, **kwargs): kwargs.setdefault('source', self.text) diff --git a/test/test_lexer.py b/test/test_lexer.py index 538da97..61204ff 100644 --- a/test/test_lexer.py +++ b/test/test_lexer.py @@ -557,6 +557,23 @@ print(''' False, (1, 1)), Text(u" '''and now some text '''", (10,11))])) + def test_tricky_code_4(self): + template = \ + """<% foo = "\\"\\\\" %>""" + nodes = Lexer(template).parse() + self._compare(nodes, TemplateNode({}, + [Code(u"""foo = "\\"\\\\" \n""", + False, (1, 1))])) + + def test_tricky_code_5(self): + template = \ + """before ${ {'key': 'value'} } after""" + nodes = Lexer(template).parse() + self._compare(nodes, TemplateNode({}, + [Text(u'before ', (1, 1)), + Expression(u" {'key': 'value'} ", [], (1, 8)), + Text(u' after', (1, 29))])) + def test_control_lines(self): template = \ """ -- GitLab