1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
The templating language is fairly simple, just {{stuff}}. For
example::
>>> from paste.util.template import Template, sub
>>> sub('Hi {{name}}', name='Ian')
'Hi Ian'
>>> Template('Hi {{repr(name)}}').substitute(name='Ian')
"Hi 'Ian'"
>>> Template('Hi {{name+1}}').substitute(name='Ian') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
TypeError: cannot concatenate 'str' and 'int' objects at line 1 column 6
It also has Django-style piping::
>>> sub('Hi {{name|repr}}', name='Ian')
"Hi 'Ian'"
Note that None shows up as an empty string::
>>> sub('Hi {{name}}', name=None)
'Hi '
And if/elif/else::
>>> t = Template('{{if x}}{{y}}{{else}}{{z}}{{endif}}')
>>> t.substitute(x=1, y=2, z=3)
'2'
>>> t.substitute(x=0, y=2, z=3)
'3'
>>> t = Template('{{if x > 0}}positive{{elif x < 0}}negative{{else}}zero{{endif}}')
>>> t.substitute(x=1), t.substitute(x=-10), t.substitute(x=0)
('positive', 'negative', 'zero')
Plus a for loop::
>>> t = Template('{{for i in x}}i={{i}}\n{{endfor}}')
>>> t.substitute(x=range(3))
'i=0\ni=1\ni=2\n'
>>> t = Template('{{for a, b in sorted(z.items()):}}{{a}}={{b}},{{endfor}}')
>>> t.substitute(z={1: 2, 3: 4})
'1=2,3=4,'
>>> t = Template('{{for i in x}}{{if not i}}{{break}}'
... '{{endif}}{{i}} {{endfor}}')
>>> t.substitute(x=[1, 2, 0, 3, 4])
'1 2 '
>>> t = Template('{{for i in x}}{{if not i}}{{continue}}'
... '{{endif}}{{i}} {{endfor}}')
>>> t.substitute(x=[1, 2, 0, 3, 0, 4])
'1 2 3 4 '
Also Python blocks::
>>> sub('{{py:\nx=1\n}}{{x}}')
'1'
And some syntax errors::
>>> t = Template('{{if x}}', name='foo.html')
Traceback (most recent call last):
...
TemplateError: No {{endif}} at line 1 column 3 in foo.html
>>> t = Template('{{for x}}', name='foo2.html')
Traceback (most recent call last):
...
TemplateError: Bad for (no "in") in 'x' at line 1 column 3 in foo2.html
There's also an HTMLTemplate that uses HTMLisms::
>>> from paste.util.template import HTMLTemplate, sub_html, html
>>> sub_html('hi {{name}}', name='<foo>')
'hi <foo>'
But if you don't want quoting to happen you can do::
>>> sub_html('hi {{name}}', name=html('<foo>'))
'hi <foo>'
>>> sub_html('hi {{name|html}}', name='<foo>')
'hi <foo>'
Also a couple handy functions;:
>>> t = HTMLTemplate('<a href="article?id={{id|url}}" {{attr(class_=class_)}}>')
>>> t.substitute(id=1, class_='foo')
'<a href="article?id=1" class="foo">'
>>> t.substitute(id='with space', class_=None)
'<a href="article?id=with%20space" >'
There's a handyish looper thing you can also use in your templates (or
in Python, but it's more useful in templates generally)::
>>> from paste.util.looper import looper
>>> seq = ['apple', 'asparagus', 'Banana', 'orange']
>>> for loop, item in looper(seq):
... if item == 'apple':
... assert loop.first
... elif item == 'orange':
... assert loop.last
... if loop.first_group(lambda i: i[0].upper()):
... print('%s:' % item[0].upper())
... print("%s %s" % (loop.number, item))
A:
1 apple
2 asparagus
B:
3 Banana
O:
4 orange
It will also strip out empty lines, when there is a line that only
contains a directive/statement (if/for, etc)::
>>> sub('{{if 1}}\n{{x}}\n{{endif}}\n', x=0)
'0\n'
>>> sub('{{if 1}}x={{x}}\n{{endif}}\n', x=1)
'x=1\n'
>>> sub('{{if 1}}\nx={{x}}\n{{endif}}\n', x=1)
'x=1\n'
Lastly, there is a special directive that will create a default value
for a variable, if no value is given::
>>> sub('{{default x=1}}{{x}}', x=2)
'2'
>>> sub('{{default x=1}}{{x}}')
'1'
>>> # The normal case:
>>> sub('{{x}}') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
NameError: name 'x' is not defined at line 1 column 3
And comments work::
>>> sub('Test=x{{#whatever}}')
'Test=x'
|