Patch #1515343: Fix printing of deprecated string exceptions with a
value in the traceback module.
This commit is contained in:
parent
844f7ddcdc
commit
c13c34c39d
|
@ -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)
|
||||
|
||||
|
|
100
Lib/traceback.py
100
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.
|
||||
"""
|
||||
list = []
|
||||
if (type(etype) == types.ClassType
|
||||
or (isinstance(etype, type) and issubclass(etype, BaseException))):
|
||||
stype = etype.__name__
|
||||
else:
|
||||
stype = etype
|
||||
if value is None:
|
||||
list.append(str(stype) + '\n')
|
||||
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
|
||||
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.
|
||||
|
||||
"""
|
||||
|
||||
# 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:
|
||||
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:
|
||||
line = "%s: %s\n" % (etype, _some_str(value))
|
||||
return line
|
||||
|
||||
def _some_str(value):
|
||||
try:
|
||||
return str(value)
|
||||
|
|
|
@ -39,6 +39,9 @@ Core and builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Patch #1515343: Fix printing of deprecated string exceptions with a
|
||||
value in the traceback module.
|
||||
|
||||
- Resync optparse with Optik 1.5.3: minor tweaks for/to tests.
|
||||
|
||||
- Patch #1524429: Use repr() instead of backticks in Tkinter again.
|
||||
|
|
Loading…
Reference in New Issue