| Home | Trees | Indices | Help |
|---|
|
|
simple, elegant templating
(part of web.py)
Template design:
Template string is split into tokens and the tokens are combined into nodes.
Parse tree is a nodelist. TextNode and ExpressionNode are simple nodes and
for-loop, if-loop etc are block nodes, which contain multiple child nodes.
Each node can emit some python string. python string emitted by the
root node is validated for safeeval and executed using python in the given environment.
Enough care is taken to make sure the generated code and the template has line to line match,
so that the error messages can point to exact line number in template. (It doesn't work in some cases still.)
Grammar:
template -> defwith sections
defwith -> '$def with (' arguments ')' | ''
sections -> section*
section -> block | assignment | line
assignment -> '$ ' <assignment expression>
line -> (text|expr)*
text -> <any characters other than $>
expr -> '$' pyexpr | '$(' pyexpr ')' | '${' pyexpr '}'
pyexpr -> <python expression>
|
|||
|
Parser Parser Base. |
|||
|
PythonTokenizer Utility wrapper over python tokenizer. |
|||
| DefwithNode | |||
| TextNode | |||
| ExpressionNode | |||
| AssignmentNode | |||
| LineNode | |||
| BlockNode | |||
| ForNode | |||
| CodeNode | |||
| StatementNode | |||
| IfNode | |||
| ElseNode | |||
| ElifNode | |||
| DefNode | |||
| VarNode | |||
|
SuiteNode Suite is a list of sections. |
|||
|
ForLoop Wrapper for expression in for stament to support loop.xxx helpers. |
|||
|
ForLoopContext Stackable context for ForLoop to support nested for loops. |
|||
| BaseTemplate | |||
| Template | |||
| CompiledTemplate | |||
| GAE_Render | |||
|
Render The most preferred way of using templates. |
|||
|
render The most preferred way of using templates. |
|||
| ParseError | |||
|
SecurityError The template seems to be trying to do something naughty. |
|||
|
SafeVisitor Make sure code is safe by walking through the AST. |
|||
|
TemplateResult Dictionary like object for storing template output. |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
INDENT =
|
|||
STATEMENT_NODES = {'for': ForNode, 'while': BlockNode, 'if': I
|
|||
KEYWORDS =
|
|||
TEMPLATE_BUILTIN_NAMES =
|
|||
TEMPLATE_BUILTINS =
|
|||
_htmlquote_re = re.compile(r'
|
|||
_htmlquote_d =
|
|||
ALLOWED_AST_NODES =
|
|||
__package__ =
|
|||
name =
|
|||
|
|||
Splits the given text at newline. >>> splitline('foo\nbar') ('foo\n', 'bar') >>> splitline('foo') ('foo', '') >>> splitline('') ('', '') |
Encodes `text` for raw use in HTML. >>> websafe(u"<'&\">") u'<'&">' Unlike the websafe function in utils.py, this works with unicode text. |
Doctest for testing template module. Define a utility function to run template test. >>> class TestResult: ... def __init__(self, t): self.t = t ... def __getattr__(self, name): return getattr(self.t, name) ... def __repr__(self): return repr(unicode(self)) ... >>> def t(code, **keywords): ... tmpl = Template(code, **keywords) ... return lambda *a, **kw: TestResult(tmpl(*a, **kw)) ... Simple tests. >>> t('1')() u'1\n' >>> t('$def with ()\n1')() u'1\n' >>> t('$def with (a)\n$a')(1) u'1\n' >>> t('$def with (a=0)\n$a')(1) u'1\n' >>> t('$def with (a=0)\n$a')(a=1) u'1\n' Test complicated expressions. >>> t('$def with (x)\n$x.upper()')('hello') u'HELLO\n' >>> t('$(2 * 3 + 4 * 5)')() u'26\n' >>> t('${2 * 3 + 4 * 5}')() u'26\n' >>> t('$def with (limit)\nkeep $(limit)ing.')('go') u'keep going.\n' >>> t('$def with (a)\n$a.b[0]')(storage(b=[1])) u'1\n' Test html escaping. >>> t('$def with (x)\n$x', filename='a.html')('<html>') u'<html>\n' >>> t('$def with (x)\n$x', filename='a.txt')('<html>') u'<html>\n' Test if, for and while. >>> t('$if 1: 1')() u'1\n' >>> t('$if 1:\n 1')() u'1\n' >>> t('$if 1:\n 1\\')() u'1' >>> t('$if 0: 0\n$elif 1: 1')() u'1\n' >>> t('$if 0: 0\n$elif None: 0\n$else: 1')() u'1\n' >>> t('$if 0 < 1 and 1 < 2: 1')() u'1\n' >>> t('$for x in [1, 2, 3]: $x')() u'1\n2\n3\n' >>> t('$def with (d)\n$for k, v in d.iteritems(): $k')({1: 1}) u'1\n' >>> t('$for x in [1, 2, 3]:\n\t$x')() u' 1\n 2\n 3\n' >>> t('$def with (a)\n$while a and a.pop():1')([1, 2, 3]) u'1\n1\n1\n' The space after : must be ignored. >>> t('$if True: foo')() u'foo\n' Test loop.xxx. >>> t("$for i in range(5):$loop.index, $loop.parity")() u'1, odd\n2, even\n3, odd\n4, even\n5, odd\n' >>> t("$for i in range(2):\n $for j in range(2):$loop.parent.parity $loop.parity")() u'odd odd\nodd even\neven odd\neven even\n' Test assignment. >>> t('$ a = 1\n$a')() u'1\n' >>> t('$ a = [1]\n$a[0]')() u'1\n' >>> t('$ a = {1: 1}\n$a.keys()[0]')() u'1\n' >>> t('$ a = []\n$if not a: 1')() u'1\n' >>> t('$ a = {}\n$if not a: 1')() u'1\n' >>> t('$ a = -1\n$a')() u'-1\n' >>> t('$ a = "1"\n$a')() u'1\n' Test comments. >>> t('$# 0')() u'\n' >>> t('hello$#comment1\nhello$#comment2')() u'hello\nhello\n' >>> t('$#comment0\nhello$#comment1\nhello$#comment2')() u'\nhello\nhello\n' Test unicode. >>> t('$def with (a)\n$a')(u'\u203d') u'\u203d\n' >>> t('$def with (a)\n$a')(u'\u203d'.encode('utf-8')) u'\u203d\n' >>> t(u'$def with (a)\n$a $:a')(u'\u203d') u'\u203d \u203d\n' >>> t(u'$def with ()\nfoo')() u'foo\n' >>> def f(x): return x ... >>> t(u'$def with (f)\n$:f("x")')(f) u'x\n' >>> t('$def with (f)\n$:f("x")')(f) u'x\n' Test dollar escaping. >>> t("Stop, $$money isn't evaluated.")() u"Stop, $money isn't evaluated.\n" >>> t("Stop, \$money isn't evaluated.")() u"Stop, $money isn't evaluated.\n" Test space sensitivity. >>> t('$def with (x)\n$x')(1) u'1\n' >>> t('$def with(x ,y)\n$x')(1, 1) u'1\n' >>> t('$(1 + 2*3 + 4)')() u'11\n' Make sure globals are working. >>> t('$x')() Traceback (most recent call last): ... NameError: global name 'x' is not defined >>> t('$x', globals={'x': 1})() u'1\n' Can't change globals. >>> t('$ x = 2\n$x', globals={'x': 1})() u'2\n' >>> t('$ x = x + 1\n$x', globals={'x': 1})() Traceback (most recent call last): ... UnboundLocalError: local variable 'x' referenced before assignment Make sure builtins are customizable. >>> t('$min(1, 2)')() u'1\n' >>> t('$min(1, 2)', builtins={})() Traceback (most recent call last): ... NameError: global name 'min' is not defined Test vars. >>> x = t('$var x: 1')() >>> x.x u'1' >>> x = t('$var x = 1')() >>> x.x 1 >>> x = t('$var x: \n foo\n bar')() >>> x.x u'foo\nbar\n' Test BOM chars. >>> t('\xef\xbb\xbf$def with(x)\n$x')('foo') u'foo\n' Test for with weird cases. >>> t('$for i in range(10)[1:5]:\n $i')() u'1\n2\n3\n4\n' >>> t("$for k, v in {'a': 1, 'b': 2}.items():\n $k $v")() u'a 1\nb 2\n' >>> t("$for k, v in ({'a': 1, 'b': 2}.items():\n $k $v")() Traceback (most recent call last): ... SyntaxError: invalid syntax Test datetime. >>> import datetime >>> t("$def with (date)\n$date.strftime('%m %Y')")(datetime.datetime(2009, 1, 1)) u'01 2009\n' |
|
|||
STATEMENT_NODES
|
TEMPLATE_BUILTIN_NAMES
|
TEMPLATE_BUILTINS
|
_htmlquote_d
|
ALLOWED_AST_NODES
|
| Home | Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 on Wed Aug 4 09:57:29 2010 | http://epydoc.sourceforge.net |