blob: 82a230db2f478ad611566a9dc9f174b251e318f1 [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 Norbye3a2425a2013-11-04 10:16:08 -080011if USE_LIB_COPY:
12 import _pydev_threading as threading
13else:
14 import threading
15
16threadingCurrentThread = threading.currentThread
17
18from pydevd_comm import GetGlobalDebugger
19
20class ExceptionBreakpoint:
Tor Norbye1aa2e092014-08-20 17:01:23 -070021
22 def __init__(
23 self,
24 qname,
25 notify_always,
26 notify_on_terminate,
27 notify_on_first_raise_only,
28 ):
29 exctype = _get_class(qname)
Tor Norbye3a2425a2013-11-04 10:16:08 -080030 self.qname = qname
31 if exctype is not None:
32 self.name = exctype.__name__
33 else:
34 self.name = None
35
Tor Norbye1aa2e092014-08-20 17:01:23 -070036 self.notify_on_terminate = notify_on_terminate
37 self.notify_always = notify_always
38 self.notify_on_first_raise_only = notify_on_first_raise_only
Tor Norbye3a2425a2013-11-04 10:16:08 -080039
40 self.type = exctype
Tor Norbye3a2425a2013-11-04 10:16:08 -080041
42
43 def __str__(self):
44 return self.qname
45
46class LineBreakpoint:
Tor Norbye1aa2e092014-08-20 17:01:23 -070047
48 def __init__(self, line, condition, func_name, expression):
49 self.line = line
Tor Norbye3a2425a2013-11-04 10:16:08 -080050 self.condition = condition
51 self.func_name = func_name
52 self.expression = expression
53
Tor Norbye3a2425a2013-11-04 10:16:08 -080054def get_exception_full_qname(exctype):
55 if not exctype:
56 return None
57 return str(exctype.__module__) + '.' + exctype.__name__
58
59def get_exception_name(exctype):
60 if not exctype:
61 return None
62 return exctype.__name__
63
64
Tor Norbye1aa2e092014-08-20 17:01:23 -070065def get_exception_breakpoint(exctype, exceptions):
66 exception_full_qname = get_exception_full_qname(exctype)
67
Tor Norbye3a2425a2013-11-04 10:16:08 -080068 exc = None
69 if exceptions is not None:
Tor Norbye1aa2e092014-08-20 17:01:23 -070070 try:
71 return exceptions[exception_full_qname]
72 except KeyError:
73 for exception_breakpoint in DictIterValues(exceptions):
74 if exception_breakpoint.type is not None and issubclass(exctype, exception_breakpoint.type):
75 if exc is None or issubclass(exception_breakpoint.type, exc.type):
76 exc = exception_breakpoint
Tor Norbye3a2425a2013-11-04 10:16:08 -080077 return exc
78
79#=======================================================================================================================
Tor Norbye1aa2e092014-08-20 17:01:23 -070080# _excepthook
Tor Norbye3a2425a2013-11-04 10:16:08 -080081#=======================================================================================================================
Tor Norbye1aa2e092014-08-20 17:01:23 -070082def _excepthook(exctype, value, tb):
Tor Norbye3a2425a2013-11-04 10:16:08 -080083 global _handle_exceptions
Tor Norbye1aa2e092014-08-20 17:01:23 -070084 if _handle_exceptions:
85 exception_breakpoint = get_exception_breakpoint(exctype, _handle_exceptions)
Tor Norbye3a2425a2013-11-04 10:16:08 -080086 else:
87 exception_breakpoint = None
88
Tor Norbye3a2425a2013-11-04 10:16:08 -080089 #Always call the original excepthook before going on to call the debugger post mortem to show it.
90 _original_excepthook(exctype, value, tb)
91
Tor Norbye1aa2e092014-08-20 17:01:23 -070092 if not exception_breakpoint:
93 return
94
Tor Norbye3a2425a2013-11-04 10:16:08 -080095 if tb is None: #sometimes it can be None, e.g. with GTK
Tor Norbye1aa2e092014-08-20 17:01:23 -070096 return
Tor Norbye3a2425a2013-11-04 10:16:08 -080097
98 frames = []
99
Tor Norbye3a2425a2013-11-04 10:16:08 -0800100 while tb:
101 frames.append(tb.tb_frame)
102 tb = tb.tb_next
103
104 thread = threadingCurrentThread()
105 frames_byid = dict([(id(frame),frame) for frame in frames])
106 frame = frames[-1]
107 thread.additionalInfo.exception = (exctype, value, tb)
108 thread.additionalInfo.pydev_force_stop_at_exception = (frame, frames_byid)
109 thread.additionalInfo.message = exception_breakpoint.qname
Tor Norbye3a2425a2013-11-04 10:16:08 -0800110 debugger = GetGlobalDebugger()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800111
112 pydevd_tracing.SetTrace(None) #no tracing from here
Tor Norbye1fff8e22014-03-10 13:13:45 -0700113
114 pydev_log.debug('Handling post-mortem stop on exception breakpoint %s'% exception_breakpoint.qname)
115
Tor Norbye3a2425a2013-11-04 10:16:08 -0800116 debugger.handle_post_mortem_stop(thread.additionalInfo, thread)
117
118#=======================================================================================================================
Tor Norbye1aa2e092014-08-20 17:01:23 -0700119# _set_pm_excepthook
Tor Norbye3a2425a2013-11-04 10:16:08 -0800120#=======================================================================================================================
Tor Norbye1aa2e092014-08-20 17:01:23 -0700121def _set_pm_excepthook(handle_exceptions_dict=None):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800122 '''
123 Should be called to register the excepthook to be used.
124
Tor Norbye1aa2e092014-08-20 17:01:23 -0700125 It's only useful for uncaught exceptions. I.e.: exceptions that go up to the excepthook.
Tor Norbye3a2425a2013-11-04 10:16:08 -0800126
Tor Norbye1aa2e092014-08-20 17:01:23 -0700127 @param handle_exceptions: dict(exception -> ExceptionBreakpoint)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800128 The exceptions that should be handled.
129 '''
130 global _handle_exceptions
131 global _original_excepthook
Tor Norbye1aa2e092014-08-20 17:01:23 -0700132 if sys.excepthook != _excepthook:
133 #Only keep the original if it's not our own _excepthook (if called many times).
Tor Norbye3a2425a2013-11-04 10:16:08 -0800134 _original_excepthook = sys.excepthook
135
Tor Norbye1aa2e092014-08-20 17:01:23 -0700136 _handle_exceptions = handle_exceptions_dict
137 sys.excepthook = _excepthook
Tor Norbye3a2425a2013-11-04 10:16:08 -0800138
Tor Norbye1aa2e092014-08-20 17:01:23 -0700139def _restore_pm_excepthook():
Tor Norbye3a2425a2013-11-04 10:16:08 -0800140 global _original_excepthook
141 if _original_excepthook:
142 sys.excepthook = _original_excepthook
143 _original_excepthook = None
144
145
146def update_exception_hook(dbg):
Tor Norbye1aa2e092014-08-20 17:01:23 -0700147 if dbg.break_on_uncaught_exceptions:
148 _set_pm_excepthook(dbg.break_on_uncaught_exceptions)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800149 else:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700150 _restore_pm_excepthook()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800151
Tor Norbye1aa2e092014-08-20 17:01:23 -0700152def _get_class( kls ):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800153 if IS_PY24 and "BaseException" == kls:
154 kls = "Exception"
Tor Norbye1aa2e092014-08-20 17:01:23 -0700155
Tor Norbye3a2425a2013-11-04 10:16:08 -0800156 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700157 return eval(kls)
158 except:
159 return pydevd_import_class.ImportName(kls)