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

Source Code for Module qm.external.DocumentTemplate.DT_Try

  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   
 86  import string, sys, traceback 
 87  from cStringIO import StringIO 
 88  from DT_Util import ParseError, parse_params, render_blocks 
 89  from DT_Util import namespace, InstanceDict 
 90  from DT_Return import DTReturn 
 91   
92 -class Try:
93 """Zope DTML Exception handling 94 95 usage: 96 97 <!--#try--> 98 <!--#except SomeError AnotherError--> 99 <!--#except YetAnotherError--> 100 <!--#except--> 101 <!--#else--> 102 <!--#/try--> 103 104 or: 105 106 <!--#try--> 107 <!--#finally--> 108 <!--#/try--> 109 110 The DTML try tag functions quite like Python's try command. 111 112 The contents of the try tag are rendered. If an exception is raised, 113 then control switches to the except blocks. The first except block to 114 match the type of the error raised is rendered. If an except block has 115 no name then it matches all raised errors. 116 117 The try tag understands class-based exceptions, as well as string-based 118 exceptions. Note: the 'raise' tag raises string-based exceptions. 119 120 Inside the except blocks information about the error is available via 121 three variables. 122 123 'error_type' -- This variable is the name of the exception caught. 124 125 'error_value' -- This is the caught exception's value. 126 127 'error_tb' -- This is a traceback for the caught exception. 128 129 The optional else block is rendered when no exception occurs in the 130 try block. Exceptions in the else block are not handled by the preceding 131 except blocks. 132 133 The try..finally form specifies a `cleanup` block, to be rendered even 134 when an exception occurs. Note that any rendered result is discarded if 135 an exception occurs in either the try or finally blocks. The finally block 136 is only of any use if you need to clean up something that will not be 137 cleaned up by the transaction abort code. 138 139 The finally block will always be called, wether there was an exception in 140 the try block or not, or wether or not you used a return tag in the try 141 block. Note that any output of the finally block is discarded if you use a 142 return tag in the try block. 143 144 If an exception occurs in the try block, and an exception occurs in the 145 finally block, or you use the return tag in that block, any information 146 about that first exception is lost. No information about the first 147 exception is available in the finally block. Also, if you use a return tag 148 in the try block, and an exception occurs in the finally block or you use 149 a return tag there as well, the result returned in the try block will be 150 lost. 151 152 Original version by Jordan B. Baker. 153 154 Try..finally and try..else implementation by Martijn Pieters. 155 """ 156 157 name = 'try' 158 blockContinuations = 'except', 'else', 'finally' 159 finallyBlock=None 160 elseBlock=None 161
162 - def __init__(self, blocks):
163 tname, args, section = blocks[0] 164 165 self.args = parse_params(args) 166 self.section = section.blocks 167 168 169 # Find out if this is a try..finally type 170 if len(blocks) == 2 and blocks[1][0] == 'finally': 171 self.finallyBlock = blocks[1][2].blocks 172 173 # This is a try [except]* [else] block. 174 else: 175 # store handlers as tuples (name,block) 176 self.handlers = [] 177 defaultHandlerFound = 0 178 179 for tname,nargs,nsection in blocks[1:]: 180 if tname == 'else': 181 if not self.elseBlock is None: 182 raise ParseError, ( 183 'No more than one else block is allowed', 184 self.name) 185 self.elseBlock = nsection.blocks 186 187 elif tname == 'finally': 188 raise ParseError, ( 189 'A try..finally combination cannot contain ' 190 'any other else, except or finally blocks', 191 self.name) 192 193 else: 194 if not self.elseBlock is None: 195 raise ParseError, ( 196 'The else block should be the last block ' 197 'in a try tag', self.name) 198 199 for errname in string.split(nargs): 200 self.handlers.append((errname,nsection.blocks)) 201 if string.strip(nargs)=='': 202 if defaultHandlerFound: 203 raise ParseError, ( 204 'Only one default exception handler ' 205 'is allowed', self.name) 206 else: 207 defaultHandlerFound = 1 208 self.handlers.append(('',nsection.blocks))
209
210 - def render(self, md):
211 if (self.finallyBlock is None): 212 return self.render_try_except(md) 213 else: 214 return self.render_try_finally(md)
215
216 - def render_try_except(self, md):
217 result = '' 218 219 # first we try to render the first block 220 try: 221 result = render_blocks(self.section, md) 222 except DTReturn: 223 raise 224 except: 225 # but an error occurs.. save the info. 226 t,v = sys.exc_info()[:2] 227 if type(t)==type(''): 228 errname = t 229 else: 230 errname = t.__name__ 231 232 handler = self.find_handler(t) 233 234 if handler is None: 235 # we didn't find a handler, so reraise the error 236 raise 237 238 # found the handler block, now render it 239 try: 240 f=StringIO() 241 traceback.print_exc(100,f) 242 error_tb=f.getvalue() 243 ns = namespace(md, error_type=errname, error_value=v, 244 error_tb=error_tb)[0] 245 md._push(InstanceDict(ns,md)) 246 return render_blocks(handler, md) 247 finally: 248 md._pop(1) 249 250 else: 251 # No errors have occured, render the optional else block 252 if (self.elseBlock is None): 253 return result 254 else: 255 return result + render_blocks(self.elseBlock, md)
256
257 - def render_try_finally(self, md):
258 result = '' 259 # first try to render the first block 260 try: 261 result = render_blocks(self.section, md) 262 # Then handle finally block 263 finally: 264 result = result + render_blocks(self.finallyBlock, md) 265 return result
266
267 - def find_handler(self,exception):
268 "recursively search for a handler for a given exception" 269 if type(exception)==type(''): 270 for e,h in self.handlers: 271 if exception==e or e=='': 272 return h 273 else: 274 return None 275 for e,h in self.handlers: 276 if e==exception.__name__ or e=='' or self.match_base(exception,e): 277 return h 278 return None
279
280 - def match_base(self,exception,name):
281 for base in exception.__bases__: 282 if base.__name__==name or self.match_base(base,name): 283 return 1 284 return None
285 286 __call__ = render
287