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  # Zope Public License (ZPL) Version 1.0 
  4  # ------------------------------------- 
  5  #  
  6  # Copyright (c) Digital Creations.  All rights reserved. 
  7  #  
  8  # This license has been certified as Open Source(tm). 
  9  #  
 10  # Redistribution and use in source and binary forms, with or without 
 11  # modification, are permitted provided that the following conditions are 
 12  # met: 
 13  #  
 14  # 1. Redistributions in source code must retain the above copyright 
 15  #    notice, this list of conditions, and the following disclaimer. 
 16  #  
 17  # 2. Redistributions in binary form must reproduce the above copyright 
 18  #    notice, this list of conditions, and the following disclaimer in 
 19  #    the documentation and/or other materials provided with the 
 20  #    distribution. 
 21  #  
 22  # 3. Digital Creations requests that attribution be given to Zope 
 23  #    in any manner possible. Zope includes a "Powered by Zope" 
 24  #    button that is installed by default. While it is not a license 
 25  #    violation to remove this button, it is requested that the 
 26  #    attribution remain. A significant investment has been put 
 27  #    into Zope, and this effort will continue if the Zope community 
 28  #    continues to grow. This is one way to assure that growth. 
 29  #  
 30  # 4. All advertising materials and documentation mentioning 
 31  #    features derived from or use of this software must display 
 32  #    the following acknowledgement: 
 33  #  
 34  #      "This product includes software developed by Digital Creations 
 35  #      for use in the Z Object Publishing Environment 
 36  #      (http://www.zope.org/)." 
 37  #  
 38  #    In the event that the product being advertised includes an 
 39  #    intact Zope distribution (with copyright and license included) 
 40  #    then this clause is waived. 
 41  #  
 42  # 5. Names associated with Zope or Digital Creations must not be used to 
 43  #    endorse or promote products derived from this software without 
 44  #    prior written permission from Digital Creations. 
 45  #  
 46  # 6. Modified redistributions of any form whatsoever must retain 
 47  #    the following acknowledgment: 
 48  #  
 49  #      "This product includes software developed by Digital Creations 
 50  #      for use in the Z Object Publishing Environment 
 51  #      (http://www.zope.org/)." 
 52  #  
 53  #    Intact (re-)distributions of any official Zope release do not 
 54  #    require an external acknowledgement. 
 55  #  
 56  # 7. Modifications are encouraged but must be packaged separately as 
 57  #    patches to official Zope releases.  Distributions that do not 
 58  #    clearly separate the patches from the original work must be clearly 
 59  #    labeled as unofficial distributions.  Modifications which do not 
 60  #    carry the name Zope may be packaged in any form, as long as they 
 61  #    conform to all of the clauses above. 
 62  #  
 63  #  
 64  # Disclaimer 
 65  #  
 66  #   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY 
 67  #   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 68  #   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 69  #   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS 
 70  #   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 71  #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 72  #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 
 73  #   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
 74  #   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
 75  #   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
 76  #   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 77  #   SUCH DAMAGE. 
 78  #  
 79  #  
 80  # This software consists of contributions made by Digital Creations and 
 81  # many individuals on behalf of Digital Creations.  Specific 
 82  # attributions are listed in the accompanying credits file. 
 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   
