1import linecache
2import os.path
3import re
4import sys
5import traceback  # @Reimport
6
7from _pydev_bundle import pydev_log
8from _pydevd_bundle import pydevd_dont_trace
9from _pydevd_bundle import pydevd_vars
10from _pydevd_bundle.pydevd_breakpoints import get_exception_breakpoint
11from _pydevd_bundle.pydevd_comm import CMD_STEP_CAUGHT_EXCEPTION, CMD_STEP_RETURN, CMD_STEP_OVER, CMD_SET_BREAK, \
12    CMD_STEP_INTO, CMD_SMART_STEP_INTO, CMD_RUN_TO_LINE, CMD_SET_NEXT_STATEMENT, CMD_STEP_INTO_MY_CODE
13from _pydevd_bundle.pydevd_constants import STATE_SUSPEND, get_thread_id, STATE_RUN, dict_iter_values, IS_PY3K, \
14    RETURN_VALUES_DICT
15from _pydevd_bundle.pydevd_dont_trace_files import DONT_TRACE, PYDEV_FILE
16from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, just_raised
17from _pydevd_bundle.pydevd_utils import get_clsname_for_code
18from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame
19try:
20    from inspect import CO_GENERATOR
21except:
22    CO_GENERATOR = 0
23
24try:
25    from _pydevd_bundle.pydevd_signature import send_signature_call_trace, send_signature_return_trace
26except ImportError:
27    def send_signature_call_trace(*args, **kwargs):
28        pass
29
30basename = os.path.basename
31
32IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException')
33DEBUG_START = ('pydevd.py', 'run')
34DEBUG_START_PY3K = ('_pydev_execfile.py', 'execfile')
35TRACE_PROPERTY = 'pydevd_traceproperty.py'
36get_file_type = DONT_TRACE.get
37
38
39def handle_breakpoint_condition(py_db, info, breakpoint, new_frame, default_return_value):
40    condition = breakpoint.condition
41    try:
42        val = eval(condition, new_frame.f_globals, new_frame.f_locals)
43        if not val:
44            return default_return_value
45
46    except:
47        if type(condition) != type(''):
48            if hasattr(condition, 'encode'):
49                condition = condition.encode('utf-8')
50
51        msg = 'Error while evaluating expression: %s\n' % (condition,)
52        sys.stderr.write(msg)
53        traceback.print_exc()
54        if not py_db.suspend_on_breakpoint_exception:
55            return default_return_value
56        else:
57            stop = True
58            try:
59                # add exception_type and stacktrace into thread additional info
60                etype, value, tb = sys.exc_info()
61                try:
62                    error = ''.join(traceback.format_exception_only(etype, value))
63                    stack = traceback.extract_stack(f=tb.tb_frame.f_back)
64
65                    # On self.set_suspend(thread, CMD_SET_BREAK) this info will be
66                    # sent to the client.
67                    info.conditional_breakpoint_exception = \
68                        ('Condition:\n' + condition + '\n\nError:\n' + error, stack)
69                finally:
70                    etype, value, tb = None, None, None
71            except:
72                traceback.print_exc()
73
74
75def handle_breakpoint_expression(breakpoint, info, new_frame):
76    try:
77        try:
78            val = eval(breakpoint.expression, new_frame.f_globals, new_frame.f_locals)
79        except:
80            val = sys.exc_info()[1]
81    finally:
82        if val is not None:
83            info.pydev_message = str(val)
84
85
86#=======================================================================================================================
87# PyDBFrame
88#=======================================================================================================================
89# IFDEF CYTHON
90# cdef class PyDBFrame:
91# ELSE
92class PyDBFrame:
93    '''This makes the tracing for a given frame, so, the trace_dispatch
94    is used initially when we enter into a new context ('call') and then
95    is reused for the entire context.
96    '''
97# ENDIF
98
99
100    #Note: class (and not instance) attributes.
101
102    #Same thing in the main debugger but only considering the file contents, while the one in the main debugger
103    #considers the user input (so, the actual result must be a join of both).
104    filename_to_lines_where_exceptions_are_ignored = {}
105    filename_to_stat_info = {}
106
107    # IFDEF CYTHON
108    # cdef tuple _args
109    # cdef int should_skip
110    # def __init__(self, tuple args):
111        # self._args = args # In the cython version we don't need to pass the frame
112        # self.should_skip = -1  # On cythonized version, put in instance.
113    # ELSE
114    should_skip = -1  # Default value in class (put in instance on set).
115
116    def __init__(self, args):
117        #args = main_debugger, filename, base, info, t, frame
118        #yeap, much faster than putting in self and then getting it from self later on
119        self._args = args
120    # ENDIF
121
122    def set_suspend(self, *args, **kwargs):
123        self._args[0].set_suspend(*args, **kwargs)
124
125    def do_wait_suspend(self, *args, **kwargs):
126        self._args[0].do_wait_suspend(*args, **kwargs)
127
128    # IFDEF CYTHON
129    # def trace_exception(self, frame, str event, arg):
130    #     cdef bint flag;
131    # ELSE
132    def trace_exception(self, frame, event, arg):
133    # ENDIF
134        if event == 'exception':
135            flag, frame = self.should_stop_on_exception(frame, event, arg)
136
137            if flag:
138                self.handle_exception(frame, event, arg)
139                return self.trace_dispatch
140
141        return self.trace_exception
142
143    def trace_return(self, frame, event, arg):
144        if event == 'return':
145            main_debugger, filename = self._args[0], self._args[1]
146            send_signature_return_trace(main_debugger, frame, filename, arg)
147        return self.trace_return
148
149    # IFDEF CYTHON
150    # def should_stop_on_exception(self, frame, str event, arg):
151    #     cdef PyDBAdditionalThreadInfo info;
152    #     cdef bint flag;
153    # ELSE
154    def should_stop_on_exception(self, frame, event, arg):
155    # ENDIF
156
157        # main_debugger, _filename, info, _thread = self._args
158        main_debugger = self._args[0]
159        info = self._args[2]
160        flag = False
161
162        # STATE_SUSPEND = 2
163        if info.pydev_state != 2:  #and breakpoint is not None:
164            exception, value, trace = arg
165
166            if trace is not None: #on jython trace is None on the first event
167                exception_breakpoint = get_exception_breakpoint(
168                    exception, main_debugger.break_on_caught_exceptions)
169
170                if exception_breakpoint is not None:
171                    if exception_breakpoint.ignore_libraries:
172                        if exception_breakpoint.notify_on_first_raise_only:
173                            if main_debugger.first_appearance_in_scope(trace):
174                                add_exception_to_frame(frame, (exception, value, trace))
175                                try:
176                                    info.pydev_message = exception_breakpoint.qname
177                                except:
178                                    info.pydev_message = exception_breakpoint.qname.encode('utf-8')
179                                flag = True
180                            else:
181                                pydev_log.debug("Ignore exception %s in library %s" % (exception, frame.f_code.co_filename))
182                                flag = False
183                    else:
184                        if not exception_breakpoint.notify_on_first_raise_only or just_raised(trace):
185                            add_exception_to_frame(frame, (exception, value, trace))
186                            try:
187                                info.pydev_message = exception_breakpoint.qname
188                            except:
189                                info.pydev_message = exception_breakpoint.qname.encode('utf-8')
190                            flag = True
191                        else:
192                            flag = False
193                else:
194                    try:
195                        if main_debugger.plugin is not None:
196                            result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg)
197                            if result:
198                                flag, frame = result
199                    except:
200                        flag = False
201
202        return flag, frame
203
204    def handle_exception(self, frame, event, arg):
205        try:
206            # print 'handle_exception', frame.f_lineno, frame.f_code.co_name
207
208            # We have 3 things in arg: exception type, description, traceback object
209            trace_obj = arg[2]
210            main_debugger = self._args[0]
211
212            if not hasattr(trace_obj, 'tb_next'):
213                return  #Not always there on Jython...
214
215            initial_trace_obj = trace_obj
216            if trace_obj.tb_next is None and trace_obj.tb_frame is frame:
217                #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).
218
219                if main_debugger.break_on_exceptions_thrown_in_same_context:
220                    #Option: Don't break if an exception is caught in the same function from which it is thrown
221                    return
222            else:
223                #Get the trace_obj from where the exception was raised...
224                while trace_obj.tb_next is not None:
225                    trace_obj = trace_obj.tb_next
226
227
228            if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception:
229                for check_trace_obj in (initial_trace_obj, trace_obj):
230                    filename = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame)[1]
231
232
233                    filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored
234
235
236                    lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(filename)
237                    if lines_ignored is None:
238                        lines_ignored = filename_to_lines_where_exceptions_are_ignored[filename] = {}
239
240                    try:
241                        curr_stat = os.stat(filename)
242                        curr_stat = (curr_stat.st_size, curr_stat.st_mtime)
243                    except:
244                        curr_stat = None
245
246                    last_stat = self.filename_to_stat_info.get(filename)
247                    if last_stat != curr_stat:
248                        self.filename_to_stat_info[filename] = curr_stat
249                        lines_ignored.clear()
250                        try:
251                            linecache.checkcache(filename)
252                        except:
253                            #Jython 2.1
254                            linecache.checkcache()
255
256                    from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get(filename)
257                    if from_user_input:
258                        merged = {}
259                        merged.update(lines_ignored)
260                        #Override what we have with the related entries that the user entered
261                        merged.update(from_user_input)
262                    else:
263                        merged = lines_ignored
264
265                    exc_lineno = check_trace_obj.tb_lineno
266
267                    # print ('lines ignored', lines_ignored)
268                    # print ('user input', from_user_input)
269                    # print ('merged', merged, 'curr', exc_lineno)
270
271                    if exc_lineno not in merged:  #Note: check on merged but update lines_ignored.
272                        try:
273                            line = linecache.getline(filename, exc_lineno, check_trace_obj.tb_frame.f_globals)
274                        except:
275                            #Jython 2.1
276                            line = linecache.getline(filename, exc_lineno)
277
278                        if IGNORE_EXCEPTION_TAG.match(line) is not None:
279                            lines_ignored[exc_lineno] = 1
280                            return
281                        else:
282                            #Put in the cache saying not to ignore
283                            lines_ignored[exc_lineno] = 0
284                    else:
285                        #Ok, dict has it already cached, so, let's check it...
286                        if merged.get(exc_lineno, 0):
287                            return
288
289
290            thread = self._args[3]
291
292            try:
293                frame_id_to_frame = {}
294                frame_id_to_frame[id(frame)] = frame
295                f = trace_obj.tb_frame
296                while f is not None:
297                    frame_id_to_frame[id(f)] = f
298                    f = f.f_back
299                f = None
300
301                thread_id = get_thread_id(thread)
302                pydevd_vars.add_additional_frame_by_id(thread_id, frame_id_to_frame)
303                try:
304                    main_debugger.send_caught_exception_stack(thread, arg, id(frame))
305                    self.set_suspend(thread, CMD_STEP_CAUGHT_EXCEPTION)
306                    self.do_wait_suspend(thread, frame, event, arg)
307                    main_debugger.send_caught_exception_stack_proceeded(thread)
308
309                finally:
310                    pydevd_vars.remove_additional_frame_by_id(thread_id)
311            except:
312                traceback.print_exc()
313
314            main_debugger.set_trace_for_frame_and_parents(frame)
315        finally:
316            #Clear some local variables...
317            trace_obj = None
318            initial_trace_obj = None
319            check_trace_obj = None
320            f = None
321            frame_id_to_frame = None
322            main_debugger = None
323            thread = None
324
325    def get_func_name(self, frame):
326        code_obj = frame.f_code
327        func_name = code_obj.co_name
328        try:
329            cls_name = get_clsname_for_code(code_obj, frame)
330            if cls_name is not None:
331                return "%s.%s" % (cls_name, func_name)
332            else:
333                return func_name
334        except:
335            traceback.print_exc()
336            return func_name
337
338    def show_return_values(self, frame, arg):
339        try:
340            try:
341                f_locals_back = getattr(frame.f_back, "f_locals", None)
342                if f_locals_back is not None:
343                    return_values_dict = f_locals_back.get(RETURN_VALUES_DICT, None)
344                    if return_values_dict is None:
345                        return_values_dict = {}
346                        f_locals_back[RETURN_VALUES_DICT] = return_values_dict
347                    name = self.get_func_name(frame)
348                    return_values_dict[name] = arg
349            except:
350                traceback.print_exc()
351        finally:
352            f_locals_back = None
353
354    def remove_return_values(self, main_debugger, frame):
355        try:
356            try:
357                # Showing return values was turned off, we should remove them from locals dict.
358                # The values can be in the current frame or in the back one
359                frame.f_locals.pop(RETURN_VALUES_DICT, None)
360
361                f_locals_back = getattr(frame.f_back, "f_locals", None)
362                if f_locals_back is not None:
363                    f_locals_back.pop(RETURN_VALUES_DICT, None)
364            except:
365                traceback.print_exc()
366        finally:
367            f_locals_back = None
368
369    # IFDEF CYTHON
370    # cpdef trace_dispatch(self, frame, str event, arg):
371    #     cdef str filename;
372    #     cdef bint is_exception_event;
373    #     cdef bint has_exception_breakpoints;
374    #     cdef bint can_skip;
375    #     cdef PyDBAdditionalThreadInfo info;
376    #     cdef int step_cmd;
377    #     cdef int line;
378    #     cdef bint is_line;
379    #     cdef bint is_call;
380    #     cdef bint is_return;
381    #     cdef str curr_func_name;
382    #     cdef bint exist_result;
383    #     cdef dict frame_skips_cache;
384    #     cdef tuple frame_cache_key;
385    #     cdef tuple line_cache_key;
386    #     cdef int breakpoints_in_line_cache;
387    #     cdef int breakpoints_in_frame_cache;
388    #     cdef bint has_breakpoint_in_frame;
389    # ELSE
390    def trace_dispatch(self, frame, event, arg):
391    # ENDIF
392
393        main_debugger, filename, info, thread, frame_skips_cache, frame_cache_key = self._args
394        # print('frame trace_dispatch', frame.f_lineno, frame.f_code.co_name, event, info.pydev_step_cmd)
395        try:
396            info.is_tracing = True
397            line = frame.f_lineno
398            line_cache_key = (frame_cache_key, line)
399
400            if main_debugger._finish_debugging_session:
401                return None
402
403            plugin_manager = main_debugger.plugin
404
405            is_exception_event = event == 'exception'
406            has_exception_breakpoints = main_debugger.break_on_caught_exceptions or main_debugger.has_plugin_exception_breaks
407
408            if is_exception_event:
409                if has_exception_breakpoints:
410                    flag, frame = self.should_stop_on_exception(frame, event, arg)
411                    if flag:
412                        self.handle_exception(frame, event, arg)
413                        return self.trace_dispatch
414                is_line = False
415                is_return = False
416                is_call = False
417            else:
418                is_line = event == 'line'
419                is_return = event == 'return'
420                is_call = event == 'call'
421                if not is_line and not is_return and not is_call:
422                    # I believe this can only happen in jython on some frontiers on jython and java code, which we don't want to trace.
423                    return None
424
425            need_trace_return = False
426            if is_call and main_debugger.signature_factory:
427                need_trace_return = send_signature_call_trace(main_debugger, frame, filename)
428            if is_return and main_debugger.signature_factory:
429                send_signature_return_trace(main_debugger, frame, filename, arg)
430
431            stop_frame = info.pydev_step_stop
432            step_cmd = info.pydev_step_cmd
433
434            if is_exception_event:
435                breakpoints_for_file = None
436                # CMD_STEP_OVER = 108
437                if stop_frame and stop_frame is not frame and step_cmd == 108 and \
438                                arg[0] in (StopIteration, GeneratorExit) and arg[2] is None:
439                    info.pydev_step_cmd = 107  # CMD_STEP_INTO = 107
440                    info.pydev_step_stop = None
441            else:
442                # If we are in single step mode and something causes us to exit the current frame, we need to make sure we break
443                # eventually.  Force the step mode to step into and the step stop frame to None.
444                # I.e.: F6 in the end of a function should stop in the next possible position (instead of forcing the user
445                # to make a step in or step over at that location).
446                # Note: this is especially troublesome when we're skipping code with the
447                # @DontTrace comment.
448                if stop_frame is frame and is_return and step_cmd in (109, 108):  # CMD_STEP_RETURN = 109, CMD_STEP_OVER = 108
449                    if not frame.f_code.co_flags & 0x20:  # CO_GENERATOR = 0x20 (inspect.CO_GENERATOR)
450                        info.pydev_step_cmd = 107  # CMD_STEP_INTO = 107
451                        info.pydev_step_stop = None
452
453                breakpoints_for_file = main_debugger.breakpoints.get(filename)
454
455                can_skip = False
456
457                if info.pydev_state == 1:  # STATE_RUN = 1
458                    #we can skip if:
459                    #- we have no stop marked
460                    #- we should make a step return/step over and we're not in the current frame
461                    # CMD_STEP_RETURN = 109, CMD_STEP_OVER = 108
462                    can_skip = (step_cmd == -1 and stop_frame is None)\
463                        or (step_cmd in (109, 108) and stop_frame is not frame)
464
465                    if can_skip:
466                        if plugin_manager is not None and main_debugger.has_plugin_line_breaks:
467                            can_skip = not plugin_manager.can_not_skip(main_debugger, self, frame)
468
469                        # CMD_STEP_OVER = 108
470                        if can_skip and is_return and main_debugger.show_return_values and info.pydev_step_cmd == 108 and frame.f_back is info.pydev_step_stop:
471                            # trace function for showing return values after step over
472                            can_skip = False
473
474                # Let's check to see if we are in a function that has a breakpoint. If we don't have a breakpoint,
475                # we will return nothing for the next trace
476                # also, after we hit a breakpoint and go to some other debugging state, we have to force the set trace anyway,
477                # so, that's why the additional checks are there.
478                if not breakpoints_for_file:
479                    if can_skip:
480                        if has_exception_breakpoints:
481                            return self.trace_exception
482                        else:
483                            if need_trace_return:
484                                return self.trace_return
485                            else:
486                                return None
487
488                else:
489                    # When cached, 0 means we don't have a breakpoint and 1 means we have.
490                    if can_skip:
491                        breakpoints_in_line_cache = frame_skips_cache.get(line_cache_key, -1)
492                        if breakpoints_in_line_cache == 0:
493                            return self.trace_dispatch
494
495                    breakpoints_in_frame_cache = frame_skips_cache.get(frame_cache_key, -1)
496                    if breakpoints_in_frame_cache != -1:
497                        # Gotten from cache.
498                        has_breakpoint_in_frame = breakpoints_in_frame_cache == 1
499
500                    else:
501                        has_breakpoint_in_frame = False
502                        # Checks the breakpoint to see if there is a context match in some function
503                        curr_func_name = frame.f_code.co_name
504
505                        #global context is set with an empty name
506                        if curr_func_name in ('?', '<module>'):
507                            curr_func_name = ''
508
509                        for breakpoint in dict_iter_values(breakpoints_for_file): #jython does not support itervalues()
510                            #will match either global or some function
511                            if breakpoint.func_name in ('None', curr_func_name):
512                                has_breakpoint_in_frame = True
513                                break
514
515                        # Cache the value (1 or 0 or -1 for default because of cython).
516                        if has_breakpoint_in_frame:
517                            frame_skips_cache[frame_cache_key] = 1
518                        else:
519                            frame_skips_cache[frame_cache_key] = 0
520
521
522                    if can_skip and not has_breakpoint_in_frame:
523                        if has_exception_breakpoints:
524                            return self.trace_exception
525                        else:
526                            if need_trace_return:
527                                return self.trace_return
528                            else:
529                                return None
530
531            #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
532            # print('NOT skipped', frame.f_lineno, frame.f_code.co_name, event)
533
534            try:
535                flag = False
536                #return is not taken into account for breakpoint hit because we'd have a double-hit in this case
537                #(one for the line and the other for the return).
538
539                stop_info = {}
540                breakpoint = None
541                exist_result = False
542                stop = False
543                bp_type = None
544                if not is_return and info.pydev_state != STATE_SUSPEND and breakpoints_for_file is not None and line in breakpoints_for_file:
545                    breakpoint = breakpoints_for_file[line]
546                    new_frame = frame
547                    stop = True
548                    if step_cmd == CMD_STEP_OVER and stop_frame is frame and (is_line or is_return):
549                        stop = False #we don't stop on breakpoint if we have to stop by step-over (it will be processed later)
550                elif plugin_manager is not None and main_debugger.has_plugin_line_breaks:
551                    result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args)
552                    if result:
553                        exist_result = True
554                        flag, breakpoint, new_frame, bp_type = result
555
556                if breakpoint:
557                    #ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint
558                    # lets do the conditional stuff here
559                    if stop or exist_result:
560                        condition = breakpoint.condition
561                        if condition is not None:
562                            result = handle_breakpoint_condition(main_debugger, info, breakpoint, new_frame,
563                                                                 self.trace_dispatch)
564                            if result is not None:
565                                return result
566
567                        if breakpoint.expression is not None:
568                            handle_breakpoint_expression(breakpoint, info, new_frame)
569
570                        if not main_debugger.first_breakpoint_reached:
571                            if is_call:
572                                back = frame.f_back
573                                if back is not None:
574                                    # When we start debug session, we call execfile in pydevd run function. It produces an additional
575                                    # 'call' event for tracing and we stop on the first line of code twice.
576                                    _, back_filename, base = get_abs_path_real_path_and_base_from_frame(back)
577                                    if (base == DEBUG_START[0] and back.f_code.co_name == DEBUG_START[1]) or \
578                                            (base == DEBUG_START_PY3K[0] and back.f_code.co_name == DEBUG_START_PY3K[1]):
579                                        stop = False
580                                        main_debugger.first_breakpoint_reached = True
581                else:
582                    # if the frame is traced after breakpoint stop,
583                    # but the file should be ignored while stepping because of filters
584                    if step_cmd != -1:
585                        if main_debugger.is_filter_enabled and main_debugger.is_ignored_by_filters(filename):
586                            # ignore files matching stepping filters
587                            return self.trace_dispatch
588                        if main_debugger.is_filter_libraries and main_debugger.not_in_scope(filename):
589                            # ignore library files while stepping
590                            return self.trace_dispatch
591
592                if main_debugger.show_return_values:
593                    if is_return and info.pydev_step_cmd == CMD_STEP_OVER and frame.f_back == info.pydev_step_stop:
594                        self.show_return_values(frame, arg)
595
596                elif main_debugger.remove_return_values_flag:
597                    try:
598                        self.remove_return_values(main_debugger, frame)
599                    finally:
600                        main_debugger.remove_return_values_flag = False
601
602                if stop:
603                    self.set_suspend(thread, CMD_SET_BREAK)
604                    if breakpoint and breakpoint.suspend_policy == "ALL":
605                        main_debugger.suspend_all_other_threads(thread)
606                elif flag and plugin_manager is not None:
607                    result = plugin_manager.suspend(main_debugger, thread, frame, bp_type)
608                    if result:
609                        frame = result
610
611                # if thread has a suspend flag, we suspend with a busy wait
612                if info.pydev_state == STATE_SUSPEND:
613                    self.do_wait_suspend(thread, frame, event, arg)
614                    return self.trace_dispatch
615                else:
616                    if not breakpoint and not is_return:
617                        # No stop from anyone and no breakpoint found in line (cache that).
618                        frame_skips_cache[line_cache_key] = 0
619
620            except:
621                traceback.print_exc()
622                raise
623
624            #step handling. We stop when we hit the right frame
625            try:
626                should_skip = 0
627                if pydevd_dont_trace.should_trace_hook is not None:
628                    if self.should_skip == -1:
629                        # I.e.: cache the result on self.should_skip (no need to evaluate the same frame multiple times).
630                        # Note that on a code reload, we won't re-evaluate this because in practice, the frame.f_code
631                        # Which will be handled by this frame is read-only, so, we can cache it safely.
632                        if not pydevd_dont_trace.should_trace_hook(frame, filename):
633                            # -1, 0, 1 to be Cython-friendly
634                            should_skip = self.should_skip = 1
635                        else:
636                            should_skip = self.should_skip = 0
637                    else:
638                        should_skip = self.should_skip
639
640                plugin_stop = False
641                if should_skip:
642                    stop = False
643
644                elif step_cmd == CMD_STEP_INTO:
645                    stop = is_line or is_return
646                    if plugin_manager is not None:
647                        result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop)
648                        if result:
649                            stop, plugin_stop = result
650
651                elif step_cmd == CMD_STEP_INTO_MY_CODE:
652                    if not main_debugger.not_in_scope(frame.f_code.co_filename):
653                        stop = is_line
654
655                elif step_cmd == CMD_STEP_OVER:
656                    stop = stop_frame is frame and (is_line or is_return)
657
658                    if frame.f_code.co_flags & CO_GENERATOR:
659                        if is_return:
660                            stop = False
661
662                    if plugin_manager is not None:
663                        result = plugin_manager.cmd_step_over(main_debugger, frame, event, self._args, stop_info, stop)
664                        if result:
665                            stop, plugin_stop = result
666
667                elif step_cmd == CMD_SMART_STEP_INTO:
668                    stop = False
669                    if info.pydev_smart_step_stop is frame:
670                        info.pydev_func_name = '.invalid.' # Must match the type in cython
671                        info.pydev_smart_step_stop = None
672
673                    if is_line or is_exception_event:
674                        curr_func_name = frame.f_code.co_name
675
676                        #global context is set with an empty name
677                        if curr_func_name in ('?', '<module>') or curr_func_name is None:
678                            curr_func_name = ''
679
680                        if curr_func_name == info.pydev_func_name:
681                            stop = True
682
683                elif step_cmd == CMD_STEP_RETURN:
684                    stop = is_return and stop_frame is frame
685
686                elif step_cmd == CMD_RUN_TO_LINE or step_cmd == CMD_SET_NEXT_STATEMENT:
687                    stop = False
688
689                    if is_line or is_exception_event:
690                        #Yes, we can only act on line events (weird hum?)
691                        #Note: This code is duplicated at pydevd.py
692                        #Acting on exception events after debugger breaks with exception
693                        curr_func_name = frame.f_code.co_name
694
695                        #global context is set with an empty name
696                        if curr_func_name in ('?', '<module>'):
697                            curr_func_name = ''
698
699                        if curr_func_name == info.pydev_func_name:
700                            line = info.pydev_next_line
701                            if frame.f_lineno == line:
702                                stop = True
703                            else:
704                                if frame.f_trace is None:
705                                    frame.f_trace = self.trace_dispatch
706                                frame.f_lineno = line
707                                frame.f_trace = None
708                                stop = True
709
710                else:
711                    stop = False
712
713                if stop and step_cmd != -1 and is_return and IS_PY3K and hasattr(frame, "f_back"):
714                    f_code = getattr(frame.f_back, 'f_code', None)
715                    if f_code is not None:
716                        back_filename = os.path.basename(f_code.co_filename)
717                        file_type = get_file_type(back_filename)
718                        if file_type == PYDEV_FILE:
719                            stop = False
720
721                if plugin_stop:
722                    stopped_on_plugin = plugin_manager.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd)
723                elif stop:
724                    if is_line:
725                        self.set_suspend(thread, step_cmd)
726                        self.do_wait_suspend(thread, frame, event, arg)
727                    else: #return event
728                        back = frame.f_back
729                        if back is not None:
730                            #When we get to the pydevd run function, the debugging has actually finished for the main thread
731                            #(note that it can still go on for other threads, but for this one, we just make it finish)
732                            #So, just setting it to None should be OK
733                            _, back_filename, base = get_abs_path_real_path_and_base_from_frame(back)
734                            if base == DEBUG_START[0] and back.f_code.co_name == DEBUG_START[1]:
735                                back = None
736
737                            elif base == TRACE_PROPERTY:
738                                # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging)
739                                #if we're in a return, we want it to appear to the user in the previous frame!
740                                return None
741
742                            elif pydevd_dont_trace.should_trace_hook is not None:
743                                if not pydevd_dont_trace.should_trace_hook(back, back_filename):
744                                    # In this case, we'll have to skip the previous one because it shouldn't be traced.
745                                    # Also, we have to reset the tracing, because if the parent's parent (or some
746                                    # other parent) has to be traced and it's not currently, we wouldn't stop where
747                                    # we should anymore (so, a step in/over/return may not stop anywhere if no parent is traced).
748                                    # Related test: _debugger_case17a.py
749                                    main_debugger.set_trace_for_frame_and_parents(back, overwrite_prev_trace=True)
750                                    return None
751
752                        if back is not None:
753                            #if we're in a return, we want it to appear to the user in the previous frame!
754                            self.set_suspend(thread, step_cmd)
755                            self.do_wait_suspend(thread, back, event, arg)
756                        else:
757                            #in jython we may not have a back frame
758                            info.pydev_step_stop = None
759                            info.pydev_step_cmd = -1
760                            info.pydev_state = STATE_RUN
761
762            except KeyboardInterrupt:
763                raise
764            except:
765                try:
766                    traceback.print_exc()
767                    info.pydev_step_cmd = -1
768                except:
769                    return None
770
771            #if we are quitting, let's stop the tracing
772            retVal = None
773            if not main_debugger.quitting:
774                retVal = self.trace_dispatch
775
776            return retVal
777        finally:
778            info.is_tracing = False
779
780        #end trace_dispatch
781
782