| import unittest |
| |
| from mako.lexer import Lexer |
| from mako import exceptions |
| |
| class LexerTest(unittest.TestCase): |
| def test_text_and_tag(self): |
| template = """ |
| <b>Hello world</b> |
| <%component name="foo"> |
| this is a component. |
| </%component> |
| |
| and some more text. |
| """ |
| node = Lexer(template).parse() |
| assert repr(node) == r"""TemplateNode({}, [Text('\n<b>Hello world</b>\n ', (1, 1)), ComponentTag('component', {'name': 'foo'}, (3, 9), ["Text('\\n this is a component.\\n ', (3, 32))"]), Text('\n \n and some more text.\n', (5, 22))])""" |
| |
| def test_unclosed_tag(self): |
| template = """ |
| |
| <%component name="foo"> |
| other text |
| """ |
| try: |
| nodes = Lexer(template).parse() |
| assert False |
| except exceptions.SyntaxException, e: |
| assert str(e) == "Unclosed tag: <%component> at line: 5 char: 9" |
| |
| def test_onlyclosed_tag(self): |
| template = """ |
| <%component name="foo"> |
| foo |
| </%component> |
| |
| </%namespace> |
| |
| hi. |
| """ |
| try: |
| nodes = Lexer(template).parse() |
| assert False |
| except exceptions.SyntaxException, e: |
| assert str(e) == "Closing tag without opening tag: </%namespace> at line: 6 char: 13" |
| |
| def test_unmatched_tag(self): |
| template = """ |
| <%namespace name="bar"> |
| <%component name="foo"> |
| foo |
| </%namespace> |
| </%component> |
| |
| |
| hi. |
| """ |
| try: |
| nodes = Lexer(template).parse() |
| assert False |
| except exceptions.SyntaxException, e: |
| assert str(e) == "Closing tag </%namespace> does not match tag: <%component> at line: 5 char: 13" |
| |
| def test_nonexistent_tag(self): |
| template = """ |
| <%lala x="5"/> |
| """ |
| try: |
| node = Lexer(template).parse() |
| assert False |
| except exceptions.CompileException, e: |
| assert str(e) == "No such tag: 'lala' at line: 2 char: 13" |
| |
| def test_component_syntax(self): |
| template = """ |
| <%component lala> |
| hi |
| </%component> |
| """ |
| try: |
| node = Lexer(template).parse() |
| assert False |
| except exceptions.CompileException, e: |
| assert str(e) == "Missing attribute(s): 'name' at line: 2 char: 9" |
| |
| def test_expr_in_attribute(self): |
| """test some slightly trickier expressions. |
| |
| you can still trip up the expression parsing, though, unless we integrated really deeply somehow with AST.""" |
| template = """ |
| <%call expr="foo>bar and 'lala' or 'hoho'"/> |
| <%call expr='foo<bar and hoho>lala and "x" + "y"'/> |
| """ |
| nodes = Lexer(template).parse() |
| #print nodes |
| assert repr(nodes) == r"""TemplateNode({}, [Text('\n ', (1, 1)), CallTag('call', {'expr': "foo>bar and 'lala' or 'hoho'"}, (2, 13), []), Text('\n ', (2, 57)), CallTag('call', {'expr': 'foo<bar and hoho>lala and "x" + "y"'}, (3, 13), []), Text('\n ', (3, 64))])""" |
| |
| |
| def test_nesting(self): |
| template = """ |
| |
| <%namespace name="ns"> |
| <%component name="lala(hi, there)"> |
| <%call expr="something()"/> |
| </%component> |
| </%namespace> |
| |
| """ |
| nodes = Lexer(template).parse() |
| assert repr(nodes) == r"""TemplateNode({}, [Text('\n \n ', (1, 1)), NamespaceTag('namespace', {'name': 'ns'}, (3, 9), ["Text('\\n ', (3, 31))", 'ComponentTag(\'component\', {\'name\': \'lala(hi, there)\'}, (4, 13), ["Text(\'\\\\n \', (4, 48))", "CallTag(\'call\', {\'expr\': \'something()\'}, (5, 17), [])", "Text(\'\\\\n \', (5, 44))"])', "Text('\\n ', (6, 26))"]), Text('\n \n ', (7, 22))])""" |
| |
| def test_code(self): |
| template = """ |
| some text |
| |
| <% |
| print "hi" |
| for x in range(1,5): |
| print x |
| %> |
| |
| more text |
| |
| <%! |
| import foo |
| %> |
| """ |
| nodes = Lexer(template).parse() |
| #print nodes |
| assert repr(nodes) == r"""TemplateNode({}, [Text('\n some text\n \n ', (1, 1)), Code('\nprint "hi"\nfor x in range(1,5):\n print x\n \n', False, (4, 9)), Text('\n \n more text\n \n ', (8, 11)), Code('\nimport foo\n \n', True, (12, 9)), Text('\n ', (14, 11))])""" |
| |
| def test_code_and_tags(self): |
| template = """ |
| <%namespace name="foo"> |
| <%component name="x"> |
| this is x |
| </%component> |
| <%component name="y"> |
| this is y |
| </%component> |
| </%namespace> |
| |
| <% |
| result = [] |
| data = get_data() |
| for x in data: |
| result.append(x+7) |
| %> |
| |
| result: <%call expr="foo.x(result)"/> |
| """ |
| nodes = Lexer(template).parse() |
| assert repr(nodes) == r"""TemplateNode({}, [Text('\n', (1, 1)), NamespaceTag('namespace', {'name': 'foo'}, (2, 1), ["Text('\\n ', (2, 24))", 'ComponentTag(\'component\', {\'name\': \'x\'}, (3, 5), ["Text(\'\\\\n this is x\\\\n \', (3, 26))"])', "Text('\\n ', (5, 18))", 'ComponentTag(\'component\', {\'name\': \'y\'}, (6, 5), ["Text(\'\\\\n this is y\\\\n \', (6, 26))"])', "Text('\\n', (8, 18))"]), Text('\n\n', (9, 14)), Code('\nresult = []\ndata = get_data()\nfor x in data:\n result.append(x+7)\n\n', False, (11, 1)), Text('\n\n result: ', (16, 3)), CallTag('call', {'expr': 'foo.x(result)'}, (18, 13), []), Text('\n', (18, 42))])""" |
| |
| |
| def test_expression(self): |
| template = """ |
| this is some ${text} and this is ${textwith | escapes, moreescapes} |
| <%component name="hi"> |
| give me ${foo()} and ${bar()} |
| </%component> |
| ${hi()} |
| """ |
| nodes = Lexer(template).parse() |
| assert repr(nodes) == r"""TemplateNode({}, [Text('\n this is some ', (1, 1)), Expression('text', [], (2, 22)), Text(' and this is ', (2, 29)), Expression('textwith ', ['escapes', 'moreescapes'], (2, 42)), Text('\n ', (2, 76)), ComponentTag('component', {'name': 'hi'}, (3, 9), ["Text('\\n give me ', (3, 31))", "Expression('foo()', [], (4, 21))", "Text(' and ', (4, 29))", "Expression('bar()', [], (4, 34))", "Text('\\n ', (4, 42))"]), Text('\n ', (5, 22)), Expression('hi()', [], (6, 9)), Text('\n', (6, 16))])""" |
| |
| def test_control_lines(self): |
| template = """ |
| text text la la |
| % if foo(): |
| mroe text la la blah blah |
| % endif |
| |
| and osme more stuff |
| % for l in range(1,5): |
| tex tesl asdl l is ${l} kfmas d |
| % endfor |
| tetx text |
| |
| """ |
| nodes = Lexer(template).parse() |
| #print nodes |
| assert repr(nodes) == r"""TemplateNode({}, [Text('\ntext text la la\n', (1, 1)), ControlLine('if', 'if foo():', False, (3, 1)), Text(' mroe text la la blah blah\n', (4, 1)), ControlLine('if', 'endif', True, (5, 1)), Text('\n and osme more stuff\n', (6, 1)), ControlLine('for', 'for l in range(1,5):', False, (8, 1)), Text(' tex tesl asdl l is ', (9, 1)), Expression('l', [], (9, 24)), Text(' kfmas d\n', (9, 28)), ControlLine('for', 'endfor', True, (10, 1)), Text(' tetx text\n \n', (11, 1))])""" |
| |
| def test_unmatched_control(self): |
| template = """ |
| |
| % if foo: |
| % for x in range(1,5): |
| % endif |
| """ |
| try: |
| nodes = Lexer(template).parse() |
| assert False |
| except exceptions.SyntaxException, e: |
| assert str(e) == "Keyword 'endif' doesn't match keyword 'for' at line: 5 char: 1" |
| |
| def test_unmatched_control_2(self): |
| template = """ |
| |
| % if foo: |
| % for x in range(1,5): |
| % endlala |
| % endif |
| """ |
| try: |
| nodes = Lexer(template).parse() |
| assert False |
| except exceptions.SyntaxException, e: |
| assert str(e) == "Keyword 'endlala' doesn't match keyword 'for' at line: 5 char: 1" |
| |
| def test_ternary_control(self): |
| template = """ |
| % if x: |
| hi |
| % elif y+7==10: |
| there |
| % elif lala: |
| lala |
| % else: |
| hi |
| % endif |
| """ |
| nodes = Lexer(template).parse() |
| #print nodes |
| assert repr(nodes) == r"""TemplateNode({}, [ControlLine('if', 'if x:', False, (1, 1)), Text(' hi\n', (3, 1)), ControlLine('elif', 'elif y+7==10:', False, (4, 1)), Text(' there\n', (5, 1)), ControlLine('elif', 'elif lala:', False, (6, 1)), Text(' lala\n', (7, 1)), ControlLine('else', 'else:', False, (8, 1)), Text(' hi\n', (9, 1)), ControlLine('if', 'endif', True, (10, 1))])""" |
| |
| def test_integration(self): |
| template = """<%namespace name="foo" file="somefile.html"/> |
| # inherit from foobar.html |
| <%inherit file="foobar.html"/> |
| |
| <%component name="header"> |
| <div>header</div> |
| </%component> |
| <%component name="footer"> |
| <div> footer</div> |
| </%component> |
| |
| <table> |
| % for j in data(): |
| <tr> |
| % for x in j: |
| <td>Hello ${x| h}</td> |
| % endfor |
| </tr> |
| % endfor |
| </table> |
| """ |
| nodes = Lexer(template).parse() |
| assert repr(nodes) == r"""TemplateNode({}, [NamespaceTag('namespace', {'name': 'foo', 'file': 'somefile.html'}, (1, 1), []), Text('\n', (1, 46)), Comment('inherit from foobar.html', (2, 1)), InheritTag('inherit', {'file': 'foobar.html'}, (3, 1), []), Text('\n\n', (3, 31)), ComponentTag('component', {'name': 'header'}, (5, 1), ["Text('\\n <div>header</div>\\n', (5, 27))"]), Text('\n', (7, 14)), ComponentTag('component', {'name': 'footer'}, (8, 1), ["Text('\\n <div> footer</div>\\n', (8, 27))"]), Text('\n\n<table>\n', (10, 14)), ControlLine('for', 'for j in data():', False, (13, 1)), Text(' <tr>\n', (14, 1)), ControlLine('for', 'for x in j:', False, (15, 1)), Text(' <td>Hello ', (16, 1)), Expression('x', ['h'], (16, 23)), Text('</td>\n', (16, 30)), ControlLine('for', 'endfor', True, (17, 1)), Text(' </tr>\n', (18, 1)), ControlLine('for', 'endfor', True, (19, 1)), Text('</table>\n', (20, 1))])""" |
| |
| if __name__ == '__main__': |
| unittest.main() |