diff --git a/noseprogressive/tests/test_tracebacks.py b/noseprogressive/tests/test_tracebacks.py index b5c4cfc..1dcab27 100644 --- a/noseprogressive/tests/test_tracebacks.py +++ b/noseprogressive/tests/test_tracebacks.py @@ -83,3 +83,25 @@ def test_none_members(): [(None, None, None, None)], AttributeError, AttributeError('I have many nasty attributes.'))) + + +def test_proxied_syntax_error(): + """The logcapture plugin formats errors by extracting and converting + the value to a string. Nose recreates a proxy exception lacking + filename and lineno attributes, crashing the shortcut formatting + """ + string_error = ''.join([ + "invalid syntax (package.py, line 111)\n", + "-------------------- >> begin captured logging << --------------------\n", + "DEBUG: a logged message\n", + "--------------------- >> end captured logging << ---------------------" + ]) + # This is essentially what nose does with a string exception + proxied_syntax_error = type('SyntaxError', (Exception,), {})(string_error) + proxied_syntax_tb = ([ + ('/usr/lib/python2.7/site-packages/nose/loader.py', 403, 'loadTestsFromName', 'module = resolve_name(addr.module)'), + ('/usr/lib/python2.7/site-packages/nose/util.py', 311, 'resolve_name', "module = __import__('.'.join(parts_copy))"), + ('/usr/local/venvs/project/tests.py', 8, '', 'from project.package import something') + ], SyntaxError, proxied_syntax_error + ) + ''.join(format_traceback(*proxied_syntax_tb)) diff --git a/noseprogressive/tracebacks.py b/noseprogressive/tracebacks.py index e7c589e..bcbab7e 100644 --- a/noseprogressive/tracebacks.py +++ b/noseprogressive/tracebacks.py @@ -79,8 +79,15 @@ def format_shortcut(editor, # SyntaxErrors have a format different from other errors and include a # file path which looks out of place in our newly highlit, editor- # shortcutted world. - exc_lines = [format_shortcut(editor, exc_value.filename, exc_value.lineno)] - formatted_exception = format_exception_only(SyntaxError, exc_value)[1:] + if hasattr(exc_value, 'filename') and hasattr(exc_value, 'lineno'): + exc_lines = [format_shortcut(editor, exc_value.filename, exc_value.lineno)] + formatted_exception = format_exception_only(SyntaxError, exc_value)[1:] + else: + # The logcapture plugin may format exceptions as strings, + # stripping them of the full filename and lineno + exc_lines = [] + formatted_exception = format_exception_only(SyntaxError, exc_value) + formatted_exception.append(u'(Try --nologcapture for a more detailed traceback)\n') else: exc_lines = [] formatted_exception = format_exception_only(exc_type, exc_value)