blob: 5d1e784583914f461cfb883f97378d52c1596eec [file] [log] [blame]
Tor Norbye1aa2e092014-08-20 17:01:23 -07001import linecache
Tor Norbye3a2425a2013-11-04 10:16:08 -08002import os.path
Tor Norbye1aa2e092014-08-20 17:01:23 -07003import re
4import traceback # @Reimport
5
6from django_debug import find_django_render_frame
7from django_debug import is_django_render_call, is_django_suspended, suspend_django, is_django_resolve_call, is_django_context_get_call
8from django_frame import DjangoTemplateFrame
9from django_frame import is_django_exception_break_context
10from django_frame import just_raised, get_template_file_name, get_template_line
Tor Norbye3a2425a2013-11-04 10:16:08 -080011import pydev_log
Tor Norbye1aa2e092014-08-20 17:01:23 -070012from pydevd_breakpoints import get_exception_breakpoint, get_exception_name
13from pydevd_comm import CMD_ADD_DJANGO_EXCEPTION_BREAK, \
14 CMD_STEP_CAUGHT_EXCEPTION, CMD_STEP_RETURN, CMD_STEP_OVER, CMD_SET_BREAK, \
15 CMD_STEP_INTO, CMD_SMART_STEP_INTO, CMD_RUN_TO_LINE, CMD_SET_NEXT_STATEMENT
16from pydevd_constants import * # @UnusedWildImport
17from pydevd_file_utils import GetFilenameAndBase
Tor Norbyec3d3a902014-09-04 13:24:04 -070018try:
19 from pydevd_signature import sendSignatureCallTrace
20except ImportError:
21 def sendSignatureCallTrace(*args, **kwargs):
22 pass
Tor Norbye1aa2e092014-08-20 17:01:23 -070023import pydevd_vars
24import pydevd_dont_trace
Tor Norbye3a2425a2013-11-04 10:16:08 -080025
26basename = os.path.basename
27
Tor Norbye1aa2e092014-08-20 17:01:23 -070028IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException')
29
30
Tor Norbye3a2425a2013-11-04 10:16:08 -080031#=======================================================================================================================
32# PyDBFrame
33#=======================================================================================================================
34class PyDBFrame:
35 '''This makes the tracing for a given frame, so, the trace_dispatch
36 is used initially when we enter into a new context ('call') and then
37 is reused for the entire context.
38 '''
39
Tor Norbye1aa2e092014-08-20 17:01:23 -070040 #Note: class (and not instance) attributes.
41
42 #Same thing in the main debugger but only considering the file contents, while the one in the main debugger
43 #considers the user input (so, the actual result must be a join of both).
44 filename_to_lines_where_exceptions_are_ignored = {}
45 filename_to_stat_info = {}
46
Tor Norbye3a2425a2013-11-04 10:16:08 -080047 def __init__(self, args):
48 #args = mainDebugger, filename, base, info, t, frame
49 #yeap, much faster than putting in self and then getting it from self later on
50 self._args = args[:-1]
51
52 def setSuspend(self, *args, **kwargs):
53 self._args[0].setSuspend(*args, **kwargs)
54
55 def doWaitSuspend(self, *args, **kwargs):
56 self._args[0].doWaitSuspend(*args, **kwargs)
57
Tor Norbye1aa2e092014-08-20 17:01:23 -070058 def _is_django_render_call(self, frame):
59 try:
60 return self._cached_is_django_render_call
61 except:
62 # Calculate lazily: note that a PyDBFrame always deals with the same
63 # frame over and over, so, we can cache this.
64 # -- although we can't cache things which change over time (such as
65 # the breakpoints for the file).
66 ret = self._cached_is_django_render_call = is_django_render_call(frame)
67 return ret
68
Tor Norbye3a2425a2013-11-04 10:16:08 -080069 def trace_exception(self, frame, event, arg):
70 if event == 'exception':
Tor Norbye1aa2e092014-08-20 17:01:23 -070071 flag, frame = self.should_stop_on_exception(frame, event, arg)
Tor Norbye3a2425a2013-11-04 10:16:08 -080072
73 if flag:
Tor Norbye1aa2e092014-08-20 17:01:23 -070074 self.handle_exception(frame, event, arg)
75 return self.trace_dispatch
Tor Norbye3a2425a2013-11-04 10:16:08 -080076
77 return self.trace_exception
78
Tor Norbye1aa2e092014-08-20 17:01:23 -070079 def should_stop_on_exception(self, frame, event, arg):
80 mainDebugger, _filename, info, thread = self._args
81 flag = False
Tor Norbye3a2425a2013-11-04 10:16:08 -080082
Tor Norbye1aa2e092014-08-20 17:01:23 -070083 if info.pydev_state != STATE_SUSPEND: #and breakpoint is not None:
84 exception, value, trace = arg
Tor Norbye3a2425a2013-11-04 10:16:08 -080085
Tor Norbye1aa2e092014-08-20 17:01:23 -070086 if trace is not None: #on jython trace is None on the first event
87 exception_breakpoint = get_exception_breakpoint(
88 exception, mainDebugger.break_on_caught_exceptions)
Tor Norbye3a2425a2013-11-04 10:16:08 -080089
Tor Norbye1aa2e092014-08-20 17:01:23 -070090 if exception_breakpoint is not None:
91 if not exception_breakpoint.notify_on_first_raise_only or just_raised(trace):
92 # print frame.f_code.co_name
93 add_exception_to_frame(frame, (exception, value, trace))
94 thread.additionalInfo.message = exception_breakpoint.qname
95 flag = True
96 else:
97 flag = False
98 else:
99 try:
100 if mainDebugger.django_exception_break and get_exception_name(exception) in [
101 'VariableDoesNotExist', 'TemplateDoesNotExist', 'TemplateSyntaxError'] \
102 and just_raised(trace) and is_django_exception_break_context(frame):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800103
Tor Norbye1aa2e092014-08-20 17:01:23 -0700104 render_frame = find_django_render_frame(frame)
105 if render_frame:
106 suspend_frame = suspend_django(
107 self, mainDebugger, thread, render_frame, CMD_ADD_DJANGO_EXCEPTION_BREAK)
108
109 if suspend_frame:
110 add_exception_to_frame(suspend_frame, (exception, value, trace))
111 flag = True
112 thread.additionalInfo.message = 'VariableDoesNotExist'
113 suspend_frame.f_back = frame
114 frame = suspend_frame
115 except :
116 flag = False
117
118 return flag, frame
Tor Norbye3a2425a2013-11-04 10:16:08 -0800119
120 def handle_exception(self, frame, event, arg):
Tor Norbye1aa2e092014-08-20 17:01:23 -0700121 try:
122 # print 'handle_exception', frame.f_lineno, frame.f_code.co_name
123
124 # We have 3 things in arg: exception type, description, traceback object
125 trace_obj = arg[2]
126 mainDebugger = self._args[0]
127
128 if not hasattr(trace_obj, 'tb_next'):
129 return #Not always there on Jython...
130
131 initial_trace_obj = trace_obj
132 if trace_obj.tb_next is None and trace_obj.tb_frame is frame:
133 #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).
134
135 if mainDebugger.break_on_exceptions_thrown_in_same_context:
136 #Option: Don't break if an exception is caught in the same function from which it is thrown
137 return
138 else:
139 #Get the trace_obj from where the exception was raised...
140 while trace_obj.tb_next is not None:
141 trace_obj = trace_obj.tb_next
142
143
144 if mainDebugger.ignore_exceptions_thrown_in_lines_with_ignore_exception:
145 for check_trace_obj in (initial_trace_obj, trace_obj):
146 filename = GetFilenameAndBase(check_trace_obj.tb_frame)[0]
147
148
149 filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored
150
151
152 lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(filename)
153 if lines_ignored is None:
154 lines_ignored = filename_to_lines_where_exceptions_are_ignored[filename] = {}
155
156 try:
157 curr_stat = os.stat(filename)
158 curr_stat = (curr_stat.st_size, curr_stat.st_mtime)
159 except:
160 curr_stat = None
161
162 last_stat = self.filename_to_stat_info.get(filename)
163 if last_stat != curr_stat:
164 self.filename_to_stat_info[filename] = curr_stat
165 lines_ignored.clear()
166 try:
167 linecache.checkcache(filename)
168 except:
169 #Jython 2.1
170 linecache.checkcache()
171
172 from_user_input = mainDebugger.filename_to_lines_where_exceptions_are_ignored.get(filename)
173 if from_user_input:
174 merged = {}
175 merged.update(lines_ignored)
176 #Override what we have with the related entries that the user entered
177 merged.update(from_user_input)
178 else:
179 merged = lines_ignored
180
181 exc_lineno = check_trace_obj.tb_lineno
182
183 # print ('lines ignored', lines_ignored)
184 # print ('user input', from_user_input)
185 # print ('merged', merged, 'curr', exc_lineno)
186
187 if not DictContains(merged, exc_lineno): #Note: check on merged but update lines_ignored.
188 try:
189 line = linecache.getline(filename, exc_lineno, check_trace_obj.tb_frame.f_globals)
190 except:
191 #Jython 2.1
192 line = linecache.getline(filename, exc_lineno)
193
194 if IGNORE_EXCEPTION_TAG.match(line) is not None:
195 lines_ignored[exc_lineno] = 1
196 return
197 else:
198 #Put in the cache saying not to ignore
199 lines_ignored[exc_lineno] = 0
200 else:
201 #Ok, dict has it already cached, so, let's check it...
202 if merged.get(exc_lineno, 0):
203 return
204
205
206 thread = self._args[3]
207
208 try:
209 frame_id_to_frame = {}
210 frame_id_to_frame[id(frame)] = frame
211 f = trace_obj.tb_frame
212 while f is not None:
213 frame_id_to_frame[id(f)] = f
214 f = f.f_back
215 f = None
216
217 thread_id = GetThreadId(thread)
218 pydevd_vars.addAdditionalFrameById(thread_id, frame_id_to_frame)
219 try:
220 mainDebugger.sendCaughtExceptionStack(thread, arg, id(frame))
221 self.setSuspend(thread, CMD_STEP_CAUGHT_EXCEPTION)
222 self.doWaitSuspend(thread, frame, event, arg)
223 mainDebugger.sendCaughtExceptionStackProceeded(thread)
224
225 finally:
226 pydevd_vars.removeAdditionalFrameById(thread_id)
227 except:
228 traceback.print_exc()
229
230 mainDebugger.SetTraceForFrameAndParents(frame)
231 finally:
232 #Clear some local variables...
233 trace_obj = None
234 initial_trace_obj = None
235 check_trace_obj = None
236 f = None
237 frame_id_to_frame = None
238 mainDebugger = None
239 thread = None
Tor Norbye3a2425a2013-11-04 10:16:08 -0800240
241 def trace_dispatch(self, frame, event, arg):
Tor Norbye1aa2e092014-08-20 17:01:23 -0700242 main_debugger, filename, info, thread = self._args
Tor Norbye3a2425a2013-11-04 10:16:08 -0800243 try:
244 info.is_tracing = True
245
Tor Norbye1aa2e092014-08-20 17:01:23 -0700246 if main_debugger._finishDebuggingSession:
Tor Norbye3a2425a2013-11-04 10:16:08 -0800247 return None
248
249 if getattr(thread, 'pydev_do_not_trace', None):
250 return None
251
Tor Norbye1aa2e092014-08-20 17:01:23 -0700252 if event == 'call' and main_debugger.signature_factory:
253 sendSignatureCallTrace(main_debugger, frame, filename)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800254
Tor Norbye1aa2e092014-08-20 17:01:23 -0700255 is_exception_event = event == 'exception'
256 has_exception_breakpoints = main_debugger.break_on_caught_exceptions or main_debugger.django_exception_break
257
258 if is_exception_event:
259 if has_exception_breakpoints:
260 flag, frame = self.should_stop_on_exception(frame, event, arg)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800261 if flag:
262 self.handle_exception(frame, event, arg)
263 return self.trace_dispatch
Tor Norbye3a2425a2013-11-04 10:16:08 -0800264
Tor Norbye1aa2e092014-08-20 17:01:23 -0700265 elif event not in ('line', 'call', 'return'):
266 #I believe this can only happen in jython on some frontiers on jython and java code, which we don't want to trace.
267 return None
268
269 stop_frame = info.pydev_step_stop
270 step_cmd = info.pydev_step_cmd
271
272 if is_exception_event:
273 breakpoints_for_file = None
274 else:
275 # If we are in single step mode and something causes us to exit the current frame, we need to make sure we break
276 # eventually. Force the step mode to step into and the step stop frame to None.
277 # I.e.: F6 in the end of a function should stop in the next possible position (instead of forcing the user
278 # to make a step in or step over at that location).
279 # Note: this is especially troublesome when we're skipping code with the
280 # @DontTrace comment.
281 if stop_frame is frame and event in ('return', 'exception') and step_cmd in (CMD_STEP_RETURN, CMD_STEP_OVER):
282 info.pydev_step_cmd = CMD_STEP_INTO
283 info.pydev_step_stop = None
284
285 breakpoints_for_file = main_debugger.breakpoints.get(filename)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800286
287 can_skip = False
288
289 if info.pydev_state == STATE_RUN:
290 #we can skip if:
291 #- we have no stop marked
292 #- we should make a step return/step over and we're not in the current frame
Tor Norbye1aa2e092014-08-20 17:01:23 -0700293 can_skip = (step_cmd is None and stop_frame is None)\
294 or (step_cmd in (CMD_STEP_RETURN, CMD_STEP_OVER) and stop_frame is not frame)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800295
Tor Norbye1aa2e092014-08-20 17:01:23 -0700296 check_stop_on_django_render_call = main_debugger.django_breakpoints and self._is_django_render_call(frame)
297 if check_stop_on_django_render_call:
Tor Norbye3a2425a2013-11-04 10:16:08 -0800298 can_skip = False
299
300 # Let's check to see if we are in a function that has a breakpoint. If we don't have a breakpoint,
301 # we will return nothing for the next trace
302 #also, after we hit a breakpoint and go to some other debugging state, we have to force the set trace anyway,
303 #so, that's why the additional checks are there.
304 if not breakpoints_for_file:
305 if can_skip:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700306 if has_exception_breakpoints:
Tor Norbye3a2425a2013-11-04 10:16:08 -0800307 return self.trace_exception
308 else:
309 return None
310
311 else:
312 #checks the breakpoint to see if there is a context match in some function
313 curr_func_name = frame.f_code.co_name
314
315 #global context is set with an empty name
316 if curr_func_name in ('?', '<module>'):
317 curr_func_name = ''
318
Tor Norbye1aa2e092014-08-20 17:01:23 -0700319 for breakpoint in DictIterValues(breakpoints_for_file): #jython does not support itervalues()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800320 #will match either global or some function
321 if breakpoint.func_name in ('None', curr_func_name):
322 break
323
324 else: # if we had some break, it won't get here (so, that's a context that we want to skip)
325 if can_skip:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700326 if has_exception_breakpoints:
327 return self.trace_exception
328 else:
329 return None
330
Tor Norbye3a2425a2013-11-04 10:16:08 -0800331
332 #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
333 #print 'NOT skipped', frame.f_lineno, frame.f_code.co_name, event
334
335 try:
336 line = frame.f_lineno
337
338
339 flag = False
Tor Norbye1aa2e092014-08-20 17:01:23 -0700340 if event == 'call' and info.pydev_state != STATE_SUSPEND and check_stop_on_django_render_call:
341 flag, frame = self.should_stop_on_django_breakpoint(frame, event, arg)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800342
343 #return is not taken into account for breakpoint hit because we'd have a double-hit in this case
344 #(one for the line and the other for the return).
345
346 if not flag and event != 'return' and info.pydev_state != STATE_SUSPEND and breakpoints_for_file is not None\
Tor Norbye1aa2e092014-08-20 17:01:23 -0700347 and DictContains(breakpoints_for_file, line):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800348 #ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint
349 # lets do the conditional stuff here
350 breakpoint = breakpoints_for_file[line]
351
352 stop = True
Tor Norbye1aa2e092014-08-20 17:01:23 -0700353 if step_cmd == CMD_STEP_OVER and stop_frame is frame and event in ('line', 'return'):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800354 stop = False #we don't stop on breakpoint if we have to stop by step-over (it will be processed later)
355 else:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700356 condition = breakpoint.condition
357 if condition is not None:
Tor Norbye3a2425a2013-11-04 10:16:08 -0800358 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700359 val = eval(condition, frame.f_globals, frame.f_locals)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800360 if not val:
361 return self.trace_dispatch
362
363 except:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700364 if type(condition) != type(''):
365 if hasattr(condition, 'encode'):
366 condition = condition.encode('utf-8')
Tor Norbye3a2425a2013-11-04 10:16:08 -0800367
Tor Norbye1aa2e092014-08-20 17:01:23 -0700368 msg = 'Error while evaluating expression: %s\n' % (condition,)
369 sys.stderr.write(msg)
370 traceback.print_exc()
371 if not main_debugger.suspend_on_breakpoint_exception:
372 return self.trace_dispatch
373 else:
374 stop = True
375 try:
376 additional_info = None
377 try:
378 additional_info = thread.additionalInfo
379 except AttributeError:
380 pass #that's ok, no info currently set
381
382 if additional_info is not None:
383 # add exception_type and stacktrace into thread additional info
384 etype, value, tb = sys.exc_info()
385 try:
386 error = ''.join(traceback.format_exception_only(etype, value))
387 stack = traceback.extract_stack(f=tb.tb_frame.f_back)
388
389 # On self.setSuspend(thread, CMD_SET_BREAK) this info will be
390 # sent to the client.
391 additional_info.conditional_breakpoint_exception = \
392 ('Condition:\n' + condition + '\n\nError:\n' + error, stack)
393 finally:
394 etype, value, tb = None, None, None
395 except:
396 traceback.print_exc()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800397
398 if breakpoint.expression is not None:
399 try:
400 try:
401 val = eval(breakpoint.expression, frame.f_globals, frame.f_locals)
402 except:
403 val = sys.exc_info()[1]
404 finally:
405 if val is not None:
406 thread.additionalInfo.message = val
407
408 if stop:
409 self.setSuspend(thread, CMD_SET_BREAK)
410
411 # if thread has a suspend flag, we suspend with a busy wait
412 if info.pydev_state == STATE_SUSPEND:
413 self.doWaitSuspend(thread, frame, event, arg)
414 return self.trace_dispatch
415
416 except:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700417 traceback.print_exc()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800418 raise
419
420 #step handling. We stop when we hit the right frame
421 try:
422 django_stop = False
Tor Norbye1aa2e092014-08-20 17:01:23 -0700423
424 should_skip = False
425 if pydevd_dont_trace.should_trace_hook is not None:
426 if not hasattr(self, 'should_skip'):
427 # I.e.: cache the result on self.should_skip (no need to evaluate the same frame multiple times).
428 # Note that on a code reload, we won't re-evaluate this because in practice, the frame.f_code
429 # Which will be handled by this frame is read-only, so, we can cache it safely.
430 should_skip = self.should_skip = not pydevd_dont_trace.should_trace_hook(frame, filename)
431 else:
432 should_skip = self.should_skip
433
434 if should_skip:
435 stop = False
436
437 elif step_cmd == CMD_STEP_INTO:
Tor Norbye3a2425a2013-11-04 10:16:08 -0800438 stop = event in ('line', 'return')
Tor Norbye1aa2e092014-08-20 17:01:23 -0700439
Tor Norbye3a2425a2013-11-04 10:16:08 -0800440 if is_django_suspended(thread):
441 #django_stop = event == 'call' and is_django_render_call(frame)
442 stop = stop and is_django_resolve_call(frame.f_back) and not is_django_context_get_call(frame)
443 if stop:
444 info.pydev_django_resolve_frame = 1 #we remember that we've go into python code from django rendering frame
445
Tor Norbye1aa2e092014-08-20 17:01:23 -0700446 elif step_cmd == CMD_STEP_OVER:
Tor Norbye3a2425a2013-11-04 10:16:08 -0800447 if is_django_suspended(thread):
Tor Norbye1aa2e092014-08-20 17:01:23 -0700448 django_stop = event == 'call' and self._is_django_render_call(frame)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800449
450 stop = False
451 else:
452 if event == 'return' and info.pydev_django_resolve_frame is not None and is_django_resolve_call(frame.f_back):
453 #we return to Django suspend mode and should not stop before django rendering frame
Tor Norbye1aa2e092014-08-20 17:01:23 -0700454 stop_frame = info.pydev_step_stop = info.pydev_django_resolve_frame
Tor Norbye3a2425a2013-11-04 10:16:08 -0800455 info.pydev_django_resolve_frame = None
456 thread.additionalInfo.suspend_type = DJANGO_SUSPEND
457
458
Tor Norbye1aa2e092014-08-20 17:01:23 -0700459 stop = stop_frame is frame and event in ('line', 'return')
Tor Norbye3a2425a2013-11-04 10:16:08 -0800460
Tor Norbye1aa2e092014-08-20 17:01:23 -0700461 elif step_cmd == CMD_SMART_STEP_INTO:
Tor Norbye3a2425a2013-11-04 10:16:08 -0800462 stop = False
463 if info.pydev_smart_step_stop is frame:
464 info.pydev_func_name = None
465 info.pydev_smart_step_stop = None
466
467 if event == 'line' or event == 'exception':
468 curr_func_name = frame.f_code.co_name
469
470 #global context is set with an empty name
471 if curr_func_name in ('?', '<module>') or curr_func_name is None:
472 curr_func_name = ''
473
474 if curr_func_name == info.pydev_func_name:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700475 stop = True
Tor Norbye3a2425a2013-11-04 10:16:08 -0800476
Tor Norbye1aa2e092014-08-20 17:01:23 -0700477 elif step_cmd == CMD_STEP_RETURN:
478 stop = event == 'return' and stop_frame is frame
Tor Norbye3a2425a2013-11-04 10:16:08 -0800479
Tor Norbye1aa2e092014-08-20 17:01:23 -0700480 elif step_cmd == CMD_RUN_TO_LINE or step_cmd == CMD_SET_NEXT_STATEMENT:
Tor Norbye3a2425a2013-11-04 10:16:08 -0800481 stop = False
482
483 if event == 'line' or event == 'exception':
484 #Yes, we can only act on line events (weird hum?)
485 #Note: This code is duplicated at pydevd.py
486 #Acting on exception events after debugger breaks with exception
487 curr_func_name = frame.f_code.co_name
488
489 #global context is set with an empty name
490 if curr_func_name in ('?', '<module>'):
491 curr_func_name = ''
492
493 if curr_func_name == info.pydev_func_name:
494 line = info.pydev_next_line
495 if frame.f_lineno == line:
496 stop = True
497 else:
498 if frame.f_trace is None:
499 frame.f_trace = self.trace_dispatch
500 frame.f_lineno = line
501 frame.f_trace = None
502 stop = True
503
504 else:
505 stop = False
506
507 if django_stop:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700508 frame = suspend_django(self, main_debugger, thread, frame)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800509 if frame:
510 self.doWaitSuspend(thread, frame, event, arg)
511 elif stop:
512 #event is always == line or return at this point
513 if event == 'line':
Tor Norbye1aa2e092014-08-20 17:01:23 -0700514 self.setSuspend(thread, step_cmd)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800515 self.doWaitSuspend(thread, frame, event, arg)
516 else: #return event
517 back = frame.f_back
518 if back is not None:
519 #When we get to the pydevd run function, the debugging has actually finished for the main thread
520 #(note that it can still go on for other threads, but for this one, we just make it finish)
521 #So, just setting it to None should be OK
Tor Norbye1aa2e092014-08-20 17:01:23 -0700522 base = basename(back.f_code.co_filename)
523 if base == 'pydevd.py' and back.f_code.co_name == 'run':
Tor Norbye3a2425a2013-11-04 10:16:08 -0800524 back = None
525
Tor Norbye1aa2e092014-08-20 17:01:23 -0700526 elif base == 'pydevd_traceproperty.py':
527 # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging)
528 #if we're in a return, we want it to appear to the user in the previous frame!
529 return None
530
Tor Norbye3a2425a2013-11-04 10:16:08 -0800531 if back is not None:
532 #if we're in a return, we want it to appear to the user in the previous frame!
Tor Norbye1aa2e092014-08-20 17:01:23 -0700533 self.setSuspend(thread, step_cmd)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800534 self.doWaitSuspend(thread, back, event, arg)
535 else:
536 #in jython we may not have a back frame
537 info.pydev_step_stop = None
538 info.pydev_step_cmd = None
539 info.pydev_state = STATE_RUN
540
541
542 except:
543 traceback.print_exc()
544 info.pydev_step_cmd = None
545
546 #if we are quitting, let's stop the tracing
547 retVal = None
Tor Norbye1aa2e092014-08-20 17:01:23 -0700548 if not main_debugger.quitting:
Tor Norbye3a2425a2013-11-04 10:16:08 -0800549 retVal = self.trace_dispatch
550
551 return retVal
552 finally:
553 info.is_tracing = False
554
555 #end trace_dispatch
556
557 if USE_PSYCO_OPTIMIZATION:
558 try:
559 import psyco
560
561 trace_dispatch = psyco.proxy(trace_dispatch)
562 except ImportError:
563 if hasattr(sys, 'exc_clear'): #jython does not have it
564 sys.exc_clear() #don't keep the traceback
565 pass #ok, psyco not available
566
Tor Norbye1aa2e092014-08-20 17:01:23 -0700567 def should_stop_on_django_breakpoint(self, frame, event, arg):
568 mainDebugger = self._args[0]
569 thread = self._args[3]
Tor Norbyec667c1f2014-05-28 17:06:51 -0700570 flag = False
Tor Norbye1aa2e092014-08-20 17:01:23 -0700571 template_frame_file = get_template_file_name(frame)
572
573 #pydev_log.debug("Django is rendering a template: %s\n" % template_frame_file)
574
575 django_breakpoints_for_file = mainDebugger.django_breakpoints.get(template_frame_file)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700576 if django_breakpoints_for_file:
Tor Norbye3a2425a2013-11-04 10:16:08 -0800577
Tor Norbye1aa2e092014-08-20 17:01:23 -0700578 #pydev_log.debug("Breakpoints for that file: %s\n" % django_breakpoints_for_file)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800579
Tor Norbye1aa2e092014-08-20 17:01:23 -0700580 template_frame_line = get_template_line(frame, template_frame_file)
581
582 #pydev_log.debug("Tracing template line: %d\n" % template_frame_line)
583
584 if DictContains(django_breakpoints_for_file, template_frame_line):
585 django_breakpoint = django_breakpoints_for_file[template_frame_line]
586
587 if django_breakpoint.is_triggered(template_frame_file, template_frame_line):
588
589 #pydev_log.debug("Breakpoint is triggered.\n")
590
Tor Norbyec667c1f2014-05-28 17:06:51 -0700591 flag = True
Tor Norbye1aa2e092014-08-20 17:01:23 -0700592 new_frame = DjangoTemplateFrame(
593 frame,
594 template_frame_file=template_frame_file,
595 template_frame_line=template_frame_line,
596 )
Tor Norbye3a2425a2013-11-04 10:16:08 -0800597
Tor Norbyec667c1f2014-05-28 17:06:51 -0700598 if django_breakpoint.condition is not None:
599 try:
600 val = eval(django_breakpoint.condition, new_frame.f_globals, new_frame.f_locals)
601 if not val:
602 flag = False
603 pydev_log.debug("Condition '%s' is evaluated to %s. Not suspending.\n" % (django_breakpoint.condition, val))
604 except:
605 pydev_log.info(
606 'Error while evaluating condition \'%s\': %s\n' % (django_breakpoint.condition, sys.exc_info()[1]))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800607
Tor Norbyec667c1f2014-05-28 17:06:51 -0700608 if django_breakpoint.expression is not None:
609 try:
610 try:
611 val = eval(django_breakpoint.expression, new_frame.f_globals, new_frame.f_locals)
612 except:
613 val = sys.exc_info()[1]
614 finally:
615 if val is not None:
616 thread.additionalInfo.message = val
617 if flag:
618 frame = suspend_django(self, mainDebugger, thread, frame)
Tor Norbye1aa2e092014-08-20 17:01:23 -0700619 return flag, frame
Tor Norbye3a2425a2013-11-04 10:16:08 -0800620
621def add_exception_to_frame(frame, exception_info):
622 frame.f_locals['__exception__'] = exception_info