| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 1 | import linecache |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 2 | import os.path |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 3 | import re |
| 4 | import traceback # @Reimport |
| 5 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 6 | import pydev_log |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 7 | from pydevd_breakpoints import get_exception_breakpoint, get_exception_name |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 8 | from pydevd_comm import CMD_STEP_CAUGHT_EXCEPTION, CMD_STEP_RETURN, CMD_STEP_OVER, CMD_SET_BREAK, \ |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 9 | CMD_STEP_INTO, CMD_SMART_STEP_INTO, CMD_RUN_TO_LINE, CMD_SET_NEXT_STATEMENT |
| 10 | from pydevd_constants import * # @UnusedWildImport |
| 11 | from pydevd_file_utils import GetFilenameAndBase |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 12 | |
| 13 | from pydevd_frame_utils import add_exception_to_frame, just_raised |
| 14 | |
| Tor Norbye | c3d3a90 | 2014-09-04 13:24:04 -0700 | [diff] [blame] | 15 | try: |
| 16 | from pydevd_signature import sendSignatureCallTrace |
| 17 | except ImportError: |
| 18 | def sendSignatureCallTrace(*args, **kwargs): |
| 19 | pass |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 20 | import pydevd_vars |
| 21 | import pydevd_dont_trace |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 22 | |
| 23 | basename = os.path.basename |
| 24 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 25 | IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException') |
| 26 | |
| 27 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 28 | #======================================================================================================================= |
| 29 | # PyDBFrame |
| 30 | #======================================================================================================================= |
| 31 | class PyDBFrame: |
| 32 | '''This makes the tracing for a given frame, so, the trace_dispatch |
| 33 | is used initially when we enter into a new context ('call') and then |
| 34 | is reused for the entire context. |
| 35 | ''' |
| 36 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 37 | #Note: class (and not instance) attributes. |
| 38 | |
| 39 | #Same thing in the main debugger but only considering the file contents, while the one in the main debugger |
| 40 | #considers the user input (so, the actual result must be a join of both). |
| 41 | filename_to_lines_where_exceptions_are_ignored = {} |
| 42 | filename_to_stat_info = {} |
| 43 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 44 | def __init__(self, args): |
| 45 | #args = mainDebugger, filename, base, info, t, frame |
| 46 | #yeap, much faster than putting in self and then getting it from self later on |
| 47 | self._args = args[:-1] |
| 48 | |
| 49 | def setSuspend(self, *args, **kwargs): |
| 50 | self._args[0].setSuspend(*args, **kwargs) |
| 51 | |
| 52 | def doWaitSuspend(self, *args, **kwargs): |
| 53 | self._args[0].doWaitSuspend(*args, **kwargs) |
| 54 | |
| 55 | def trace_exception(self, frame, event, arg): |
| 56 | if event == 'exception': |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 57 | flag, frame = self.should_stop_on_exception(frame, event, arg) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 58 | |
| 59 | if flag: |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 60 | self.handle_exception(frame, event, arg) |
| 61 | return self.trace_dispatch |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 62 | |
| 63 | return self.trace_exception |
| 64 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 65 | def should_stop_on_exception(self, frame, event, arg): |
| 66 | mainDebugger, _filename, info, thread = self._args |
| 67 | flag = False |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 68 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 69 | if info.pydev_state != STATE_SUSPEND: #and breakpoint is not None: |
| 70 | exception, value, trace = arg |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 71 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 72 | if trace is not None: #on jython trace is None on the first event |
| 73 | exception_breakpoint = get_exception_breakpoint( |
| 74 | exception, mainDebugger.break_on_caught_exceptions) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 75 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 76 | if exception_breakpoint is not None: |
| 77 | if not exception_breakpoint.notify_on_first_raise_only or just_raised(trace): |
| 78 | # print frame.f_code.co_name |
| 79 | add_exception_to_frame(frame, (exception, value, trace)) |
| 80 | thread.additionalInfo.message = exception_breakpoint.qname |
| 81 | flag = True |
| 82 | else: |
| 83 | flag = False |
| 84 | else: |
| 85 | try: |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 86 | result = mainDebugger.plugin.exception_break(mainDebugger, self, frame, self._args, arg) |
| 87 | if result: |
| 88 | (flag, frame) = result |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 89 | |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 90 | except: |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 91 | flag = False |
| 92 | |
| 93 | return flag, frame |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 94 | |
| 95 | def handle_exception(self, frame, event, arg): |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 96 | try: |
| 97 | # print 'handle_exception', frame.f_lineno, frame.f_code.co_name |
| 98 | |
| 99 | # We have 3 things in arg: exception type, description, traceback object |
| 100 | trace_obj = arg[2] |
| 101 | mainDebugger = self._args[0] |
| 102 | |
| 103 | if not hasattr(trace_obj, 'tb_next'): |
| 104 | return #Not always there on Jython... |
| 105 | |
| 106 | initial_trace_obj = trace_obj |
| 107 | if trace_obj.tb_next is None and trace_obj.tb_frame is frame: |
| 108 | #I.e.: tb_next should be only None in the context it was thrown (trace_obj.tb_frame is frame is just a double check). |
| 109 | |
| 110 | if mainDebugger.break_on_exceptions_thrown_in_same_context: |
| 111 | #Option: Don't break if an exception is caught in the same function from which it is thrown |
| 112 | return |
| 113 | else: |
| 114 | #Get the trace_obj from where the exception was raised... |
| 115 | while trace_obj.tb_next is not None: |
| 116 | trace_obj = trace_obj.tb_next |
| 117 | |
| 118 | |
| 119 | if mainDebugger.ignore_exceptions_thrown_in_lines_with_ignore_exception: |
| 120 | for check_trace_obj in (initial_trace_obj, trace_obj): |
| 121 | filename = GetFilenameAndBase(check_trace_obj.tb_frame)[0] |
| 122 | |
| 123 | |
| 124 | filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored |
| 125 | |
| 126 | |
| 127 | lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(filename) |
| 128 | if lines_ignored is None: |
| 129 | lines_ignored = filename_to_lines_where_exceptions_are_ignored[filename] = {} |
| 130 | |
| 131 | try: |
| 132 | curr_stat = os.stat(filename) |
| 133 | curr_stat = (curr_stat.st_size, curr_stat.st_mtime) |
| 134 | except: |
| 135 | curr_stat = None |
| 136 | |
| 137 | last_stat = self.filename_to_stat_info.get(filename) |
| 138 | if last_stat != curr_stat: |
| 139 | self.filename_to_stat_info[filename] = curr_stat |
| 140 | lines_ignored.clear() |
| 141 | try: |
| 142 | linecache.checkcache(filename) |
| 143 | except: |
| 144 | #Jython 2.1 |
| 145 | linecache.checkcache() |
| 146 | |
| 147 | from_user_input = mainDebugger.filename_to_lines_where_exceptions_are_ignored.get(filename) |
| 148 | if from_user_input: |
| 149 | merged = {} |
| 150 | merged.update(lines_ignored) |
| 151 | #Override what we have with the related entries that the user entered |
| 152 | merged.update(from_user_input) |
| 153 | else: |
| 154 | merged = lines_ignored |
| 155 | |
| 156 | exc_lineno = check_trace_obj.tb_lineno |
| 157 | |
| 158 | # print ('lines ignored', lines_ignored) |
| 159 | # print ('user input', from_user_input) |
| 160 | # print ('merged', merged, 'curr', exc_lineno) |
| 161 | |
| 162 | if not DictContains(merged, exc_lineno): #Note: check on merged but update lines_ignored. |
| 163 | try: |
| 164 | line = linecache.getline(filename, exc_lineno, check_trace_obj.tb_frame.f_globals) |
| 165 | except: |
| 166 | #Jython 2.1 |
| 167 | line = linecache.getline(filename, exc_lineno) |
| 168 | |
| 169 | if IGNORE_EXCEPTION_TAG.match(line) is not None: |
| 170 | lines_ignored[exc_lineno] = 1 |
| 171 | return |
| 172 | else: |
| 173 | #Put in the cache saying not to ignore |
| 174 | lines_ignored[exc_lineno] = 0 |
| 175 | else: |
| 176 | #Ok, dict has it already cached, so, let's check it... |
| 177 | if merged.get(exc_lineno, 0): |
| 178 | return |
| 179 | |
| 180 | |
| 181 | thread = self._args[3] |
| 182 | |
| 183 | try: |
| 184 | frame_id_to_frame = {} |
| 185 | frame_id_to_frame[id(frame)] = frame |
| 186 | f = trace_obj.tb_frame |
| 187 | while f is not None: |
| 188 | frame_id_to_frame[id(f)] = f |
| 189 | f = f.f_back |
| 190 | f = None |
| 191 | |
| 192 | thread_id = GetThreadId(thread) |
| 193 | pydevd_vars.addAdditionalFrameById(thread_id, frame_id_to_frame) |
| 194 | try: |
| 195 | mainDebugger.sendCaughtExceptionStack(thread, arg, id(frame)) |
| 196 | self.setSuspend(thread, CMD_STEP_CAUGHT_EXCEPTION) |
| 197 | self.doWaitSuspend(thread, frame, event, arg) |
| 198 | mainDebugger.sendCaughtExceptionStackProceeded(thread) |
| 199 | |
| 200 | finally: |
| 201 | pydevd_vars.removeAdditionalFrameById(thread_id) |
| 202 | except: |
| 203 | traceback.print_exc() |
| 204 | |
| 205 | mainDebugger.SetTraceForFrameAndParents(frame) |
| 206 | finally: |
| 207 | #Clear some local variables... |
| 208 | trace_obj = None |
| 209 | initial_trace_obj = None |
| 210 | check_trace_obj = None |
| 211 | f = None |
| 212 | frame_id_to_frame = None |
| 213 | mainDebugger = None |
| 214 | thread = None |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 215 | |
| 216 | def trace_dispatch(self, frame, event, arg): |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 217 | main_debugger, filename, info, thread = self._args |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 218 | try: |
| 219 | info.is_tracing = True |
| 220 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 221 | if main_debugger._finishDebuggingSession: |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 222 | return None |
| 223 | |
| 224 | if getattr(thread, 'pydev_do_not_trace', None): |
| 225 | return None |
| 226 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 227 | if event == 'call' and main_debugger.signature_factory: |
| 228 | sendSignatureCallTrace(main_debugger, frame, filename) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 229 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 230 | is_exception_event = event == 'exception' |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 231 | has_exception_breakpoints = main_debugger.break_on_caught_exceptions \ |
| 232 | or main_debugger.plugin.has_exception_breaks(main_debugger) |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 233 | |
| 234 | if is_exception_event: |
| 235 | if has_exception_breakpoints: |
| 236 | flag, frame = self.should_stop_on_exception(frame, event, arg) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 237 | if flag: |
| 238 | self.handle_exception(frame, event, arg) |
| 239 | return self.trace_dispatch |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 240 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 241 | elif event not in ('line', 'call', 'return'): |
| 242 | #I believe this can only happen in jython on some frontiers on jython and java code, which we don't want to trace. |
| 243 | return None |
| 244 | |
| 245 | stop_frame = info.pydev_step_stop |
| 246 | step_cmd = info.pydev_step_cmd |
| 247 | |
| 248 | if is_exception_event: |
| 249 | breakpoints_for_file = None |
| 250 | else: |
| 251 | # If we are in single step mode and something causes us to exit the current frame, we need to make sure we break |
| 252 | # eventually. Force the step mode to step into and the step stop frame to None. |
| 253 | # I.e.: F6 in the end of a function should stop in the next possible position (instead of forcing the user |
| 254 | # to make a step in or step over at that location). |
| 255 | # Note: this is especially troublesome when we're skipping code with the |
| 256 | # @DontTrace comment. |
| 257 | if stop_frame is frame and event in ('return', 'exception') and step_cmd in (CMD_STEP_RETURN, CMD_STEP_OVER): |
| 258 | info.pydev_step_cmd = CMD_STEP_INTO |
| 259 | info.pydev_step_stop = None |
| 260 | |
| 261 | breakpoints_for_file = main_debugger.breakpoints.get(filename) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 262 | |
| 263 | can_skip = False |
| 264 | |
| 265 | if info.pydev_state == STATE_RUN: |
| 266 | #we can skip if: |
| 267 | #- we have no stop marked |
| 268 | #- we should make a step return/step over and we're not in the current frame |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 269 | can_skip = (step_cmd is None and stop_frame is None)\ |
| 270 | or (step_cmd in (CMD_STEP_RETURN, CMD_STEP_OVER) and stop_frame is not frame) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 271 | |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 272 | if can_skip: |
| 273 | can_skip = not main_debugger.plugin.can_not_skip(main_debugger, self, frame) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 274 | |
| 275 | # Let's check to see if we are in a function that has a breakpoint. If we don't have a breakpoint, |
| 276 | # we will return nothing for the next trace |
| 277 | #also, after we hit a breakpoint and go to some other debugging state, we have to force the set trace anyway, |
| 278 | #so, that's why the additional checks are there. |
| 279 | if not breakpoints_for_file: |
| 280 | if can_skip: |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 281 | if has_exception_breakpoints: |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 282 | return self.trace_exception |
| 283 | else: |
| 284 | return None |
| 285 | |
| 286 | else: |
| 287 | #checks the breakpoint to see if there is a context match in some function |
| 288 | curr_func_name = frame.f_code.co_name |
| 289 | |
| 290 | #global context is set with an empty name |
| 291 | if curr_func_name in ('?', '<module>'): |
| 292 | curr_func_name = '' |
| 293 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 294 | for breakpoint in DictIterValues(breakpoints_for_file): #jython does not support itervalues() |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 295 | #will match either global or some function |
| 296 | if breakpoint.func_name in ('None', curr_func_name): |
| 297 | break |
| 298 | |
| 299 | else: # if we had some break, it won't get here (so, that's a context that we want to skip) |
| 300 | if can_skip: |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 301 | if has_exception_breakpoints: |
| 302 | return self.trace_exception |
| 303 | else: |
| 304 | return None |
| 305 | |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 306 | |
| 307 | #We may have hit a breakpoint or we are already in step mode. Either way, let's check what we should do in this frame |
| 308 | #print 'NOT skipped', frame.f_lineno, frame.f_code.co_name, event |
| 309 | |
| 310 | try: |
| 311 | line = frame.f_lineno |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 312 | flag = False |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 313 | #return is not taken into account for breakpoint hit because we'd have a double-hit in this case |
| 314 | #(one for the line and the other for the return). |
| 315 | |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 316 | stop_info = {} |
| 317 | breakpoint = None |
| 318 | exist_result = False |
| 319 | stop_info['stop'] = False |
| 320 | if not flag and event != 'return' and info.pydev_state != STATE_SUSPEND and breakpoints_for_file is not None \ |
| 321 | and DictContains(breakpoints_for_file, line): |
| 322 | breakpoint = breakpoints_for_file[line] |
| 323 | new_frame = frame |
| 324 | stop_info['stop'] = True |
| 325 | if step_cmd == CMD_STEP_OVER and stop_frame is frame and event in ('line', 'return'): |
| 326 | stop_info['stop'] = False #we don't stop on breakpoint if we have to stop by step-over (it will be processed later) |
| 327 | else: |
| 328 | result = main_debugger.plugin.get_breakpoint(main_debugger, self, frame, event, self._args) |
| 329 | if result: |
| 330 | exist_result = True |
| 331 | (flag, breakpoint, new_frame) = result |
| 332 | |
| 333 | if breakpoint: |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 334 | #ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint |
| 335 | # lets do the conditional stuff here |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 336 | if stop_info['stop'] or exist_result: |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 337 | condition = breakpoint.condition |
| 338 | if condition is not None: |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 339 | try: |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 340 | val = eval(condition, new_frame.f_globals, new_frame.f_locals) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 341 | if not val: |
| 342 | return self.trace_dispatch |
| 343 | |
| 344 | except: |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 345 | if type(condition) != type(''): |
| 346 | if hasattr(condition, 'encode'): |
| 347 | condition = condition.encode('utf-8') |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 348 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 349 | msg = 'Error while evaluating expression: %s\n' % (condition,) |
| 350 | sys.stderr.write(msg) |
| 351 | traceback.print_exc() |
| 352 | if not main_debugger.suspend_on_breakpoint_exception: |
| 353 | return self.trace_dispatch |
| 354 | else: |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 355 | stop_info['stop'] = True |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 356 | try: |
| 357 | additional_info = None |
| 358 | try: |
| 359 | additional_info = thread.additionalInfo |
| 360 | except AttributeError: |
| 361 | pass #that's ok, no info currently set |
| 362 | |
| 363 | if additional_info is not None: |
| 364 | # add exception_type and stacktrace into thread additional info |
| 365 | etype, value, tb = sys.exc_info() |
| 366 | try: |
| 367 | error = ''.join(traceback.format_exception_only(etype, value)) |
| 368 | stack = traceback.extract_stack(f=tb.tb_frame.f_back) |
| 369 | |
| 370 | # On self.setSuspend(thread, CMD_SET_BREAK) this info will be |
| 371 | # sent to the client. |
| 372 | additional_info.conditional_breakpoint_exception = \ |
| 373 | ('Condition:\n' + condition + '\n\nError:\n' + error, stack) |
| 374 | finally: |
| 375 | etype, value, tb = None, None, None |
| 376 | except: |
| 377 | traceback.print_exc() |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 378 | |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 379 | if breakpoint.expression is not None: |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 380 | try: |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 381 | try: |
| 382 | val = eval(breakpoint.expression, new_frame.f_globals, new_frame.f_locals) |
| 383 | except: |
| 384 | val = sys.exc_info()[1] |
| 385 | finally: |
| 386 | if val is not None: |
| 387 | thread.additionalInfo.message = val |
| 388 | if stop_info['stop']: |
| 389 | self.setSuspend(thread, CMD_SET_BREAK) |
| 390 | elif flag: |
| 391 | result = main_debugger.plugin.suspend(main_debugger, thread, frame) |
| 392 | if result: |
| 393 | frame = result |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 394 | |
| 395 | # if thread has a suspend flag, we suspend with a busy wait |
| 396 | if info.pydev_state == STATE_SUSPEND: |
| 397 | self.doWaitSuspend(thread, frame, event, arg) |
| 398 | return self.trace_dispatch |
| 399 | |
| 400 | except: |
| Tor Norbye | c667c1f | 2014-05-28 17:06:51 -0700 | [diff] [blame] | 401 | traceback.print_exc() |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 402 | raise |
| 403 | |
| 404 | #step handling. We stop when we hit the right frame |
| 405 | try: |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 406 | should_skip = False |
| 407 | if pydevd_dont_trace.should_trace_hook is not None: |
| 408 | if not hasattr(self, 'should_skip'): |
| 409 | # I.e.: cache the result on self.should_skip (no need to evaluate the same frame multiple times). |
| 410 | # Note that on a code reload, we won't re-evaluate this because in practice, the frame.f_code |
| 411 | # Which will be handled by this frame is read-only, so, we can cache it safely. |
| 412 | should_skip = self.should_skip = not pydevd_dont_trace.should_trace_hook(frame, filename) |
| 413 | else: |
| 414 | should_skip = self.should_skip |
| 415 | |
| 416 | if should_skip: |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 417 | stop_info['stop'] = False |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 418 | |
| 419 | elif step_cmd == CMD_STEP_INTO: |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 420 | stop_info['stop'] = event in ('line', 'return') |
| 421 | main_debugger.plugin.cmd_step_into(main_debugger, frame, event, self._args, stop_info) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 422 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 423 | elif step_cmd == CMD_STEP_OVER: |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 424 | stop_info['stop'] = stop_frame is frame and event in ('line', 'return') |
| 425 | main_debugger.plugin.cmd_step_over(main_debugger, frame, event, self._args, stop_info) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 426 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 427 | elif step_cmd == CMD_SMART_STEP_INTO: |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 428 | stop_info['stop'] = False |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 429 | if info.pydev_smart_step_stop is frame: |
| 430 | info.pydev_func_name = None |
| 431 | info.pydev_smart_step_stop = None |
| 432 | |
| 433 | if event == 'line' or event == 'exception': |
| 434 | curr_func_name = frame.f_code.co_name |
| 435 | |
| 436 | #global context is set with an empty name |
| 437 | if curr_func_name in ('?', '<module>') or curr_func_name is None: |
| 438 | curr_func_name = '' |
| 439 | |
| 440 | if curr_func_name == info.pydev_func_name: |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 441 | stop_info['stop'] = True |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 442 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 443 | elif step_cmd == CMD_STEP_RETURN: |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 444 | stop_info['stop'] = event == 'return' and stop_frame is frame |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 445 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 446 | elif step_cmd == CMD_RUN_TO_LINE or step_cmd == CMD_SET_NEXT_STATEMENT: |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 447 | stop_info['stop'] = False |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 448 | |
| 449 | if event == 'line' or event == 'exception': |
| 450 | #Yes, we can only act on line events (weird hum?) |
| 451 | #Note: This code is duplicated at pydevd.py |
| 452 | #Acting on exception events after debugger breaks with exception |
| 453 | curr_func_name = frame.f_code.co_name |
| 454 | |
| 455 | #global context is set with an empty name |
| 456 | if curr_func_name in ('?', '<module>'): |
| 457 | curr_func_name = '' |
| 458 | |
| 459 | if curr_func_name == info.pydev_func_name: |
| 460 | line = info.pydev_next_line |
| 461 | if frame.f_lineno == line: |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 462 | stop_info['stop'] = True |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 463 | else: |
| 464 | if frame.f_trace is None: |
| 465 | frame.f_trace = self.trace_dispatch |
| 466 | frame.f_lineno = line |
| 467 | frame.f_trace = None |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 468 | stop_info['stop'] = True |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 469 | |
| 470 | else: |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 471 | stop_info['stop'] = False |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 472 | |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 473 | if True in DictIterValues(stop_info): |
| 474 | stopped_on_plugin = main_debugger.plugin.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd) |
| 475 | if DictContains(stop_info, 'stop') and stop_info['stop'] and not stopped_on_plugin: |
| 476 | if event == 'line': |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 477 | self.setSuspend(thread, step_cmd) |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 478 | self.doWaitSuspend(thread, frame, event, arg) |
| 479 | else: #return event |
| 480 | back = frame.f_back |
| 481 | if back is not None: |
| 482 | #When we get to the pydevd run function, the debugging has actually finished for the main thread |
| 483 | #(note that it can still go on for other threads, but for this one, we just make it finish) |
| 484 | #So, just setting it to None should be OK |
| 485 | base = basename(back.f_code.co_filename) |
| 486 | if base == 'pydevd.py' and back.f_code.co_name == 'run': |
| 487 | back = None |
| 488 | |
| 489 | elif base == 'pydevd_traceproperty.py': |
| 490 | # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging) |
| 491 | #if we're in a return, we want it to appear to the user in the previous frame! |
| 492 | return None |
| 493 | |
| 494 | if back is not None: |
| 495 | #if we're in a return, we want it to appear to the user in the previous frame! |
| 496 | self.setSuspend(thread, step_cmd) |
| 497 | self.doWaitSuspend(thread, back, event, arg) |
| 498 | else: |
| 499 | #in jython we may not have a back frame |
| 500 | info.pydev_step_stop = None |
| 501 | info.pydev_step_cmd = None |
| 502 | info.pydev_state = STATE_RUN |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 503 | |
| 504 | |
| 505 | except: |
| 506 | traceback.print_exc() |
| 507 | info.pydev_step_cmd = None |
| 508 | |
| 509 | #if we are quitting, let's stop the tracing |
| 510 | retVal = None |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame] | 511 | if not main_debugger.quitting: |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 512 | retVal = self.trace_dispatch |
| 513 | |
| 514 | return retVal |
| 515 | finally: |
| 516 | info.is_tracing = False |
| 517 | |
| 518 | #end trace_dispatch |
| 519 | |
| 520 | if USE_PSYCO_OPTIMIZATION: |
| 521 | try: |
| 522 | import psyco |
| 523 | |
| 524 | trace_dispatch = psyco.proxy(trace_dispatch) |
| 525 | except ImportError: |
| 526 | if hasattr(sys, 'exc_clear'): #jython does not have it |
| 527 | sys.exc_clear() #don't keep the traceback |
| Tor Norbye | e782c57 | 2014-09-18 11:43:07 -0700 | [diff] [blame] | 528 | pass #ok, psyco not available |