diff --git a/examples/bench/basic.py b/examples/bench/basic.py index bf531ef5d8f71c543a2d02992f69c80330c1ca1a..e9131e1a3e5d0991e071d52edd97bc1dc6e11497 100644 --- a/examples/bench/basic.py +++ b/examples/bench/basic.py @@ -70,7 +70,7 @@ def mako(dirname, verbose=False): def render(): return template.render(title="Just a test", user="joe", list_items=[u'Number %d' % num for num in range(1,15)]) if verbose: - print render() + print template.code, render() return render mako_inheritance = mako diff --git a/lib/mako/codegen.py b/lib/mako/codegen.py index 78aa21d08d61a0583a07bd7d57b65ff239562db8..6ce1d9a39ff7d82ed8bfb3788ec167da380ff08c 100644 --- a/lib/mako/codegen.py +++ b/lib/mako/codegen.py @@ -265,6 +265,8 @@ class _GenerateRenderMethod(object): self.printer.writeline("return [%s]" % (','.join(export))) self.printer.writeline(None) self.printer.writeline("%s = runtime.Namespace(%s, context.clean_inheritance_tokens(), templateuri=%s, callables=make_namespace())" % (node.name, repr(node.name), node.parsed_attributes.get('file', 'None'))) + if eval(node.attributes.get('inheritable', "False")): + self.printer.writeline("self.%s = %s" % (node.name, node.name)) def visitDefTag(self, node): pass diff --git a/lib/mako/lexer.py b/lib/mako/lexer.py index 0b1d2b730cfa5dcfbbb7cfa4dc20f11671757a26..4b59c269e300ad4a4cc945aa669cd642ced8fc08 100644 --- a/lib/mako/lexer.py +++ b/lib/mako/lexer.py @@ -103,9 +103,7 @@ class Lexer(object): (\w+) # keyword - \s+ # some space - - ((?:\w+|=|".*?"|'.*?')*) # attrname, = sign, string expression + ((?:\s+\w+|=|".*?"|'.*?')*) # attrname, = sign, string expression \s* # more whitespace @@ -126,14 +124,17 @@ class Lexer(object): self.append_node(parsetree.Tag, keyword, attributes) if isend: self.tag.pop() + else: + if keyword == 'text': + match = self.match(r'.*?(?=\</%text>)', re.S) + if not match: + raise exceptions.SyntaxException("Unclosed tag: <%%%s>" % self.tag[-1].keyword, self.matched_lineno, self.matched_charpos) + return self.match_tag_end() return True else: return False def match_tag_end(self): -# if not len(self.tag): -# return False -# match = self.match(r'\</%\s*(.+?)' + self.tag[-1].keyword + '\s*>') match = self.match(r'\</%\s*(.+?)\s*>') if match: if not len(self.tag): diff --git a/lib/mako/parsetree.py b/lib/mako/parsetree.py index 4ee3cbae2ad33fbeb1eaf1c316e8fef302c3e70e..45e696dff82133f1fd8dd8456d0a5b73b6d9d7f0 100644 --- a/lib/mako/parsetree.py +++ b/lib/mako/parsetree.py @@ -222,11 +222,16 @@ class IncludeTag(Tag): class NamespaceTag(Tag): __keyword__ = 'namespace' def __init__(self, keyword, attributes, **kwargs): - super(NamespaceTag, self).__init__(keyword, attributes, ('file',), ('name',), ('name',), **kwargs) + super(NamespaceTag, self).__init__(keyword, attributes, ('file',), ('name','inheritable'), ('name',), **kwargs) self.name = attributes['name'] def declared_identifiers(self): return [self.name] - + +class TextTag(Tag): + __keyword__ = 'text' + def __init__(self, keyword, attributes, **kwargs): + super(TextTag, self).__init__(keyword, attributes, (), (), (), **kwargs) + class DefTag(Tag): __keyword__ = 'def' def __init__(self, keyword, attributes, **kwargs): diff --git a/lib/mako/runtime.py b/lib/mako/runtime.py index 1a81c094984b29cda3e5c4a96540928c49c97e68..1941ba6051218f5833a21c683e14f9e7b550f76f 100644 --- a/lib/mako/runtime.py +++ b/lib/mako/runtime.py @@ -93,7 +93,7 @@ class Namespace(object): if callables is not None: self.callables = dict([(c.func_name, c) for c in callables]) else: - self.callables = {} + self.callables = None if populate_self and self.template is not None: (lclcallable, self.context) = _populate_self_namespace(context, self.template, self_ns=self) diff --git a/test/lexer.py b/test/lexer.py index 8ca478bfdeb9cecd3191d8771e8be78b9d98104e..c673332b550904284fac938d2b06e25aee0650dd 100644 --- a/test/lexer.py +++ b/test/lexer.py @@ -71,6 +71,32 @@ class LexerTest(unittest.TestCase): except exceptions.CompileException, e: assert str(e) == "No such tag: 'lala' at line: 2 char: 13" + def test_text_tag(self): + template = """ + # comment + % if foo: + hi + % endif + <%text> + # more code + + % more code + <%illegal compionent>/></> + <%def name="laal">def</%def> + + + </%text> + + <%def name="foo">this is foo</%def> + + % if bar: + code + % endif + """ + node = Lexer(template).parse() + print repr(node) + assert repr(node) == """TemplateNode({}, [Comment('comment', (1, 1)), ControlLine('if', 'if foo:', False, (3, 1)), Text(' hi\n', (4, 1)), ControlLine('if', 'endif', True, (5, 1)), Text(' ', (6, 1)), TextTag('text', {}, (6, 9), []), Text('\n\n ', (14, 17)), DefTag('def', {'name': 'foo'}, (16, 9), ["Text('this is foo', (16, 26))"]), Text('\n', (16, 44)), ControlLine('if', 'if bar:', False, (17, 1)), Text(' code\n', (19, 1)), ControlLine('if', 'endif', True, (20, 1)), Text(' ', (21, 1))])""" + def test_def_syntax(self): template = """ <%def lala> @@ -162,7 +188,7 @@ class LexerTest(unittest.TestCase): ${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)), DefTag('def', {'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))])""" + 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)), DefTag('def', {'name': 'hi'}, (3, 9), ["Text('\\n give me ', (3, 25))", "Expression('foo()', [], (4, 21))", "Text(' and ', (4, 29))", "Expression('bar()', [], (4, 34))", "Text('\\n ', (4, 42))"]), Text('\n ', (5, 16)), Expression('hi()', [], (6, 9)), Text('\n', (6, 16))])""" def test_control_lines(self): template = """