changeset 104:f12e7987d7f4 trunk

Added `py:with` directive based on Jonas' patch in #17.
author cmlenz
date Thu, 27 Jul 2006 09:22:17 +0000
parents 0f246a30d3a7
children 71f3db26eecb
files markup/template.py markup/tests/template.py
diffstat 2 files changed, 67 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/markup/template.py
+++ b/markup/template.py
@@ -619,6 +619,47 @@
         return _apply_directives(stream, ctxt, directives)
 
 
+class WithDirective(Directive):
+    """Implementation of the `py:with` template directive, which allows
+    shorthand access to variables and expressions.
+    
+    >>> tmpl = Template('''<div xmlns:py="http://markup.edgewall.org/">
+    ...   <span py:with="y=7; z=x+10">$x $y $z</span>
+    ... </div>''')
+    >>> print tmpl.generate(Context(x=42))
+    <div>
+      <span>42 7 52</span>
+    </div>
+    """
+    __slots__ = ['vars']
+
+    ATTRIBUTE = 'vars'
+
+    def __init__(self, value, filename=None, lineno=-1, offset=-1):
+        Directive.__init__(self, None, filename, lineno, offset)
+        self.vars = []
+        try:
+            for stmt in value.split(';'):
+                name, value = stmt.split('=', 1)
+                self.vars.append((name.strip(),
+                                  Expression(value.strip(), filename, lineno)))
+        except SyntaxError, err:
+            raise TemplateSyntaxError(err, filename, lineno,
+                                      offset + (err.offset or 0))
+
+    def __call__(self, stream, ctxt, directives):
+        ctxt.push(dict([(name, expr.evaluate(ctxt))
+                        for name, expr in self.vars]))
+        for event in _apply_directives(stream, ctxt, directives):
+            yield event
+        ctxt.pop()
+
+    def __repr__(self):
+        return '<%s "%s">' % (self.__class__.__name__,
+                              '; '.join(['%s = %s' % (name, expr.source)
+                                         for name, expr in self.vars]))
+
+
 class Template(object):
     """Can parse a template and transform it into the corresponding output
     based on context data.
@@ -635,6 +676,7 @@
                   ('when', WhenDirective),
                   ('otherwise', OtherwiseDirective),
                   ('choose', ChooseDirective),
+                  ('with', WithDirective),
                   ('replace', ReplaceDirective),
                   ('content', ContentDirective),
                   ('attrs', AttrsDirective),
--- a/markup/tests/template.py
+++ b/markup/tests/template.py
@@ -414,6 +414,30 @@
         </div>""", str(tmpl.generate()))
 
 
+class WithDirectiveTestCase(unittest.TestCase):
+    """Tests for the `py:with` template directive."""
+
+    def test_shadowing(self):
+        tmpl = Template("""<div xmlns:py="http://markup.edgewall.org/">
+          ${x}
+          <span py:with="x = x * 2" py:replace="x"/>
+          ${x}
+        </div>""")
+        self.assertEqual("""<div>
+          42
+          84
+          42
+        </div>""", str(tmpl.generate(Context(x=42))))
+
+    def test_as_element(self):
+        tmpl = Template("""<div xmlns:py="http://markup.edgewall.org/">
+          <py:with vars="x = x * 2">${x}</py:with>
+        </div>""")
+        self.assertEqual("""<div>
+          84
+        </div>""", str(tmpl.generate(Context(x=42))))
+
+
 class TemplateTestCase(unittest.TestCase):
     """Tests for basic template processing, expression evaluation and error
     reporting.
@@ -578,6 +602,7 @@
     suite.addTest(unittest.makeSuite(IfDirectiveTestCase, 'test'))
     suite.addTest(unittest.makeSuite(MatchDirectiveTestCase, 'test'))
     suite.addTest(unittest.makeSuite(StripDirectiveTestCase, 'test'))
+    suite.addTest(unittest.makeSuite(WithDirectiveTestCase, 'test'))
     return suite
 
 if __name__ == '__main__':
Copyright (C) 2012-2017 Edgewall Software