blob: 1171157257e940f5983bb6c564d501d3a67ac5de [file] [log] [blame]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001from pydevd_constants import *
2import pydevd_tracing
3import sys
4import pydev_log
Tor Norbye1aa2e092014-08-20 17:01:23 -07005import pydevd_import_class
Tor Norbye3a2425a2013-11-04 10:16:08 -08006
7_original_excepthook = None
8_handle_exceptions = None
9
10
Tor Norbyec3d3a902014-09-04 13:24:04 -070011import _pydev_threading as threading
Tor Norbye3a2425a2013-11-04 10:16:08 -080012
13threadingCurrentThread = threading.currentThread
14
15from pydevd_comm import GetGlobalDebugger
16
17class ExceptionBreakpoint:
Tor Norbye1aa2e092014-08-20 17:01:23 -070018
19 def __init__(
20 self,
21 qname,
22 notify_always,
23 notify_on_terminate,
24 notify_on_first_raise_only,
25 ):
26 exctype = _get_class(qname)
Tor Norbye3a2425a2013-11-04 10:16:08 -080027 self.qname = qname
28 if exctype is not None:
29 self.name = exctype.__name__
30 else:
31 self.name = None
32
Tor Norbye1aa2e092014-08-20 17:01:23 -070033 self.notify_on_terminate = notify_on_terminate
34 self.notify_always = notify_always
35 self.notify_on_first_raise_only = notify_on_first_raise_only
Tor Norbye3a2425a2013-11-04 10:16:08 -080036
37 self.type = exctype
Tor Norbye3a2425a2013-11-04 10:16:08 -080038
39
40 def __str__(self):
41 return self.qname
42
43class LineBreakpoint:
Tor Norbye1aa2e092014-08-20 17:01:23 -070044
45 def __init__(self, line, condition, func_name, expression):
46 self.line = line
Tor Norbye3a2425a2013-11-04 10:16:08 -080047 self.condition = condition
48 self.func_name = func_name
49 self.expression = expression
50
Tor Norbye3a2425a2013-11-04 10:16:08 -080051def get_exception_full_qname(exctype):
52 if not exctype:
53 return None
54 return str(exctype.__module__) + '.' + exctype.__name__
55
56def get_exception_name(exctype):
57 if not exctype:
58 return None
59 return exctype.__name__
60
61
Tor Norbye1aa2e092014-08-20 17:01:23 -070062def get_exception_breakpoint(exctype, exceptions):
63 exception_full_qname = get_exception_full_qname(exctype)
64
Tor Norbye3a2425a2013-11-04 10:16:08 -080065 exc = None
66 if exceptions is not None:
Tor Norbye1aa2e092014-08-20 17:01:23 -070067 try:
68 return exceptions[exception_full_qname]
69 except KeyError:
70 for exception_breakpoint in DictIterValues(exceptions):
71 if exception_breakpoint.type is not None and issubclass(exctype, exception_breakpoint.type):
72 if exc is None or issubclass(exception_breakpoint.type, exc.type):
73 exc = exception_breakpoint
Tor Norbye3a2425a2013-11-04 10:16:08 -080074 return exc
75
76#=======================================================================================================================
Tor Norbye1aa2e092014-08-20 17:01:23 -070077# _excepthook
Tor Norbye3a2425a2013-11-04 10:16:08 -080078#=======================================================================================================================
Tor Norbye1aa2e092014-08-20 17:01:23 -070079def _excepthook(exctype, value, tb):
Tor Norbye3a2425a2013-11-04 10:16:08 -080080 global _handle_exceptions
Tor Norbye1aa2e092014-08-20 17:01:23 -070081 if _handle_exceptions:
82 exception_breakpoint = get_exception_breakpoint(exctype, _handle_exceptions)
Tor Norbye3a2425a2013-11-04 10:16:08 -080083 else:
84 exception_breakpoint = None
85
Tor Norbye3a2425a2013-11-04 10:16:08 -080086 #Always call the original excepthook before going on to call the debugger post mortem to show it.
87 _original_excepthook(exctype, value, tb)
88
Tor Norbye1aa2e092014-08-20 17:01:23 -070089 if not exception_breakpoint:
90 return
91
Tor Norbye3a2425a2013-11-04 10:16:08 -080092 if tb is None: #sometimes it can be None, e.g. with GTK
Tor Norbye1aa2e092014-08-20 17:01:23 -070093 return
Tor Norbye3a2425a2013-11-04 10:16:08 -080094
95 frames = []
96
Tor Norbye3a2425a2013-11-04 10:16:08 -080097 while tb:
98 frames.append(tb.tb_frame)
99 tb = tb.tb_next
100
101 thread = threadingCurrentThread()
102 frames_byid = dict([(id(frame),frame) for frame in frames])
103 frame = frames[-1]
104 thread.additionalInfo.exception = (exctype, value, tb)
105 thread.additionalInfo.pydev_force_stop_at_exception = (frame, frames_byid)
106 thread.additionalInfo.message = exception_breakpoint.qname
Tor Norbye3a2425a2013-11-04 10:16:08 -0800107 debugger = GetGlobalDebugger()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800108
109 pydevd_tracing.SetTrace(None) #no tracing from here
Tor Norbye1fff8e22014-03-10 13:13:45 -0700110
111 pydev_log.debug('Handling post-mortem stop on exception breakpoint %s'% exception_breakpoint.qname)
112
Tor Norbye3a2425a2013-11-04 10:16:08 -0800113 debugger.handle_post_mortem_stop(thread.additionalInfo, thread)
114
115#=======================================================================================================================
Tor Norbye1aa2e092014-08-20 17:01:23 -0700116# _set_pm_excepthook
Tor Norbye3a2425a2013-11-04 10:16:08 -0800117#=======================================================================================================================
Tor Norbye1aa2e092014-08-20 17:01:23 -0700118def _set_pm_excepthook(handle_exceptions_dict=None):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800119 '''
120 Should be called to register the excepthook to be used.
121
Tor Norbye1aa2e092014-08-20 17:01:23 -0700122 It's only useful for uncaught exceptions. I.e.: exceptions that go up to the excepthook.
Tor Norbye3a2425a2013-11-04 10:16:08 -0800123
Tor Norbye1aa2e092014-08-20 17:01:23 -0700124 @param handle_exceptions: dict(exception -> ExceptionBreakpoint)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800125 The exceptions that should be handled.
126 '''
127 global _handle_exceptions
128 global _original_excepthook
Tor Norbye1aa2e092014-08-20 17:01:23 -0700129 if sys.excepthook != _excepthook:
130 #Only keep the original if it's not our own _excepthook (if called many times).
Tor Norbye3a2425a2013-11-04 10:16:08 -0800131 _original_excepthook = sys.excepthook
132
Tor Norbye1aa2e092014-08-20 17:01:23 -0700133 _handle_exceptions = handle_exceptions_dict
134 sys.excepthook = _excepthook
Tor Norbye3a2425a2013-11-04 10:16:08 -0800135
Tor Norbye1aa2e092014-08-20 17:01:23 -0700136def _restore_pm_excepthook():
Tor Norbye3a2425a2013-11-04 10:16:08 -0800137 global _original_excepthook
138 if _original_excepthook:
139 sys.excepthook = _original_excepthook
140 _original_excepthook = None
141
142
143def update_exception_hook(dbg):
Tor Norbye1aa2e092014-08-20 17:01:23 -0700144 if dbg.break_on_uncaught_exceptions:
145 _set_pm_excepthook(dbg.break_on_uncaught_exceptions)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800146 else:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700147 _restore_pm_excepthook()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800148
Tor Norbye1aa2e092014-08-20 17:01:23 -0700149def _get_class( kls ):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800150 if IS_PY24 and "BaseException" == kls:
151 kls = "Exception"
Tor Norbye1aa2e092014-08-20 17:01:23 -0700152
Tor Norbye3a2425a2013-11-04 10:16:08 -0800153 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700154 return eval(kls)
155 except:
156 return pydevd_import_class.ImportName(kls)