Handle unicode paths more thoroughly.
Further testing exposed that we weren't decoding where we could, and the SyntaxError special case needed to be updated too.
This commit is contained in:
parent
ffe9882743
commit
37c5f154f0
@ -164,6 +164,18 @@ def _some_str(value):
|
|||||||
|
|
||||||
# --
|
# --
|
||||||
|
|
||||||
|
def _some_fs_str(value):
|
||||||
|
"""_some_str, but for filesystem paths."""
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
if type(value) is bytes:
|
||||||
|
return value.decode(sys.getfilesystemencoding())
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return _some_str(value)
|
||||||
|
|
||||||
|
|
||||||
def print_exc(limit=None, file=None, chain=True):
|
def print_exc(limit=None, file=None, chain=True):
|
||||||
"""Shorthand for 'print_exception(*sys.exc_info(), limit, file)'."""
|
"""Shorthand for 'print_exception(*sys.exc_info(), limit, file)'."""
|
||||||
print_exception(*sys.exc_info(), limit=limit, file=file, chain=chain)
|
print_exception(*sys.exc_info(), limit=limit, file=file, chain=chain)
|
||||||
@ -380,7 +392,7 @@ class StackSummary(list):
|
|||||||
for frame in self:
|
for frame in self:
|
||||||
row = []
|
row = []
|
||||||
row.append(u(' File "{0}", line {1}, in {2}\n').format(
|
row.append(u(' File "{0}", line {1}, in {2}\n').format(
|
||||||
_some_str(frame.filename), frame.lineno, frame.name))
|
_some_fs_str(frame.filename), frame.lineno, frame.name))
|
||||||
if frame.line:
|
if frame.line:
|
||||||
row.append(u(' {0}\n').format(frame.line.strip()))
|
row.append(u(' {0}\n').format(frame.line.strip()))
|
||||||
if frame.locals:
|
if frame.locals:
|
||||||
@ -526,7 +538,7 @@ class TracebackException:
|
|||||||
return
|
return
|
||||||
|
|
||||||
# It was a syntax error; show exactly where the problem was found.
|
# It was a syntax error; show exactly where the problem was found.
|
||||||
filename = self.filename or u("<string>")
|
filename = _some_fs_str(self.filename) or u("<string>")
|
||||||
lineno = str(self.lineno) or u('?')
|
lineno = str(self.lineno) or u('?')
|
||||||
yield u(' File "{0}", line {1}\n').format(filename, lineno)
|
yield u(' File "{0}", line {1}\n').format(filename, lineno)
|
||||||
|
|
||||||
|
@ -607,14 +607,26 @@ class TestStack(unittest.TestCase):
|
|||||||
[' File "foo.py", line 1, in fred\n line\n'],
|
[' File "foo.py", line 1, in fred\n line\n'],
|
||||||
s.format())
|
s.format())
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.getfilesystemencoding()=='ANSI_X3.4-1968',
|
||||||
|
'Requires non-ascii fs encoding')
|
||||||
|
def test_format_unicode_filename(self):
|
||||||
|
# Filenames in Python2 may be bytestrings that will fail to implicit
|
||||||
|
# decode.
|
||||||
|
fname = u('\u5341').encode(sys.getfilesystemencoding())
|
||||||
|
s = traceback.StackSummary.from_list([(fname, 1, 'fred', 'line')])
|
||||||
|
self.assertEqual(
|
||||||
|
[u(' File "\u5341", line 1, in fred\n line\n')],
|
||||||
|
s.format())
|
||||||
|
|
||||||
def test_format_bad_filename(self):
|
def test_format_bad_filename(self):
|
||||||
# Filenames in Python2 may be bytestrings that will fail to implicit
|
# Filenames in Python2 may be bytestrings that will fail to implicit
|
||||||
# decode.
|
# decode.
|
||||||
# This won't decode via the implicit(ascii) codec.
|
# This won't decode via the implicit(ascii) codec or the default
|
||||||
fname = u('\u5341').encode('shift-jis')
|
# fs encoding (unless the encoding is a wildcard encoding).
|
||||||
|
fname = b('\x8b')
|
||||||
s = traceback.StackSummary.from_list([(fname, 1, 'fred', 'line')])
|
s = traceback.StackSummary.from_list([(fname, 1, 'fred', 'line')])
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[' File "b\'\\x8f\\\\\'", line 1, in fred\n line\n'],
|
[' File "b\'\\x8b\'", line 1, in fred\n line\n'],
|
||||||
s.format())
|
s.format())
|
||||||
|
|
||||||
def test_locals(self):
|
def test_locals(self):
|
||||||
@ -639,7 +651,7 @@ class TestStack(unittest.TestCase):
|
|||||||
traceback.walk_stack(None), capture_locals=True, limit=1)
|
traceback.walk_stack(None), capture_locals=True, limit=1)
|
||||||
s = some_inner(3, 4)
|
s = some_inner(3, 4)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[' File "' + FNAME + '", line 639, '
|
[' File "' + FNAME + '", line 651, '
|
||||||
'in some_inner\n'
|
'in some_inner\n'
|
||||||
' traceback.walk_stack(None), capture_locals=True, limit=1)\n'
|
' traceback.walk_stack(None), capture_locals=True, limit=1)\n'
|
||||||
' a = 1\n'
|
' a = 1\n'
|
||||||
@ -821,3 +833,67 @@ class TestTracebackException(unittest.TestCase):
|
|||||||
u(' ^\n'),
|
u(' ^\n'),
|
||||||
u('SyntaxError: uh oh\n')],
|
u('SyntaxError: uh oh\n')],
|
||||||
list(exc.format()))
|
list(exc.format()))
|
||||||
|
|
||||||
|
@unittest.skipUnless(sys.version_info[0] < 3, "Applies to 2.x only.")
|
||||||
|
@unittest.skipIf(sys.getfilesystemencoding()=='ANSI_X3.4-1968',
|
||||||
|
'Requires non-ascii fs encoding')
|
||||||
|
def test_format_unicode_filename(self):
|
||||||
|
# Filenames in Python2 may be bytestrings that will fail to implicit
|
||||||
|
# decode.
|
||||||
|
fname = u('\u5341').encode(sys.getfilesystemencoding())
|
||||||
|
lines = u("1\n2\n3\n")
|
||||||
|
fake_module = dict(
|
||||||
|
__name__='fred',
|
||||||
|
__loader__=FakeLoader(lines)
|
||||||
|
)
|
||||||
|
linecache.updatecache(fname, fake_module)
|
||||||
|
e = SyntaxError("uh oh")
|
||||||
|
e.filename = fname
|
||||||
|
e.lineno = 2
|
||||||
|
e.text = b('something wrong')
|
||||||
|
e.offset = 1
|
||||||
|
c = test_code(fname, 'method')
|
||||||
|
f = test_frame(c, fake_module, {'something': 1})
|
||||||
|
tb = test_tb(f, 2, None)
|
||||||
|
exc = traceback.TracebackException(SyntaxError, e, tb)
|
||||||
|
list(exc.format_exception_only())
|
||||||
|
self.assertEqual([
|
||||||
|
u('Traceback (most recent call last):\n'),
|
||||||
|
u(' File "\u5341", line 2, in method\n 2\n'),
|
||||||
|
u(' File "\u5341", line 2\n'),
|
||||||
|
u(' something wrong\n'),
|
||||||
|
u(' ^\n'),
|
||||||
|
u('SyntaxError: uh oh\n')],
|
||||||
|
list(exc.format()))
|
||||||
|
|
||||||
|
@unittest.skipUnless(sys.version_info[0] < 3, "Applies to 2.x only.")
|
||||||
|
def test_format_bad_filename(self):
|
||||||
|
# Filenames in Python2 may be bytestrings that will fail to implicit
|
||||||
|
# decode.
|
||||||
|
# This won't decode via the implicit(ascii) codec or the default
|
||||||
|
# fs encoding (unless the encoding is a wildcard encoding).
|
||||||
|
fname = b('\x8b')
|
||||||
|
lines = u("1\n2\n3\n")
|
||||||
|
fake_module = dict(
|
||||||
|
__name__='fred',
|
||||||
|
__loader__=FakeLoader(lines)
|
||||||
|
)
|
||||||
|
linecache.updatecache(fname, fake_module)
|
||||||
|
e = SyntaxError("uh oh")
|
||||||
|
e.filename = fname
|
||||||
|
e.lineno = 2
|
||||||
|
e.text = b('something wrong')
|
||||||
|
e.offset = 1
|
||||||
|
c = test_code(fname, 'method')
|
||||||
|
f = test_frame(c, fake_module, {'something': 1})
|
||||||
|
tb = test_tb(f, 2, None)
|
||||||
|
exc = traceback.TracebackException(SyntaxError, e, tb)
|
||||||
|
list(exc.format_exception_only())
|
||||||
|
self.assertEqual([
|
||||||
|
u('Traceback (most recent call last):\n'),
|
||||||
|
b(' File "b\'\\x8b\'", line 2, in method\n 2\n').decode(),
|
||||||
|
b(' File "b\'\\x8b\'", line 2\n').decode(),
|
||||||
|
u(' something wrong\n'),
|
||||||
|
u(' ^\n'),
|
||||||
|
u('SyntaxError: uh oh\n')],
|
||||||
|
list(exc.format()))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user