Package qm :: Package external :: Package DocumentTemplate :: Module DT_Var
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_Var

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13  __doc__='''Variable insertion parameters 
 14   
 15      When inserting variables, parameters may be specified to 
 16      control how the data will be formatted.  In HTML source, the 
 17      'fmt' parameter is used to specify a C-style or custom format 
 18      to be used when inserting an object.  In EPFS source, the 'fmt' 
 19      parameter is only used for custom formats, a C-style format is 
 20      specified after the closing parenthesis. 
 21   
 22      Custom formats 
 23   
 24         A custom format is used when outputing user-defined 
 25         objects.  The value of a custom format is a method name to 
 26         be invoked on the object being inserted.  The method should 
 27         return an object that, when converted to a string, yields 
 28         the desired text.  For example, the DTML code:: 
 29   
 30            <dtml-var date fmt=DayOfWeek> 
 31   
 32         Inserts the result of calling the method 'DayOfWeek' of the 
 33         object bound to the variable 'date', with no arguments. 
 34   
 35         In addition to object methods, serveral additional custom 
 36         formats are available: 
 37   
 38             'whole-dollars' -- Show a numeric value with a dollar symbol. 
 39   
 40             'dollars-and-cents' -- Show a numeric value with a dollar 
 41               symbol and two decimal places. 
 42   
 43             'collection-length' -- Get the length of a collection of objects. 
 44   
 45         Note that when using the EPFS source format, both a 
 46         C-style and a custom format may be provided.  In this case, 
 47         the C-Style format is applied to the result of calling 
 48         the custom formatting method. 
 49   
 50      Null values and missing variables 
 51   
 52         In some applications, and especially in database applications, 
 53         data variables may alternate between "good" and "null" or 
 54         "missing" values.  A format that is used for good values may be 
 55         inappropriate for null values.  For this reason, the 'null' 
 56         parameter can be used to specify text to be used for null 
 57         values.  Null values are defined as values that: 
 58   
 59           - Cannot be formatted with the specified format, and 
 60   
 61           - Are either the special Python value 'None' or 
 62             are false and yield an empty string when converted to 
 63             a string. 
 64   
 65         For example, when showing a monitary value retrieved from a 
 66         database that is either a number or a missing value, the 
 67         following variable insertion might be used:: 
 68   
 69             <dtml-var cost fmt="$%.2d" null=\'n/a\'> 
 70   
 71         Missing values are providing for variables which are not 
 72         present in the name space, rather than raising an NameError, 
 73         you could do this: 
 74   
 75             <dtml-var cost missing=0> 
 76   
 77         and in this case, if cost was missing, it would be set to 0. 
 78         In the case where you want to deal with both at the same time, 
 79         you can use 'default': 
 80   
 81             <dtml-var description default=''> 
 82   
 83         In this case, it would use '' if the value was null or if the 
 84         variable was missing. 
 85   
 86      String manipulation 
 87   
 88         A number of special attributes are provided to transform the 
 89         value after formatting has been applied.  These parameters 
 90         are supplied without arguments. 
 91   
 92         'lower' --  cause all upper-case letters to be converted to lower case. 
 93   
 94         'upper' --  cause all upper-case letters to be converted to lower case. 
 95   
 96         'capitalize' -- cause the first character of the inserted value 
 97         to be converted to upper case. 
 98   
 99         'spacify' -- cause underscores in the inserted value to be 
100         converted to spaces. 
101   
102         'thousands_commas' -- cause commas to be inserted every three 
103         digits to the left of a decimal point in values containing 
104         numbers.  For example, the value, "12000 widgets" becomes 
105         "12,000 widgets". 
106   
107         'html_quote' -- convert characters that have special meaning 
108         in HTML to HTML character entities. 
109   
110         'url_quote' -- convert characters that have special meaning 
111         in URLS to HTML character entities using decimal values. 
112   
113         'url_quote_plus' -- like url_quote but also replace blank 
114         space characters with '+'. This is needed for building 
115         query strings in some cases. 
116   
117         'sql_quote' -- Convert single quotes to pairs of single 
118         quotes. This is needed to safely include values in 
119         Standard Query Language (SQL) strings. 
120   
121         'newline_to_br' -- Convert newlines and carriage-return and 
122         newline combinations to break tags. 
123   
124         'url' -- Get the absolute URL of the object by calling it\'s 
125         'absolute_url' method, if it has one. 
126   
127      Truncation 
128   
129         The attributes 'size' and 'etc'  can be used to truncate long 
130         strings.  If the 'size' attribute is specified, the string to 
131         be inserted is truncated at the given length.  If a space 
132         occurs in the second half of the truncated string, then the 
133         string is further truncated to the right-most space.  After 
134         truncation, the value given for the 'etc' attribute is added to 
135         the string.  If the 'etc' attribute is not provided, then '...' 
136         is used.  For example, if the value of spam is 
137         '"blah blah blah blah"', then the tag        
138         '<!--#var spam size=10-->' inserts '"blah blah ..."'. 
139   
140   
141  Evaluating expressions without rendering results 
142   
143     A 'call' tag is provided for evaluating named objects or expressions 
144     without rendering the result. 
145   
146   
147  ''' # ' 
148  __rcs_id__='$Id: DT_Var.py 1069 2008-11-13 21:55:43Z stefan $' 
149  __version__='$Revision: 1069 $'[11:-2] 
150   
151  from DT_Util import parse_params, name_param, html_quote, str 
152  import string, re, sys 
153  from urllib import quote, quote_plus 
154   
155 -class Var:
156 name='var' 157 expr=None 158
159 - def __init__(self, args, fmt='s'):
160 if args[:4]=='var ': args=args[4:] 161 args = parse_params(args, name='', lower=1, upper=1, expr='', 162 capitalize=1, spacify=1, null='', fmt='s', 163 size=0, etc='...', thousands_commas=1, 164 html_quote=1, url_quote=1, sql_quote=1, 165 url_quote_plus=1, missing='', 166 newline_to_br=1, url=1) 167 self.args=args 168 169 self.modifiers=tuple( 170 map(lambda t: t[1], 171 filter(lambda m, args=args, used=args.has_key: 172 used(m[0]) and args[m[0]], 173 modifiers))) 174 175 name, expr = name_param(args,'var',1) 176 177 self.__name__, self.expr = name, expr 178 self.fmt = fmt 179 180 if len(args)==1 and fmt=='s': 181 if expr is None: expr=name 182 else: expr=expr.eval 183 self.simple_form=(expr,)
184
185 - def render(self, md):
186 args=self.args 187 have_arg=args.has_key 188 name=self.__name__ 189 190 val=self.expr 191 192 if val is None: 193 if md.has_key(name): 194 if have_arg('url'): 195 val=md.getitem(name,0) 196 val=val.absolute_url() 197 else: 198 val = md[name] 199 else: 200 if have_arg('missing'): 201 return args['missing'] 202 else: 203 raise KeyError, name 204 else: 205 val=val.eval(md) 206 if have_arg('url'): val=val.absolute_url() 207 208 __traceback_info__=name, val, args 209 210 if have_arg('null') and not val and val != 0: 211 # check for null (false but not zero, including None, [], '') 212 return args['null'] 213 214 215 # handle special formats defined using fmt= first 216 if have_arg('fmt'): 217 fmt=args['fmt'] 218 if have_arg('null') and not val and val != 0: 219 try: 220 if hasattr(val, fmt): 221 val = getattr(val,fmt)() 222 elif special_formats.has_key(fmt): 223 val = special_formats[fmt](val, name, md) 224 elif fmt=='': val='' 225 else: val = fmt % val 226 except: 227 t, v= sys.exc_type, sys.exc_value 228 if hasattr(sys, 'exc_info'): t, v = sys.exc_info()[:2] 229 if val is None or not str(val): return args['null'] 230 raise t, v 231 232 else: 233 # We duplicate the code here to avoid exception handler 234 # which tends to screw up stack or leak 235 if hasattr(val, fmt): 236 val = getattr(val,fmt)() 237 elif special_formats.has_key(fmt): 238 val = special_formats[fmt](val, name, md) 239 elif fmt=='': val='' 240 else: val = fmt % val 241 242 # finally, pump it through the actual string format... 243 fmt=self.fmt 244 if fmt=='s': val=str(val) 245 else: val = ('%'+self.fmt) % (val,) 246 247 # next, look for upper, lower, etc 248 for f in self.modifiers: val=f(val) 249 250 if have_arg('size'): 251 size=args['size'] 252 try: size=int(size) 253 except: raise 'Document Error',( 254 '''a <code>size</code> attribute was used in a <code>var</code> 255 tag with a non-integer value.''') 256 if len(val) > size: 257 val=val[:size] 258 l=val.rfind(' ') 259 if l > size/2: 260 val=val[:l+1] 261 if have_arg('etc'): l=args['etc'] 262 else: l='...' 263 val=val+l 264 265 return val
266 267 __call__=render
268
269 -class Call:
270 name='call' 271 expr=None 272
273 - def __init__(self, args):
274 args = parse_params(args, name='', expr='') 275 name, expr = name_param(args,'call',1) 276 if expr is None: expr=name 277 else: expr=expr.eval 278 self.simple_form=(expr, None)
279 280
281 -def url_quote(v, name='(Unknown name)', md={}):
282 return quote(str(v))
283
284 -def url_quote_plus(v, name='(Unknown name)', md={}):
285 return quote_plus(str(v))
286
287 -def url_unquote(v, name='(Unknown name)', md={}):
288 return unquote(str(v))
289
290 -def url_unquote_plus(v, name='(Unknown name)', md={}):
291 return unquote_plus(str(v))
292
293 -def newline_to_br(v, name='(Unknown name)', md={}):
294 v=str(v) 295 if v.find('\r') >= 0: v=''.join(v.split('\r')) 296 if v.find('\n') >= 0: v='<br />\n'.join(v.split('\n')) 297 return v
298
299 -def whole_dollars(v, name='(Unknown name)', md={}):
300 try: return "$%d" % v 301 except: return ''
302
303 -def dollars_and_cents(v, name='(Unknown name)', md={}):
304 try: return "$%.2f" % v 305 except: return ''
306
307 -def thousands_commas(v, name='(Unknown name)', md={}, 308 thou=re.compile( 309 r"([0-9])([0-9][0-9][0-9]([,.]|$))").search):
310 v=str(v) 311 vl=v.split('.') 312 if not vl: return v 313 v=vl[0] 314 del vl[0] 315 if vl: s='.'+'.'.join(vl) 316 else: s='' 317 mo=thou(v) 318 while mo is not None: 319 l = mo.start(0) 320 v=v[:l+1]+','+v[l+1:] 321 mo=thou(v) 322 return v+s
323
324 -def whole_dollars_with_commas(v, name='(Unknown name)', md={}):
325 try: v= "$%d" % v 326 except: v='' 327 return thousands_commas(v)
328
329 -def dollars_and_cents_with_commas(v, name='(Unknown name)', md={}):
330 try: v= "$%.2f" % v 331 except: v= '' 332 return thousands_commas(v)
333
334 -def len_format(v, name='(Unknown name)', md={}):
335 return str(len(v))
336
337 -def len_comma(v, name='(Unknown name)', md={}):
338 return thousands_commas(str(len(v)))
339 340 StructuredText=None
341 -def structured_text(v, name='(Unknown name)', md={}):
342 global StructuredText 343 if StructuredText is None: import StructuredText 344 return str(StructuredText.html_with_references(str(v), 3))
345
346 -def sql_quote(v, name='(Unknown name)', md={}):
347 """Quote single quotes in a string by doubling them. 348 349 This is needed to securely insert values into sql 350 string literals in templates that generate sql. 351 """ 352 if v.find("'") >= 0: return v.replace("'", "''") 353 return v
354 355 special_formats={ 356 'whole-dollars': whole_dollars, 357 'dollars-and-cents': dollars_and_cents, 358 'collection-length': len_format, 359 'structured-text': structured_text, 360 361 # The rest are deprecated: 362 'sql-quote': sql_quote, 363 'html-quote': html_quote, 364 'url-quote': url_quote, 365 'url-quote-plus': url_quote_plus, 366 'url-unquote': url_unquote, 367 'url-unquote-plus': url_unquote_plus, 368 'multi-line': newline_to_br, 369 'comma-numeric': thousands_commas, 370 'dollars-with-commas': whole_dollars_with_commas, 371 'dollars-and-cents-with-commas': dollars_and_cents_with_commas, 372 } 373
374 -def spacify(val):
375 if val.find('_') >= 0: val=val.replace('_', ' ') 376 return val
377 378 modifiers=(html_quote, url_quote, url_quote_plus, url_unquote, 379 url_unquote_plus, newline_to_br, 380 string.lower, string.upper, string.capitalize, spacify, 381 thousands_commas, sql_quote, url_unquote, url_unquote_plus) 382 modifiers=map(lambda f: (f.__name__, f), modifiers) 383
384 -class Comment:
385 '''Comments 386 387 The 'comment' tag can be used to simply include comments 388 in DTML source. 389 390 For example:: 391 392 <!--#comment--> 393 394 This text is not rendered. 395 396 <!--#/comment--> 397 ''' 398 name='comment' 399 blockContinuations=() 400
401 - def __init__(self, args, fmt=''): pass
402
403 - def render(self, md):
404 return ''
405 406 __call__=render
407