mirror of https://github.com/cool-RR/PySnooper.git
Log exceptions nicely
This commit is contained in:
parent
4b77bb6000
commit
d24f9e3846
|
@ -3,12 +3,14 @@
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
|
import opcode
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
import collections
|
import collections
|
||||||
import datetime as datetime_module
|
import datetime as datetime_module
|
||||||
import itertools
|
import itertools
|
||||||
import threading
|
import threading
|
||||||
|
import traceback
|
||||||
|
|
||||||
from .variables import CommonVariable, Exploding, BaseVariable
|
from .variables import CommonVariable, Exploding, BaseVariable
|
||||||
from .third_party import six
|
from .third_party import six
|
||||||
|
@ -334,14 +336,36 @@ class Tracer:
|
||||||
# #
|
# #
|
||||||
### Finished dealing with misplaced function definition. ##############
|
### Finished dealing with misplaced function definition. ##############
|
||||||
|
|
||||||
self.write(u'{indent}{now_string} {thread_info}{event:9} '
|
# If a call ends due to an exception, we still get a 'return' event
|
||||||
u'{line_no:4} {source_line}'.format(**locals()))
|
# with arg = None. This seems to be the only way to tell the difference
|
||||||
|
# https://stackoverflow.com/a/12800909/2482744
|
||||||
|
ended_by_exception = (
|
||||||
|
event == 'return'
|
||||||
|
and arg is None
|
||||||
|
and (opcode.opname[frame.f_code.co_code[frame.f_lasti]]
|
||||||
|
not in ('RETURN_VALUE', 'YIELD_VALUE'))
|
||||||
|
)
|
||||||
|
|
||||||
|
if ended_by_exception:
|
||||||
|
self.write('{indent}Call ended by exception'.
|
||||||
|
format(**locals()))
|
||||||
|
else:
|
||||||
|
self.write(u'{indent}{now_string} {thread_info}{event:9} '
|
||||||
|
u'{line_no:4} {source_line}'.format(**locals()))
|
||||||
|
|
||||||
if event == 'return':
|
if event == 'return':
|
||||||
return_value_repr = utils.get_shortish_repr(arg)
|
|
||||||
self.write('{indent}Return value:.. {return_value_repr}'.
|
|
||||||
format(**locals()))
|
|
||||||
del self.frame_to_local_reprs[frame]
|
del self.frame_to_local_reprs[frame]
|
||||||
thread_global.depth -= 1
|
thread_global.depth -= 1
|
||||||
|
|
||||||
|
if not ended_by_exception:
|
||||||
|
return_value_repr = utils.get_shortish_repr(arg)
|
||||||
|
self.write('{indent}Return value:.. {return_value_repr}'.
|
||||||
|
format(**locals()))
|
||||||
|
|
||||||
|
if event == 'exception':
|
||||||
|
exception = '\n'.join(traceback.format_exception_only(*arg[:2])).strip()
|
||||||
|
exception = utils.truncate(exception, utils.MAX_EXCEPTION_LENGTH)
|
||||||
|
self.write('{indent}{exception}'.
|
||||||
|
format(**locals()))
|
||||||
|
|
||||||
return self.trace
|
return self.trace
|
||||||
|
|
|
@ -7,6 +7,7 @@ from .pycompat import ABC
|
||||||
from .third_party import six
|
from .third_party import six
|
||||||
|
|
||||||
MAX_VARIABLE_LENGTH = 100
|
MAX_VARIABLE_LENGTH = 100
|
||||||
|
MAX_EXCEPTION_LENGTH = 200
|
||||||
|
|
||||||
def _check_methods(C, *methods):
|
def _check_methods(C, *methods):
|
||||||
mro = C.__mro__
|
mro = C.__mro__
|
||||||
|
|
Loading…
Reference in New Issue