|
[Webware-checkins] CVS: Webware/WebKit Application.py,1.129,1.130 ExceptionHandler.py,1.12,1.13 HTTPRequest.py,1.36,1.37 HTTPResponse.py,1.16,1.17 Message.py,1.3,1.4 Page.py,1.18,1.19 Response.py,1.2,1.3 Session.py,1.20,1.21 Transaction.py,1.10,1.11
From: Chuck Esterbrook <echuck@us...> - 2002-02-13 07:11
|
Update of /cvsroot/webware/Webware/WebKit
In directory usw-pr-cvs1:/tmp/cvs-serv10431
Modified Files:
Application.py ExceptionHandler.py HTTPRequest.py
HTTPResponse.py Message.py Page.py Response.py Session.py
Transaction.py
Log Message:
Restructured ExceptionHandler to ask the transaction to writeExceptionReport() which then asks each of it's objects. This adds some new variables, the Session and now provides a hook to servlets.
Index: Application.py
===================================================================
RCS file: /cvsroot/webware/Webware/WebKit/Application.py,v
retrieving revision 1.129
retrieving revision 1.130
diff -C2 -d -r1.129 -r1.130
*** Application.py 1 Feb 2002 08:54:06 -0000 1.129
--- Application.py 13 Feb 2002 07:11:13 -0000 1.130
***************
*** 1315,1319 ****
return ssPath, urlPath, extraURLPath
!
--- 1315,1323 ----
return ssPath, urlPath, extraURLPath
! def writeExceptionReport(self, handler):
! # Nothing particularly useful that I can think of needs to be
! # added to the exception reports by the Application.
! # See ExceptionHandler.py for more info.
! pass
Index: ExceptionHandler.py
===================================================================
RCS file: /cvsroot/webware/Webware/WebKit/ExceptionHandler.py,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -d -r1.12 -r1.13
*** ExceptionHandler.py 1 Feb 2002 08:33:43 -0000 1.12
--- ExceptionHandler.py 13 Feb 2002 07:11:13 -0000 1.13
***************
*** 3,8 ****
from time import asctime, localtime
from WebUtils.HTMLForException import HTMLForException
! from WebUtils.Funcs import htmlForDict
from HTTPResponse import HTTPResponse
--- 3,12 ----
from time import asctime, localtime
from WebUtils.HTMLForException import HTMLForException
! from WebUtils.Funcs import htmlForDict, htmlEncode
from HTTPResponse import HTTPResponse
+ from types import DictType
+
+
+ class singleton: pass
***************
*** 13,16 ****
--- 17,39 ----
After handling an exception, it should be removed.
+ At some point, the exception handler sends "writeExceptionReport"
+ to the transaction, which in turn sends it to the other transactional objects (application, request, response, etc.)
+ The handler is the single argument for this message.
+
+ Classes may find it useful to do things like this:
+
+ exceptionReportAttrs = 'foo bar baz'.split()
+ def writeExceptionReport(self, handler):
+ handler.writeTitle(self.__class__.__name__)
+ handler.writeAttrs(self, self.exceptionReportAttrs)
+
+ The handler write methods that may be useful are:
+ def write(self, s):
+ def writeln(self, s):
+ def writeTitle(self, s):
+ def writeDict(self, d):
+ def writeTable(self, listOfDicts, keys=None):
+ def writeAttrs(self, obj, attrNames):
+
See the WebKit.html documentation for other information.
'''
***************
*** 48,54 ****
def servletPathname(self):
! return self._tra.request().pathTranslated()
! # @@ 2000-05-01 ce: What should this be?
! # @@ 2000-06-28 ce: probaby servletURL()
def basicServletName(self):
--- 71,78 ----
def servletPathname(self):
! try:
! return self._tra.request().serverSidePath()
! except:
! return None
def basicServletName(self):
***************
*** 125,158 ****
def htmlDebugInfo(self):
''' Return HTML-formatted debugging information about the current exception. '''
! html = ['''
! %s
! <p> <i>%s</i>
! ''' % (htTitle('Traceback'), self.servletPathname())]
! html.append(HTMLForException(self._exc))
- html.extend([
- htTitle('Misc Info'),
- htmlForDict({
- 'time': asctime(localtime(self._res.endTime())),
- 'filename': self.servletPathname(),
- 'os.getcwd()': os.getcwd(),
- 'sys.path': sys.path
- }),
- htTitle('Fields'), htmlForDict(self._req.fields()),
- htTitle('Headers'), htmlForDict(self._res.headers()),
- htTitle('Environment'), htmlForDict(self._req.environ(), {'PATH': ';'}),
- htTitle('Ids'), htTable(osIdTable(), ['name', 'value'])])
- # @@ 2000-05-01 ce: Shouldn't we be asking each of the objects (transaction, request, response, ...) for it's debugging info to append? That would be more OOPish.
if self.setting('IncludeFancyTraceback'):
! html.append(htTitle('Fancy Traceback'))
try:
from WebUtils.ExpansiveHTMLForException import ExpansiveHTMLForException
! html.append(ExpansiveHTMLForException(context=self.setting('FancyTracebackContext')))
except:
! html.append('Unable to generate a fancy traceback!')
!
! return string.join(html, '')
def saveErrorPage(self, html):
--- 149,279 ----
def htmlDebugInfo(self):
''' Return HTML-formatted debugging information about the current exception. '''
! self.html = []
! self.writeHTML()
! html = ''.join(self.html)
! self.html = None
! return html
! def writeHTML(self):
! self.writeTraceback()
! self.writeMiscInfo()
! self.writeTransaction()
! self.writeEnvironment()
! self.writeIds()
! self.writeFancyTraceback()
+ ## Write utility methods ##
+
+ def write(self, s):
+ self.html.append(str(s))
+
+ def writeln(self, s):
+ self.html.append(str(s))
+ self.html.append('\n')
+
+ def writeTitle(self, s):
+ self.writeln(htTitle(s))
+
+ def writeDict(self, d):
+ self.writeln(htmlForDict(d))
+
+ def writeTable(self, listOfDicts, keys=None):
+ """
+ Writes a table whose contents are given by listOfDicts. The
+ keys of each dictionary are expected to be the same. If the
+ keys arg is None, the headings are taken in alphabetical order
+ from the first dictionary. If listOfDicts is "false", nothing
+ happens.
+
+ Caveat: There's no way to influence the formatting or to use
+ column titles that are different than the keys.
+ """
+ if not listOfDicts:
+ return
+
+ if keys is None:
+ keys = listOfDicts[0].keys()
+ keys.sort()
+
+ wr = self.writeln
+ wr('<table>\n<tr>')
+ for key in keys:
+ wr('<td bgcolor=#F0F0F0><b>%s</b></td>' % key)
+ wr('</tr>\n')
+
+ for row in listOfDicts:
+ wr('<tr>')
+ for key in keys:
+ wr('<td bgcolor=#F0F0F0>%s</td>' % row[key])
+ wr('</tr>\n')
+
+ wr('</table>')
+
+ def writeAttrs(self, obj, attrNames):
+ """
+ Writes the attributes of the object as given by attrNames.
+ Tries obj._name first, followed by obj.name(). Is resilient
+ regarding exceptions so as not to not ever spoil the
+ exception report.
+ """
+ rows = []
+ for name in attrNames:
+ value = getattr(obj, '_'+name, singleton) # go for data attribute
+ try:
+ if value is singleton:
+ value = getattr(obj, name, singleton) # go for method
+ if value is singleton:
+ value = '(could not find attribute or method)'
+ else:
+ try:
+ value = value()
+ except Exception, e:
+ value = '(exception during method call: %s: %s)' % (e.__class__.__name__, e)
+ value = self.repr(value)
+ else:
+ value = self.repr(value)
+ except Exception, e:
+ value = '(exception during value processing: %s: %s)' % (e.__class__.__name__, e)
+ rows.append({'attr': name, 'value': value})
+ self.writeTable(rows, ('attr', 'value'))
+
+
+ ## Write specific parts ##
+
+ def writeTraceback(self):
+ self.writeTitle('Traceback')
+ self.write('<p> <i>%s</i>' % self.servletPathname())
+ self.write(HTMLForException(self._exc))
+
+ def writeMiscInfo(self):
+ self.writeTitle('MiscInfo')
+ info = {
+ 'time': asctime(localtime(self._res.endTime())),
+ 'filename': self.servletPathname(),
+ 'os.getcwd()': os.getcwd(),
+ 'sys.path': sys.path
+ }
+ self.writeDict(info)
+
+ def writeTransaction(self):
+ self._tra.writeExceptionReport(self)
+
+ def writeEnvironment(self):
+ self.writeTitle('Environment')
+ self.writeDict(os.environ)
+
+ def writeIds(self):
+ self.writeTitle('Ids')
+ self.writeTable(osIdTable(), ['name', 'value'])
+
+ def writeFancyTraceback(self):
if self.setting('IncludeFancyTraceback'):
! self.writeTitle('Fancy Traceback')
try:
from WebUtils.ExpansiveHTMLForException import ExpansiveHTMLForException
! self.write(ExpansiveHTMLForException(context=self.setting('FancyTracebackContext')))
except:
! self.write('Unable to generate a fancy traceback! (uncaught exception)')
def saveErrorPage(self, html):
***************
*** 224,231 ****
# Some misc functions
def htTitle(name):
return '''
! <p> <br> <table border=0 cellpadding=4 cellspacing=0 bgcolor=#A00000> <tr> <td>
<font face="Tahoma, Arial, Helvetica" color=white> <b> %s </b> </font>
</td> </tr> </table>''' % name
--- 345,366 ----
+ ## Self utility ##
+
+ def repr(self, x):
+ """
+ Returns the repr() of x already html encoded. As a special case, dictionaries are nicely formatted in table.
+
+ This is a utility method for writeAttrs.
+ """
+ if type(x) is DictType:
+ return htmlForDict(x)
+ else:
+ return htmlEncode(repr(x))
+
+
# Some misc functions
def htTitle(name):
return '''
! <p> <br> <table border=0 cellpadding=4 cellspacing=0 bgcolor=#A00000 width=100%%> <tr> <td align=center>
<font face="Tahoma, Arial, Helvetica" color=white> <b> %s </b> </font>
</td> </tr> </table>''' % name
***************
*** 242,273 ****
table.append({'name': funcName, 'value': value})
return table
-
- def htTable(listOfDicts, keys=None):
- ''' The listOfDicts parameter is expected to be a list of dictionaries whose keys are always the same.
- This function returns an HTML string with the contents of the table.
- If keys is None, the headings are taken from the first row in alphabetical order.
- Returns an empty string if listOfDicts is none or empty.
- Deficiencies: There's no way to influence the formatting or to use column titles that are different than the keys. '''
-
- if not listOfDicts:
- return ''
-
- if keys is None:
- keys = listOfDicts[0].keys()
- keys.sort()
-
- s = '<table border=0 cellpadding=2 cellspacing=2 bgcolor=#F0F0F0>\n<tr>'
- for key in keys:
- s = '%s<td><b>%s</b></td>' % (s, key)
- s = s + '</tr>\n'
-
- for row in listOfDicts:
- s = s + '<tr>'
- for key in keys:
- s = '%s<td>%s</td>' % (s, row[key])
- s = s + '</tr>\n'
-
- s = s + '</table>'
- return s
def dateForEmail():
--- 377,380 ----
Index: HTTPRequest.py
===================================================================
RCS file: /cvsroot/webware/Webware/WebKit/HTTPRequest.py,v
retrieving revision 1.36
retrieving revision 1.37
diff -C2 -d -r1.36 -r1.37
*** HTTPRequest.py 1 Feb 2002 08:54:06 -0000 1.36
--- HTTPRequest.py 13 Feb 2002 07:11:13 -0000 1.37
***************
*** 518,521 ****
--- 518,523 ----
return string.join(res, '')
+ exceptionReportAttrNames = Request.exceptionReportAttrNames + 'uri servletPath serverSidePath pathInfo pathTranslated queryString method sessionId parents fields cookies environ'.split()
+
## Deprecated ##
Index: HTTPResponse.py
===================================================================
RCS file: /cvsroot/webware/Webware/WebKit/HTTPResponse.py,v
retrieving revision 1.16
retrieving revision 1.17
diff -C2 -d -r1.16 -r1.17
*** HTTPResponse.py 13 May 2001 21:10:17 -0000 1.16
--- HTTPResponse.py 13 Feb 2002 07:11:13 -0000 1.17
***************
*** 286,287 ****
--- 286,291 ----
self.setHeader(i[:sep], string.rstrip(i[sep+1:]))
+
+ ## Exception reporting ##
+
+ exceptionReportAttrNames = Response.exceptionReportAttrNames + ['committed', 'headers', 'cookies']
Index: Message.py
===================================================================
RCS file: /cvsroot/webware/Webware/WebKit/Message.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** Message.py 25 Oct 2001 05:44:10 -0000 1.3
--- Message.py 13 Feb 2002 07:11:13 -0000 1.4
***************
*** 68,69 ****
--- 68,78 ----
''' Returns a list of argument names. '''
return self._args.keys()
+
+
+ ## Exception reports ##
+
+ exceptionReportAttrNames = ['args']
+
+ def writeExceptionReport(self, handler):
+ handler.writeTitle(self.__class__.__name__)
+ handler.writeAttrs(self, self.exceptionReportAttrNames)
Index: Page.py
===================================================================
RCS file: /cvsroot/webware/Webware/WebKit/Page.py,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -d -r1.18 -r1.19
*** Page.py 4 Feb 2002 18:31:48 -0000 1.18
--- Page.py 13 Feb 2002 07:11:13 -0000 1.19
***************
*** 335,338 ****
--- 335,339 ----
return apply(self.application().callMethodOfServlet, (self.transaction(), URL, method) + args, kwargs)
+
## Self utility ##
***************
*** 348,352 ****
-
## Private utility ##
--- 349,352 ----
***************
*** 358,359 ****
--- 358,375 ----
self._actionDict[action] = 1
return self._actionDict
+
+
+ ## Exception reports ##
+
+ def writeExceptionReport(self, handler):
+ handler.writeTitle(self.__class__.__name__)
+ handler.writeln('''Servlets can provide debugging information here by overriding writeExceptionReport().<br>For example:
+ <pre> exceptionReportAttrs = 'foo bar baz'.split()
+ def writeExceptionReport(self, handler):
+ handler.writeTitle(self.__class__.__name__)
+ handler.writeAttrs(self, self.exceptionReportAttrs)
+ handler.write('any string')
+ </pre>
+
+ See WebKit/ExceptionHandler.py for more information.
+ ''')
Index: Response.py
===================================================================
RCS file: /cvsroot/webware/Webware/WebKit/Response.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** Response.py 19 Apr 2001 22:39:49 -0000 1.2
--- Response.py 13 Feb 2002 07:11:13 -0000 1.3
***************
*** 51,55 ****
--- 51,62 ----
return self._strmOut
+
## Cleanup ##
+
def clearTransaction(self):
del self._transaction
+
+
+ ## Exception reporting ##
+
+ exceptionReportAttrNames = Message.exceptionReportAttrNames + ['endTime']
Index: Session.py
===================================================================
RCS file: /cvsroot/webware/Webware/WebKit/Session.py,v
retrieving revision 1.20
retrieving revision 1.21
diff -C2 -d -r1.20 -r1.21
*** Session.py 11 Feb 2002 19:13:55 -0000 1.20
--- Session.py 13 Feb 2002 07:11:13 -0000 1.21
***************
*** 178,179 ****
--- 178,188 ----
url = urlparse.urlunparse(url)
return url
+
+
+ ## Exception reports ##
+
+ exceptionReportAttrNames = 'lastAccessTime isExpired numTrans timeout values'.split()
+
+ def writeExceptionReport(self, handler):
+ handler.writeTitle(self.__class__.__name__)
+ handler.writeAttrs(self, self.exceptionReportAttrNames)
Index: Transaction.py
===================================================================
RCS file: /cvsroot/webware/Webware/WebKit/Transaction.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -d -r1.10 -r1.11
*** Transaction.py 5 Feb 2002 23:23:10 -0000 1.10
--- Transaction.py 13 Feb 2002 07:11:13 -0000 1.11
***************
*** 1,3 ****
--- 1,5 ----
from Common import *
+ from WebUtils.Funcs import htmlEncode
+ import traceback
***************
*** 135,136 ****
--- 137,157 ----
attr.resetKeyBindings()
delattr(self, attrName)
+
+
+ ## Exception handling ##
+
+ exceptionReportAttrNames = 'application request response session servlet'.split()
+
+ def writeExceptionReport(self, handler):
+ handler.writeTitle(self.__class__.__name__)
+ handler.writeAttrs(self, self.exceptionReportAttrNames)
+
+ for name in self.exceptionReportAttrNames:
+ obj = getattr(self, '_'+name, None)
+ if obj:
+ try:
+ obj.writeExceptionReport(handler)
+ except Exception, e:
+ handler.writeln('<p> Uncaught exception while asking <b>%s</b> to write report:\n<pre>' % name)
+ traceback.print_exc(file=handler)
+ handler.writeln('</pre>')
|
| Thread | Author | Date |
|---|---|---|
| [Webware-checkins] CVS: Webware/WebKit Application.py,1.129,1.130 ExceptionHandler.py,1.12,1.13 HTTPRequest.py,1.36,1.37 HTTPResponse.py,1.16,1.17 Message.py,1.3,1.4 Page.py,1.18,1.19 Response.py,1.2,1.3 Session.py,1.20,1.21 Transaction.py,1.10,1.11 | Chuck Esterbrook <echuck@us...> |