summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2006-07-24 14:09:56 (GMT)
committerGeorg Brandl <georg@python.org>2006-07-24 14:09:56 (GMT)
commitc13c34c39d0a39b3f3bfe1d2145861dbdc19dd68 (patch)
treeb62ea51b24f05fef526f6de7c0568e7135c35f5c /Lib
parent844f7ddcdc3b171ea18c626e46dec14a5786400a (diff)
downloadcpython-c13c34c39d0a39b3f3bfe1d2145861dbdc19dd68.zip
cpython-c13c34c39d0a39b3f3bfe1d2145861dbdc19dd68.tar.gz
cpython-c13c34c39d0a39b3f3bfe1d2145861dbdc19dd68.tar.bz2
Patch #1515343: Fix printing of deprecated string exceptions with a
value in the traceback module.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_traceback.py36
-rw-r--r--Lib/traceback.py96
2 files changed, 88 insertions, 44 deletions
diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py
index 1b59f98..4ecd2cd 100644
--- a/Lib/test/test_traceback.py
+++ b/Lib/test/test_traceback.py
@@ -31,8 +31,9 @@ class TracebackCases(unittest.TestCase):
err = self.get_exception_format(self.syntax_error_with_caret,
SyntaxError)
self.assert_(len(err) == 4)
- self.assert_("^" in err[2]) # third line has caret
self.assert_(err[1].strip() == "return x!")
+ self.assert_("^" in err[2]) # third line has caret
+ self.assert_(err[1].find("!") == err[2].find("^")) # in the right place
def test_nocaret(self):
if is_jython:
@@ -47,8 +48,9 @@ class TracebackCases(unittest.TestCase):
err = self.get_exception_format(self.syntax_error_bad_indentation,
IndentationError)
self.assert_(len(err) == 4)
- self.assert_("^" in err[2])
self.assert_(err[1].strip() == "print 2")
+ self.assert_("^" in err[2])
+ self.assert_(err[1].find("2") == err[2].find("^"))
def test_bug737473(self):
import sys, os, tempfile, time
@@ -109,6 +111,36 @@ def test():
lst = traceback.format_exception_only(e.__class__, e)
self.assertEqual(lst, ['KeyboardInterrupt\n'])
+ # String exceptions are deprecated, but legal. The quirky form with
+ # separate "type" and "value" tends to break things, because
+ # not isinstance(value, type)
+ # and a string cannot be the first argument to issubclass.
+ #
+ # Note that sys.last_type and sys.last_value do not get set if an
+ # exception is caught, so we sort of cheat and just emulate them.
+ #
+ # test_string_exception1 is equivalent to
+ #
+ # >>> raise "String Exception"
+ #
+ # test_string_exception2 is equivalent to
+ #
+ # >>> raise "String Exception", "String Value"
+ #
+ def test_string_exception1(self):
+ str_type = "String Exception"
+ err = traceback.format_exception_only(str_type, None)
+ self.assert_(len(err) == 1)
+ self.assert_(err[0] == str_type + '\n')
+
+ def test_string_exception2(self):
+ str_type = "String Exception"
+ str_value = "String Value"
+ err = traceback.format_exception_only(str_type, str_value)
+ self.assert_(len(err) == 1)
+ self.assert_(err[0] == str_type + ': ' + str_value + '\n')
+
+
def test_main():
run_unittest(TracebackCases)
diff --git a/Lib/traceback.py b/Lib/traceback.py
index d900f52..24b9c68 100644
--- a/Lib/traceback.py
+++ b/Lib/traceback.py
@@ -150,51 +150,63 @@ def format_exception_only(etype, value):
The arguments are the exception type and value such as given by
sys.last_type and sys.last_value. The return value is a list of
- strings, each ending in a newline. Normally, the list contains a
- single string; however, for SyntaxError exceptions, it contains
- several lines that (when printed) display detailed information
- about where the syntax error occurred. The message indicating
- which exception occurred is the always last string in the list.
+ strings, each ending in a newline.
+
+ Normally, the list contains a single string; however, for
+ SyntaxError exceptions, it contains several lines that (when
+ printed) display detailed information about where the syntax
+ error occurred.
+
+ The message indicating which exception occurred is always the last
+ string in the list.
+
"""
- list = []
- if (type(etype) == types.ClassType
- or (isinstance(etype, type) and issubclass(etype, BaseException))):
- stype = etype.__name__
+
+ # An instance should not have a meaningful value parameter, but
+ # sometimes does, particularly for string exceptions, such as
+ # >>> raise string1, string2 # deprecated
+ #
+ # Clear these out first because issubtype(string1, SyntaxError)
+ # would throw another exception and mask the original problem.
+ if (isinstance(etype, BaseException) or
+ isinstance(etype, types.InstanceType) or
+ type(etype) is str):
+ return [_format_final_exc_line(etype, value)]
+
+ stype = etype.__name__
+
+ if not issubclass(etype, SyntaxError):
+ return [_format_final_exc_line(stype, value)]
+
+ # It was a syntax error; show exactly where the problem was found.
+ try:
+ msg, (filename, lineno, offset, badline) = value
+ except Exception:
+ pass
else:
- stype = etype
- if value is None:
- list.append(str(stype) + '\n')
+ filename = filename or "<string>"
+ lines = [(' File "%s", line %d\n' % (filename, lineno))]
+ if badline is not None:
+ lines.append(' %s\n' % badline.strip())
+ if offset is not None:
+ caretspace = badline[:offset].lstrip()
+ # non-space whitespace (likes tabs) must be kept for alignment
+ caretspace = ((c.isspace() and c or ' ') for c in caretspace)
+ # only three spaces to account for offset1 == pos 0
+ lines.append(' %s^\n' % ''.join(caretspace))
+ value = msg
+
+ lines.append(_format_final_exc_line(stype, value))
+ return lines
+
+def _format_final_exc_line(etype, value):
+ """Return a list of a single line -- normal case for format_exception_only"""
+ if value is None or not str(value):
+ line = "%s\n" % etype
else:
- if issubclass(etype, SyntaxError):
- try:
- msg, (filename, lineno, offset, line) = value
- except:
- pass
- else:
- if not filename: filename = "<string>"
- list.append(' File "%s", line %d\n' %
- (filename, lineno))
- if line is not None:
- i = 0
- while i < len(line) and line[i].isspace():
- i = i+1
- list.append(' %s\n' % line.strip())
- if offset is not None:
- s = ' '
- for c in line[i:offset-1]:
- if c.isspace():
- s = s + c
- else:
- s = s + ' '
- list.append('%s^\n' % s)
- value = msg
- s = _some_str(value)
- if s:
- list.append('%s: %s\n' % (str(stype), s))
- else:
- list.append('%s\n' % str(stype))
- return list
-
+ line = "%s: %s\n" % (etype, _some_str(value))
+ return line
+
def _some_str(value):
try:
return str(value)