[Checkins] SVN: zope.exceptions/trunk/ Added TextExceptionFormatter.extractStack and extract_stack
Adam Groszer
cvs-admin at zope.org
Wed Mar 28 13:58:14 UTC 2012
Log message for revision 124764:
Added TextExceptionFormatter.extractStack and extract_stack
Changed:
U zope.exceptions/trunk/CHANGES.txt
U zope.exceptions/trunk/src/zope/exceptions/exceptionformatter.py
U zope.exceptions/trunk/src/zope/exceptions/tests/test_exceptionformatter.py
-=-
Modified: zope.exceptions/trunk/CHANGES.txt
===================================================================
--- zope.exceptions/trunk/CHANGES.txt 2012-03-28 13:55:01 UTC (rev 124763)
+++ zope.exceptions/trunk/CHANGES.txt 2012-03-28 13:58:11 UTC (rev 124764)
@@ -5,7 +5,7 @@
3.6.3 (unreleased)
------------------
-- Nothing changed yet.
+- Added TextExceptionFormatter.extractStack and extract_stack
3.6.2 (2012-03-28)
Modified: zope.exceptions/trunk/src/zope/exceptions/exceptionformatter.py
===================================================================
--- zope.exceptions/trunk/src/zope/exceptions/exceptionformatter.py 2012-03-28 13:55:01 UTC (rev 124763)
+++ zope.exceptions/trunk/src/zope/exceptions/exceptionformatter.py 2012-03-28 13:58:11 UTC (rev 124764)
@@ -98,9 +98,14 @@
def formatTracebackInfo(self, tbi):
return self.formatSupplementLine('__traceback_info__: %s' % (tbi, ))
- def formatLine(self, tb):
- f = tb.tb_frame
- lineno = tb.tb_lineno
+ def formatLine(self, tb=None, f=None):
+ if tb and not f:
+ f = tb.tb_frame
+ lineno = tb.tb_lineno
+ elif not tb and f:
+ lineno = f.f_lineno
+ else:
+ raise ValueError("tb or f needs to be passed")
co = f.f_code
filename = co.co_filename
name = co.co_name
@@ -174,7 +179,7 @@
result.append('(Recursive formatException() stopped, trying traceback.format_tb)\n')
result.extend(traceback.format_tb(tb))
break
- line = self.formatLine(tb)
+ line = self.formatLine(tb=tb)
result.append(line + '\n')
tb = tb.tb_next
n = n + 1
@@ -182,7 +187,26 @@
result.append(self.formatLastLine(exc_line))
return result
+ def extractStack(self, f=None):
+ if f is None:
+ try:
+ raise ZeroDivisionError
+ except ZeroDivisionError:
+ f = sys.exc_info()[2].tb_frame.f_back
+ # The next line provides a way to detect recursion.
+ __exception_formatter__ = 1
+ result = []
+ limit = self.getLimit()
+ n = 0
+ while f is not None and (limit is None or n < limit):
+ line = self.formatLine(f=f)
+ result.append(line + '\n')
+ f = f.f_back
+ n = n + 1
+ return result
+
+
class HTMLExceptionFormatter(TextExceptionFormatter):
line_sep = '<br />\r\n'
@@ -201,8 +225,8 @@
s = s.replace('\n', self.line_sep)
return '__traceback_info__: %s' % (s, )
- def formatLine(self, tb):
- line = TextExceptionFormatter.formatLine(self, tb)
+ def formatLine(self, tb=None, f=None):
+ line = TextExceptionFormatter.formatLine(self, tb, f)
return '<li>%s</li>' % line
def formatLastLine(self, exc_line):
@@ -237,3 +261,17 @@
lines = format_exception(t, v, tb, limit, as_html, with_filenames)
for line in lines:
file.write(line)
+
+def extract_stack(f, limit=None, as_html=False,
+ with_filenames=True):
+ """Format a stack trace and the exception information.
+
+ Similar to 'traceback.format_exception', but adds supplemental
+ information to the traceback and accepts two options, 'as_html'
+ and 'with_filenames'.
+ """
+ if as_html:
+ fmt = HTMLExceptionFormatter(limit, with_filenames)
+ else:
+ fmt = TextExceptionFormatter(limit, with_filenames)
+ return fmt.extractStack(f)
Modified: zope.exceptions/trunk/src/zope/exceptions/tests/test_exceptionformatter.py
===================================================================
--- zope.exceptions/trunk/src/zope/exceptions/tests/test_exceptionformatter.py 2012-03-28 13:55:01 UTC (rev 124763)
+++ zope.exceptions/trunk/src/zope/exceptions/tests/test_exceptionformatter.py 2012-03-28 13:58:11 UTC (rev 124764)
@@ -18,6 +18,7 @@
from unittest import TestCase, makeSuite
from zope.exceptions.exceptionformatter import format_exception
+from zope.exceptions.exceptionformatter import extract_stack
def tb(as_html=0):
@@ -27,6 +28,12 @@
finally:
del b
+def st(as_html=0):
+ f = sys.exc_info()[2].tb_frame
+ try:
+ return ''.join(extract_stack(f, as_html=as_html))
+ finally:
+ del f
class ExceptionForTesting (Exception):
pass
@@ -60,6 +67,19 @@
def testBasicNamesHTML(self):
self.testBasicNamesText(1)
+ def testBasicNamesText_stack(self, as_html=0):
+ try:
+ raise ExceptionForTesting
+ except ExceptionForTesting:
+ s = st(as_html)
+ # The stack trace should include the name of this function.
+ self.assertTrue(s.find('testBasicNamesText_stack') >= 0)
+ else:
+ self.fail('no exception occurred')
+
+ def testBasicNamesHTML_stack(self):
+ self.testBasicNamesText_stack(1)
+
def testSupplement(self, as_html=0):
try:
__traceback_supplement__ = (TestingTracebackSupplement,
@@ -83,6 +103,29 @@
def testSupplementHTML(self):
self.testSupplement(1)
+ def testSupplement_stack(self, as_html=0):
+ try:
+ __traceback_supplement__ = (TestingTracebackSupplement,
+ "You're one in a million")
+ raise ExceptionForTesting
+ except ExceptionForTesting:
+ s = st(as_html)
+ # The source URL
+ self.assertTrue(s.find('/somepath') >= 0, s)
+ # The line number
+ self.assertTrue(s.find('634') >= 0, s)
+ # The column number
+ self.assertTrue(s.find('57') >= 0, s)
+ # The expression
+ self.assertTrue(s.find("You're one in a million") >= 0, s)
+ # The warning
+ self.assertTrue(s.find("Repent, for the end is nigh") >= 0, s)
+ else:
+ self.fail('no exception occurred')
+
+ def testSupplementHTML_stack(self):
+ self.testSupplement_stack(1)
+
def testTracebackInfo(self, as_html=0):
try:
__traceback_info__ = "Adam & Eve"
@@ -100,6 +143,23 @@
def testTracebackInfoHTML(self):
self.testTracebackInfo(1)
+ def testTracebackInfo_stack(self, as_html=0):
+ try:
+ __traceback_info__ = "Adam & Eve"
+ raise ExceptionForTesting
+ except ExceptionForTesting:
+ s = st(as_html)
+ if as_html:
+ # Be sure quoting is happening.
+ self.assertTrue(s.find('Adam & Eve') >= 0, s)
+ else:
+ self.assertTrue(s.find('Adam & Eve') >= 0, s)
+ else:
+ self.fail('no exception occurred')
+
+ def testTracebackInfoHTML_stack(self):
+ self.testTracebackInfo_stack(1)
+
def testTracebackInfoTuple(self):
try:
__traceback_info__ = ("Adam", "Eve")
@@ -157,9 +217,9 @@
class FormatterException(Exception):
pass
-
+
class FailingFormatter(TextExceptionFormatter):
- def formatLine(self, tb):
+ def formatLine(self, tb=None, f=None):
raise FormatterException("Formatter failed")
fmt = FailingFormatter()
@@ -176,5 +236,6 @@
self.assertEqual(s.splitlines()[-2], ' raise FormatterException("Formatter failed")')
self.assertTrue('FormatterException: Formatter failed' in s.splitlines()[-1])
+
def test_suite():
return makeSuite(Test)
More information about the checkins
mailing list