[Zope-Checkins] CVS: Zope/lib/python/ZPublisher - HTTPResponse.py:1.53.12.1

Shane Hathaway shane@cvs.zope.org
Tue, 2 Apr 2002 18:01:48 -0500


Update of /cvs-repository/Zope/lib/python/ZPublisher
In directory cvs.zope.org:/tmp/cvs-serv30770

Modified Files:
      Tag: shane-better-tracebacks-branch
	HTTPResponse.py 
Log Message:
Made HTTPResponses use the new exception formatter.

Stopped appending tracebacks to the bottom of valid HTML.  You
can turn this back on with a global if you want, but I'm making a product
that can log site exceptions, eliminating the need for appending tracebacks.


=== Zope/lib/python/ZPublisher/HTTPResponse.py 1.53 => 1.53.12.1 ===
 from BaseResponse import BaseResponse
 from zExceptions import Unauthorized
+from zExceptions.ExceptionFormatter import format_exception
 
 nl2sp=maketrans('\n',' ')
 
+
+# Enable APPEND_TRACEBACKS to make Zope append tracebacks like it used to,
+# but a better solution is to make standard_error_message display error_tb.
+APPEND_TRACEBACKS = 0
+
+
 status_reasons={
 100: 'Continue',
 101: 'Switching Protocols',
@@ -354,8 +361,15 @@
         else: h=value
         self.setHeader(name,h)
 
-    def isHTML(self,str):
-        return str.strip().lower()[:6] == '<html>' or str.find('</') > 0
+    def isHTML(self, s):
+        s = s.lstrip()
+        # Note that the string can be big, so s.lower().startswith() is more
+        # expensive than s[:n].lower().
+        if (s[:6].lower() == '<html>' or s[:14].lower() == '<!doctype html'):
+            return 1
+        if s.find('</') > 0:
+            return 1
+        return 0
 
     def quoteHTML(self,text,
                   subs={'&':'&amp;', "<":'&lt;', ">":'&gt;', '\"':'&quot;'}
@@ -367,42 +381,9 @@
         return text
          
 
-    def format_exception(self, etype, value, tb, limit=None):
-        import traceback
-        result=['Traceback (innermost last):']
-        if limit is None:
-                if hasattr(sys, 'tracebacklimit'):
-                        limit = sys.tracebacklimit
-        n = 0
-        while tb is not None and (limit is None or n < limit):
-                f = tb.tb_frame
-                lineno = tb.tb_lineno
-                co = f.f_code
-                filename = co.co_filename
-                name = co.co_name
-                locals=f.f_locals
-                result.append('  File %s, line %d, in %s'
-                              % (filename,lineno,name))
-                try: result.append('    (Object: %s)' %
-                                   locals[co.co_varnames[0]].__name__)
-                except: pass
-                try: result.append('    (Info: %s)' %
-                                   str(locals['__traceback_info__']))
-                except: pass
-                tb = tb.tb_next
-                n = n + 1
-        result.append(' '.join(traceback.format_exception_only(etype, value)))
-        return result
-
-    def _traceback(self, t, v, tb):
-        tb = self.format_exception(t, v, tb, 200)
-        tb = '\n'.join(tb)
-        tb = self.quoteHTML(tb)
-        if self.debug_mode: _tbopen, _tbclose = '<PRE>', '</PRE>'
-        else:               _tbopen, _tbclose = '''<pre
-          onclick="this.firstChild.data=this.lastChild.data">
-        &sect;<!--''',  '--></pre>'
-        return "\n%s\n%s\n%s" % (_tbopen, tb, _tbclose)
+    def _traceback(self, t, v, tb, as_html=1):
+        tb = format_exception(t, v, tb, as_html=as_html)
+        return '\n'.join(tb)
 
     def redirect(self, location, status=302, lock=0):
         """Cause a redirection without raising an error"""
@@ -589,14 +570,16 @@
                 'Sorry, a site error occurred.<p>'
                  + self._traceback(t, v, tb)),
                  is_error=1)
-        elif b.strip().lower()[:6]=='<html>' or \
-              b.strip().lower()[:14]=='<!doctype html':
+        elif self.isHTML(b):
             # error is an HTML document, not just a snippet of html
-            body = self.setBody(b + self._traceback(t, '(see above)', tb),
-                              is_error=1)
+            if APPEND_TRACEBACKS:
+                body = self.setBody(b + self._traceback(t, '(see above)', tb),
+                                    is_error=1)
+            else:
+                body = self.setBody(b, is_error=1)
         else:
             body = self.setBody((str(t),
-                               b + self._traceback(t,'(see above)', tb)),
+                               b + self._traceback(t,'(see above)', tb, 0)),
                               is_error=1)
         del tb
         return body