227 -class Var:
228 name='var' 229 expr=None 230
231 - def __init__(self, args, fmt='s'):
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
257 - def render(self, md):
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 # check for null (false but not zero, including None, [], '') 284 return args['null'] 285 286 287 # handle special formats defined using fmt= first 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 # We duplicate the code here to avoid exception handler 306 # which tends to screw up stack or leak 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 # finally, pump it through the actual string format... 315 fmt=self.fmt 316 if fmt=='s': val=str(val) 317 else: val = ('%'+self.fmt) % (val,) 318 319 # next, look for upper, lower, etc 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
340
341 -class Call:
342 name='call' 343 expr=None 344
345 - def __init__(self, args):
346 args = parse_params(args, name='', expr='') 347 name, expr = name_param(args,'call',1) 348 if expr is None: expr=name 349 else: expr=expr.eval 350 self.simple_form=expr,None
351 352
353 -def url_quote(v, name='(Unknown name)', md={}):
354 return quote(str(v))
355
356 -def url_quote_plus(v, name='(Unknown name)', md={}):
357 return quote_plus(str(v))
358 359
360 -def newline_to_br(v, name='(Unknown name)', md={}):
361 v=str(v) 362 if v.find('\r') >= 0: v=''.join(v.split('\r')) 363 if v.find('\n') >= 0: v='<br />\n'.join(v.split('\n')) 364 return v
365
366 -def whole_dollars(v, name='(Unknown name)', md={}):
367 try: return "$%d" % v 368 except: return ''
369
370 -def dollars_and_cents(v, name='(Unknown name)', md={}):
371 try: return "$%.2f" % v 372 except: return ''
373
374 -def thousands_commas(v, name='(Unknown name)', md={}, 375 thou=re.compile( 376 r"([0-9])([0-9][0-9][0-9]([,.]|$))").search):
377 v=str(v) 378 vl=v.split('.') 379 if not vl: return v 380 v=vl[0] 381 del vl[0] 382 if vl: s='.'+'.'.join(vl) 383 else: s='' 384 mo=thou(v) 385 while mo is not None: 386 l = mo.start(0) 387 v=v[:l+1]+','+v[l+1:] 388 mo=thou(v) 389 return v+s
390
391 -def whole_dollars_with_commas(v, name='(Unknown name)', md={}):
392 try: v= "$%d" % v 393 except: v='' 394 return thousands_commas(v)
395
396 -def dollars_and_cents_with_commas(v, name='(Unknown name)', md={}):
397 try: v= "$%.2f" % v 398 except: v= '' 399 return thousands_commas(v)
400
401 -def len_format(v, name='(Unknown name)', md={}):
402 return str(len(v))
403
404 -def len_comma(v, name='(Unknown name)', md={}):
405 return thousands_commas(str(len(v)))
406 407 StructuredText=None
408 -def structured_text(v, name='(Unknown name)', md={}):
409 global StructuredText 410 if StructuredText is None: import StructuredText 411 return str(StructuredText.html_with_references(str(v), 3))
412
413 -def sql_quote(v, name='(Unknown name)', md={}):
414 """Quote single quotes in a string by doubling them. 415 416 This is needed to securely insert values into sql 417 string literals in templates that generate sql. 418 """ 419 if v.find("'") >= 0: return v.replace("'", "''") 420 return v
421 422 special_formats={ 423 'whole-dollars': whole_dollars, 424 'dollars-and-cents': dollars_and_cents, 425 'collection-length': len_format, 426 'structured-text': structured_text, 427 428 # The rest are depricated: 429 'sql-quote': sql_quote, 430 'html-quote': html_quote, 431 'url-quote': url_quote, 432 'url-quote-plus': url_quote_plus, 433 'multi-line': newline_to_br, 434 'comma-numeric': thousands_commas, 435 'dollars-with-commas': whole_dollars_with_commas, 436 'dollars-and-cents-with-commas': dollars_and_cents_with_commas, 437 } 438
439 -def spacify(val):
440 if val.find('_') >= 0: val=val.replace('_', ' ') 441 return val
442 443 modifiers=(html_quote, url_quote, url_quote_plus, newline_to_br, 444 string.lower, string.upper, string.capitalize, spacify, 445 thousands_commas, sql_quote) 446 modifiers=map(lambda f: (f.__name__, f), modifiers) 447
448 -class Comment:
449 '''Comments 450 451 The 'comment' tag can be used to simply include comments 452 in DTML source. 453 454 For example:: 455 456 <!--#comment--> 457 458 This text is not rendered. 459 460 <!--#/comment--> 461 ''' 462 name='comment' 463 blockContinuations=() 464
465 - def __init__(self, args, fmt=''): pass
466
467 - def render(self, md):
468 return ''
469 470 __call__=render
471