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 __doc__='''Variable insertion parameters
86
87 When inserting variables, parameters may be specified to
88 control how the data will be formatted. In HTML source, the
89 'fmt' parameter is used to specify a C-style or custom format
90 to be used when inserting an object. In EPFS source, the 'fmt'
91 parameter is only used for custom formats, a C-style format is
92 specified after the closing parenthesis.
93
94 Custom formats
95
96 A custom format is used when outputing user-defined
97 objects. The value of a custom format is a method name to
98 be invoked on the object being inserted. The method should
99 return an object that, when converted to a string, yields
100 the desired text. For example, the HTML source::
101
102 <!--#var date fmt=DayOfWeek-->
103
104 Inserts the result of calling the method 'DayOfWeek' of the
105 object bound to the variable 'date', with no arguments.
106
107 In addition to object methods, serveral additional custom
108 formats are available:
109
110 'whole-dollars' -- Show a numeric value with a dollar symbol.
111
112 'dollars-and-cents' -- Show a numeric value with a dollar
113 symbol and two decimal places.
114
115 'collection-length' -- Get the length of a collection of objects.
116
117 Note that when using the EPFS source format, both a
118 C-style and a custom format may be provided. In this case,
119 the C-Style format is applied to the result of calling
120 the custom formatting method.
121
122 Null values and missing variables
123
124 In some applications, and especially in database applications,
125 data variables may alternate between "good" and "null" or
126 "missing" values. A format that is used for good values may be
127 inappropriate for null values. For this reason, the 'null'
128 parameter can be used to specify text to be used for null
129 values. Null values are defined as values that:
130
131 - Cannot be formatted with the specified format, and
132
133 - Are either the special Python value 'None' or
134 are false and yield an empty string when converted to
135 a string.
136
137 For example, when showing a monitary value retrieved from a
138 database that is either a number or a missing value, the
139 following variable insertion might be used::
140
141 <dtml-var cost fmt="$%.2d" null=\'n/a\'>
142
143 Missing values are providing for variables which are not
144 present in the name space, rather than raising an NameError,
145 you could do this:
146
147 <dtml-var cost missing=0>
148
149 and in this case, if cost was missing, it would be set to 0.
150 In the case where you want to deal with both at the same time,
151 you can use 'default':
152
153 <dtml-var description default=''>
154
155 In this case, it would use '' if the value was null or if the
156 variable was missing.
157
158 String manipulation
159
160 A number of special attributes are provided to transform the
161 value after formatting has been applied. These parameters
162 are supplied without arguments.
163
164 'lower' -- cause all upper-case letters to be converted to lower case.
165
166 'upper' -- cause all upper-case letters to be converted to lower case.
167
168 'capitalize' -- cause the first character of the inserted value
169 to be converted to upper case.
170
171 'spacify' -- cause underscores in the inserted value to be
172 converted to spaces.
173
174 'thousands_commas' -- cause commas to be inserted every three
175 digits to the left of a decimal point in values containing
176 numbers. For example, the value, "12000 widgets" becomes
177 "12,000 widgets".
178
179 'html_quote' -- convert characters that have special meaning
180 in HTML to HTML character entities.
181
182 'url_quote' -- convert characters that have special meaning
183 in URLS to HTML character entities using decimal values.
184
185 'url_quote_plus' -- like url_quote but also replace blank
186 space characters with '+'. This is needed for building
187 query strings in some cases.
188
189 'sql_quote' -- Convert single quotes to pairs of single
190 quotes. This is needed to safely include values in
191 Standard Query Language (SQL) strings.
192
193 'newline_to_br' -- Convert newlines and carriage-return and
194 newline combinations to break tags.
195
196 'url' -- Get the absolute URL of the object by calling it\'s
197 'absolute_url' method, if it has one.
198
199 Truncation
200
201 The attributes 'size' and 'etc' can be used to truncate long
202 strings. If the 'size' attribute is specified, the string to
203 be inserted is truncated at the given length. If a space
204 occurs in the second half of the truncated string, then the
205 string is further truncated to the right-most space. After
206 truncation, the value given for the 'etc' attribute is added to
207 the string. If the 'etc' attribute is not provided, then '...'
208 is used. For example, if the value of spam is
209 '"blah blah blah blah"', then the tag
210 '<!--#var spam size=10-->' inserts '"blah blah ..."'.
211
212
213 Evaluating expressions without rendering results
214
215 A 'call' tag is provided for evaluating named objects or expressions
216 without rendering the result.
217
218
219 '''
220 __rcs_id__='$Id: DT_Var.py 1007 2007-02-10 01:07:28Z stefan $'
221 __version__='$Revision: 1007 $'[11:-2]
222
223 from DT_Util import parse_params, name_param, html_quote, str
224 import string, re, sys
225 from urllib import quote, quote_plus
226
228 name='var'
229 expr=None
230
232 if args[:4]=='var ': args=args[4:]
233 args = parse_params(args, name='', lower=1, upper=1, expr='',
234 capitalize=1, spacify=1, null='', fmt='s',
235 size=0, etc='...', thousands_commas=1,
236 html_quote=1, url_quote=1, sql_quote=1,
237 url_quote_plus=1, missing='',
238 newline_to_br=1, url=1)
239 self.args=args
240
241 self.modifiers=tuple(
242 map(lambda t: t[1],
243 filter(lambda m, args=args, used=args.has_key:
244 used(m[0]) and args[m[0]],
245 modifiers)))
246
247 name, expr = name_param(args,'var',1)
248
249 self.__name__, self.expr = name, expr
250 self.fmt = fmt
251
252 if len(args)==1 and fmt=='s':
253 if expr is None: expr=name
254 else: expr=expr.eval
255 self.simple_form=expr,
256
258 args=self.args
259 have_arg=args.has_key
260 name=self.__name__
261
262 val=self.expr
263
264 if val is None:
265 if md.has_key(name):
266 if have_arg('url'):
267 val=md.getitem(name,0)
268 val=val.absolute_url()
269 else:
270 val = md[name]
271 else:
272 if have_arg('missing'):
273 return args['missing']
274 else:
275 raise KeyError, name
276 else:
277 val=val.eval(md)
278 if have_arg('url'): val=val.absolute_url()
279
280 __traceback_info__=name, val, args
281
282 if have_arg('null') and not val and val != 0:
283
284 return args['null']
285
286
287
288 if have_arg('fmt'):
289 fmt=args['fmt']
290 if have_arg('null') and not val and val != 0:
291 try:
292 if hasattr(val, fmt):
293 val = getattr(val,fmt)()
294 elif special_formats.has_key(fmt):
295 val = special_formats[fmt](val, name, md)
296 elif fmt=='': val=''
297 else: val = fmt % val
298 except:
299 t, v= sys.exc_type, sys.exc_value
300 if hasattr(sys, 'exc_info'): t, v = sys.exc_info()[:2]
301 if val is None or not str(val): return args['null']
302 raise t, v
303
304 else:
305
306
307 if hasattr(val, fmt):
308 val = getattr(val,fmt)()
309 elif special_formats.has_key(fmt):
310 val = special_formats[fmt](val, name, md)
311 elif fmt=='': val=''
312 else: val = fmt % val
313
314
315 fmt=self.fmt
316 if fmt=='s': val=str(val)
317 else: val = ('%'+self.fmt) % (val,)
318
319
320 for f in self.modifiers: val=f(val)
321
322 if have_arg('size'):
323 size=args['size']
324 try: size=int(size)
325 except: raise 'Document Error',(
326 '''a <code>size</code> attribute was used in a <code>var</code>
327 tag with a non-integer value.''')
328 if len(val) > size:
329 val=val[:size]
330 l=val.rfind(' ')
331 if l > size/2:
332 val=val[:l+1]
333 if have_arg('etc'): l=args['etc']
334 else: l='...'
335 val=val+l
336
337 return val
338
339 __call__=render