# Important: Autogenerated file.

# DO NOT edit manually!
# DO NOT edit manually!
import sys
from _pydevd_bundle.pydevd_constants import STATE_RUN, PYTHON_SUSPEND, IS_JYTHON, IS_IRONPYTHON
from _pydev_bundle import pydev_log
# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
pydev_log.debug("Using Cython speedups")
# ELSE
# from _pydevd_bundle.pydevd_frame import PyDBFrame
# ENDIF

version = 11

if not hasattr(sys, '_current_frames'):

    # Some versions of Jython don't have it (but we can provide a replacement)
    if IS_JYTHON:
        from java.lang import NoSuchFieldException
        from org.python.core import ThreadStateMapping
        try:
            cachedThreadState = ThreadStateMapping.getDeclaredField('globalThreadStates') # Dev version
        except NoSuchFieldException:
            cachedThreadState = ThreadStateMapping.getDeclaredField('cachedThreadState') # Release Jython 2.7.0
        cachedThreadState.accessible = True
        thread_states = cachedThreadState.get(ThreadStateMapping)

        def _current_frames():
            as_array = thread_states.entrySet().toArray()
            ret = {}
            for thread_to_state in as_array:
                thread = thread_to_state.getKey()
                if thread is None:
                    continue
                thread_state = thread_to_state.getValue()
                if thread_state is None:
                    continue

                frame = thread_state.frame
                if frame is None:
                    continue

                ret[thread.getId()] = frame
            return ret
        
    elif IS_IRONPYTHON: 
        _tid_to_last_frame = {}
        
        # IronPython doesn't have it. Let's use our workaround...
        def _current_frames():
            return _tid_to_last_frame

    else:
        raise RuntimeError('Unable to proceed (sys._current_frames not available in this Python implementation).')
else:
    _current_frames = sys._current_frames

#=======================================================================================================================
# PyDBAdditionalThreadInfo
#=======================================================================================================================
# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
cdef class PyDBAdditionalThreadInfo:
# ELSE
# class PyDBAdditionalThreadInfo(object):
# ENDIF

    # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
    cdef public int pydev_state;
    cdef public object pydev_step_stop; # Actually, it's a frame or None
    cdef public int pydev_step_cmd;
    cdef public bint pydev_notify_kill;
    cdef public object pydev_smart_step_stop; # Actually, it's a frame or None
    cdef public bint pydev_django_resolve_frame;
    cdef public object pydev_call_from_jinja2;
    cdef public object pydev_call_inside_jinja2;
    cdef public bint is_tracing;
    cdef public tuple conditional_breakpoint_exception;
    cdef public str pydev_message;
    cdef public int suspend_type;
    cdef public int pydev_next_line;
    cdef public str pydev_func_name;
    # ELSE
#     __slots__ = [
#         'pydev_state',
#         'pydev_step_stop',
#         'pydev_step_cmd',
#         'pydev_notify_kill',
#         'pydev_smart_step_stop',
#         'pydev_django_resolve_frame',
#         'pydev_call_from_jinja2',
#         'pydev_call_inside_jinja2',
#         'is_tracing',
#         'conditional_breakpoint_exception',
#         'pydev_message',
#         'suspend_type',
#         'pydev_next_line',
#         'pydev_func_name',
#     ]
    # ENDIF

    def __init__(self):
        self.pydev_state = STATE_RUN
        self.pydev_step_stop = None
        self.pydev_step_cmd = -1 # Something as CMD_STEP_INTO, CMD_STEP_OVER, etc.
        self.pydev_notify_kill = False
        self.pydev_smart_step_stop = None
        self.pydev_django_resolve_frame = False
        self.pydev_call_from_jinja2 = None
        self.pydev_call_inside_jinja2 = None
        self.is_tracing = False
        self.conditional_breakpoint_exception = None
        self.pydev_message = ''
        self.suspend_type = PYTHON_SUSPEND
        self.pydev_next_line = -1
        self.pydev_func_name = '.invalid.' # Must match the type in cython


    def iter_frames(self, t):
        #sys._current_frames(): dictionary with thread id -> topmost frame
        current_frames = _current_frames()
        v = current_frames.get(t.ident)
        if v is not None:
            return [v]
        return []

    def __str__(self):
        return 'State:%s Stop:%s Cmd: %s Kill:%s' % (
            self.pydev_state, self.pydev_step_stop, self.pydev_step_cmd, self.pydev_notify_kill)

import linecache
import os.path
import re
import sys
import traceback  # @Reimport

from _pydev_bundle import pydev_log
from _pydevd_bundle import pydevd_dont_trace
from _pydevd_bundle import pydevd_vars
from _pydevd_bundle.pydevd_breakpoints import get_exception_breakpoint
from _pydevd_bundle.pydevd_comm import CMD_STEP_CAUGHT_EXCEPTION, CMD_STEP_RETURN, CMD_STEP_OVER, CMD_SET_BREAK, \
    CMD_STEP_INTO, CMD_SMART_STEP_INTO, CMD_RUN_TO_LINE, CMD_SET_NEXT_STATEMENT, CMD_STEP_INTO_MY_CODE
from _pydevd_bundle.pydevd_constants import STATE_SUSPEND, get_thread_id, STATE_RUN, dict_iter_values, IS_PY3K, \
    dict_keys, RETURN_VALUES_DICT
from _pydevd_bundle.pydevd_dont_trace_files import DONT_TRACE, PYDEV_FILE
from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame, just_raised, remove_exception_from_frame, ignore_exception_trace
from _pydevd_bundle.pydevd_utils import get_clsname_for_code
from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame
try:
    from inspect import CO_GENERATOR
except:
    CO_GENERATOR = 0

try:
    from _pydevd_bundle.pydevd_signature import send_signature_call_trace, send_signature_return_trace
except ImportError:
    def send_signature_call_trace(*args, **kwargs):
        pass

basename = os.path.basename

IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException')
DEBUG_START = ('pydevd.py', 'run')
DEBUG_START_PY3K = ('_pydev_execfile.py', 'execfile')
TRACE_PROPERTY = 'pydevd_traceproperty.py'
get_file_type = DONT_TRACE.get


def file_tracing_filter(path):
    return False


def handle_breakpoint_condition(py_db, info, breakpoint, new_frame):
    condition = breakpoint.condition
    try:
        if breakpoint.handle_hit_condition(new_frame):
            return True

        if condition is None:
            return False

        return eval(condition, new_frame.f_globals, new_frame.f_locals)

    except:
        if type(condition) != type(''):
            if hasattr(condition, 'encode'):
                condition = condition.encode('utf-8')

        msg = 'Error while evaluating expression: %s\n' % (condition,)
        sys.stderr.write(msg)
        traceback.print_exc()
        if not py_db.suspend_on_breakpoint_exception:
            return False
        else:
            try:
                # add exception_type and stacktrace into thread additional info
                etype, value, tb = sys.exc_info()
                try:
                    error = ''.join(traceback.format_exception_only(etype, value))
                    stack = traceback.extract_stack(f=tb.tb_frame.f_back)

                    # On self.set_suspend(thread, CMD_SET_BREAK) this info will be
                    # sent to the client.
                    info.conditional_breakpoint_exception = \
                        ('Condition:\n' + condition + '\n\nError:\n' + error, stack)
                finally:
                    etype, value, tb = None, None, None
            except:
                traceback.print_exc()
            return True


def handle_breakpoint_expression(breakpoint, info, new_frame):
    try:
        try:
            val = eval(breakpoint.expression, new_frame.f_globals, new_frame.f_locals)
        except:
            val = sys.exc_info()[1]
    finally:
        if val is not None:
            info.pydev_message = str(val)


#=======================================================================================================================
# PyDBFrame
#=======================================================================================================================
# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
cdef class PyDBFrame:
# ELSE
# class PyDBFrame:
#     '''This makes the tracing for a given frame, so, the trace_dispatch
#     is used initially when we enter into a new context ('call') and then
#     is reused for the entire context.
#     '''
# ENDIF


    #Note: class (and not instance) attributes.

    #Same thing in the main debugger but only considering the file contents, while the one in the main debugger
    #considers the user input (so, the actual result must be a join of both).
    filename_to_lines_where_exceptions_are_ignored = {}
    filename_to_stat_info = {}

    # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
    cdef tuple _args
    cdef int should_skip
    def __init__(self, tuple args):
        self._args = args # In the cython version we don't need to pass the frame
        self.should_skip = -1  # On cythonized version, put in instance.
    # ELSE
#     should_skip = -1  # Default value in class (put in instance on set).
# 
#     def __init__(self, args):
#         #args = main_debugger, filename, base, info, t, frame
#         #yeap, much faster than putting in self and then getting it from self later on
#         self._args = args
    # ENDIF

    def set_suspend(self, *args, **kwargs):
        self._args[0].set_suspend(*args, **kwargs)

    def do_wait_suspend(self, *args, **kwargs):
        self._args[0].do_wait_suspend(*args, **kwargs)

    # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
    def trace_exception(self, frame, str event, arg):
        cdef bint flag;
    # ELSE
#     def trace_exception(self, frame, event, arg):
    # ENDIF
        if event == 'exception':
            should_stop, frame = self.should_stop_on_exception(frame, event, arg)

            if should_stop:
                self.handle_exception(frame, event, arg)
                return self.trace_dispatch
    
        return self.trace_exception

    def trace_return(self, frame, event, arg):
        if event == 'return':
            main_debugger, filename = self._args[0], self._args[1]
            send_signature_return_trace(main_debugger, frame, filename, arg)
        return self.trace_return

    # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
    def should_stop_on_exception(self, frame, str event, arg):
        cdef PyDBAdditionalThreadInfo info;
        cdef bint flag;
    # ELSE
#     def should_stop_on_exception(self, frame, event, arg):
    # ENDIF

        # main_debugger, _filename, info, _thread = self._args
        main_debugger = self._args[0]
        info = self._args[2]
        should_stop = False

        # STATE_SUSPEND = 2
        if info.pydev_state != 2:  #and breakpoint is not None:
            exception, value, trace = arg

            if trace is not None and hasattr(trace, 'tb_next'): 
                # on jython trace is None on the first event and it may not have a tb_next.

                exception_breakpoint = get_exception_breakpoint(
                    exception, main_debugger.break_on_caught_exceptions)

                if exception_breakpoint is not None:
                    if exception_breakpoint.condition is not None:
                        eval_result = handle_breakpoint_condition(main_debugger, info, exception_breakpoint, frame)
                        if not eval_result:
                            return False, frame

                    if exception_breakpoint.ignore_libraries:
                        if not main_debugger.is_exception_trace_in_project_scope(trace):
                            pydev_log.debug("Ignore exception %s in library %s -- (%s)" % (exception, frame.f_code.co_filename, frame.f_code.co_name))
                            return False, frame
                    
                    if ignore_exception_trace(trace):
                        return False, frame
                    
                    was_just_raised = just_raised(trace)
                    if was_just_raised:
                        add_exception_to_frame(frame, (exception, value, trace))
                    
                    if was_just_raised:
        
                        if main_debugger.break_on_exceptions_thrown_in_same_context:
                            # Option: Don't break if an exception is caught in the same function from which it is thrown
                            return False, frame

                    if exception_breakpoint.notify_on_first_raise_only:
                        if main_debugger.break_on_exceptions_thrown_in_same_context:
                            # In this case we never stop if it was just raised, so, to know if it was the first we
                            # need to check if we're in the 2nd method.
                            if not was_just_raised and not just_raised(trace.tb_next):
                                return False, frame  # I.e.: we stop only when we'r
                                
                        else:
                            if not was_just_raised:
                                return False, frame  # I.e.: we stop only when it was just raised
                            
                    # If it got here we should stop.
                    should_stop = True                    
                    try:
                        info.pydev_message = exception_breakpoint.qname
                    except:
                        info.pydev_message = exception_breakpoint.qname.encode('utf-8')

                else:
                    # No regular exception breakpoint, let's see if some plugin handles it.
                    try:
                        if main_debugger.plugin is not None:
                            result = main_debugger.plugin.exception_break(main_debugger, self, frame, self._args, arg)
                            if result:
                                should_stop, frame = result
                    except:
                        should_stop = False

                if should_stop:
                    if exception_breakpoint is not None and exception_breakpoint.expression is not None:
                        handle_breakpoint_expression(exception_breakpoint, info, frame)

        return should_stop, frame

    def handle_exception(self, frame, event, arg):
        try:
            # print('handle_exception', frame.f_lineno, frame.f_code.co_name)

            # We have 3 things in arg: exception type, description, traceback object
            trace_obj = arg[2]
            main_debugger = self._args[0]

            initial_trace_obj = trace_obj
            if trace_obj.tb_next is None and trace_obj.tb_frame is frame:
                #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).
                pass
            else:
                #Get the trace_obj from where the exception was raised...
                while trace_obj.tb_next is not None:
                    trace_obj = trace_obj.tb_next


            if main_debugger.ignore_exceptions_thrown_in_lines_with_ignore_exception:
                for check_trace_obj in (initial_trace_obj, trace_obj):
                    filename = get_abs_path_real_path_and_base_from_frame(check_trace_obj.tb_frame)[1]


                    filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored


                    lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(filename)
                    if lines_ignored is None:
                        lines_ignored = filename_to_lines_where_exceptions_are_ignored[filename] = {}

                    try:
                        curr_stat = os.stat(filename)
                        curr_stat = (curr_stat.st_size, curr_stat.st_mtime)
                    except:
                        curr_stat = None

                    last_stat = self.filename_to_stat_info.get(filename)
                    if last_stat != curr_stat:
                        self.filename_to_stat_info[filename] = curr_stat
                        lines_ignored.clear()
                        try:
                            linecache.checkcache(filename)
                        except:
                            #Jython 2.1
                            linecache.checkcache()

                    from_user_input = main_debugger.filename_to_lines_where_exceptions_are_ignored.get(filename)
                    if from_user_input:
                        merged = {}
                        merged.update(lines_ignored)
                        #Override what we have with the related entries that the user entered
                        merged.update(from_user_input)
                    else:
                        merged = lines_ignored

                    exc_lineno = check_trace_obj.tb_lineno

                    # print ('lines ignored', lines_ignored)
                    # print ('user input', from_user_input)
                    # print ('merged', merged, 'curr', exc_lineno)

                    if exc_lineno not in merged:  #Note: check on merged but update lines_ignored.
                        try:
                            line = linecache.getline(filename, exc_lineno, check_trace_obj.tb_frame.f_globals)
                        except:
                            #Jython 2.1
                            line = linecache.getline(filename, exc_lineno)

                        if IGNORE_EXCEPTION_TAG.match(line) is not None:
                            lines_ignored[exc_lineno] = 1
                            return
                        else:
                            #Put in the cache saying not to ignore
                            lines_ignored[exc_lineno] = 0
                    else:
                        #Ok, dict has it already cached, so, let's check it...
                        if merged.get(exc_lineno, 0):
                            return


            thread = self._args[3]

            try:
                frame_id_to_frame = {}
                frame_id_to_frame[id(frame)] = frame
                f = trace_obj.tb_frame
                while f is not None:
                    frame_id_to_frame[id(f)] = f
                    f = f.f_back
                f = None

                thread_id = get_thread_id(thread)
                pydevd_vars.add_additional_frame_by_id(thread_id, frame_id_to_frame)
                try:
                    main_debugger.send_caught_exception_stack(thread, arg, id(frame))
                    self.set_suspend(thread, CMD_STEP_CAUGHT_EXCEPTION)
                    self.do_wait_suspend(thread, frame, event, arg)
                    main_debugger.send_caught_exception_stack_proceeded(thread)

                finally:
                    pydevd_vars.remove_additional_frame_by_id(thread_id)
            except:
                traceback.print_exc()

            main_debugger.set_trace_for_frame_and_parents(frame)
        finally:
            #Clear some local variables...
            trace_obj = None
            initial_trace_obj = None
            check_trace_obj = None
            f = None
            frame_id_to_frame = None
            main_debugger = None
            thread = None

    def get_func_name(self, frame):
        code_obj = frame.f_code
        func_name = code_obj.co_name
        try:
            cls_name = get_clsname_for_code(code_obj, frame)
            if cls_name is not None:
                return "%s.%s" % (cls_name, func_name)
            else:
                return func_name
        except:
            traceback.print_exc()
            return func_name

    def show_return_values(self, frame, arg):
        try:
            try:
                f_locals_back = getattr(frame.f_back, "f_locals", None)
                if f_locals_back is not None:
                    return_values_dict = f_locals_back.get(RETURN_VALUES_DICT, None)
                    if return_values_dict is None:
                        return_values_dict = {}
                        f_locals_back[RETURN_VALUES_DICT] = return_values_dict
                    name = self.get_func_name(frame)
                    return_values_dict[name] = arg
            except:
                traceback.print_exc()
        finally:
            f_locals_back = None

    def remove_return_values(self, main_debugger, frame):
        try:
            try:
                # Showing return values was turned off, we should remove them from locals dict.
                # The values can be in the current frame or in the back one
                frame.f_locals.pop(RETURN_VALUES_DICT, None)

                f_locals_back = getattr(frame.f_back, "f_locals", None)
                if f_locals_back is not None:
                    f_locals_back.pop(RETURN_VALUES_DICT, None)
            except:
                traceback.print_exc()
        finally:
            f_locals_back = None

    # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
    cpdef trace_dispatch(self, frame, str event, arg):
        cdef str filename;
        cdef bint is_exception_event;
        cdef bint has_exception_breakpoints;
        cdef bint can_skip;
        cdef PyDBAdditionalThreadInfo info;
        cdef int step_cmd;
        cdef int line;
        cdef bint is_line;
        cdef bint is_call;
        cdef bint is_return;
        cdef str curr_func_name;
        cdef bint exist_result;
        cdef dict frame_skips_cache;
        cdef tuple frame_cache_key;
        cdef tuple line_cache_key;
        cdef int breakpoints_in_line_cache;
        cdef int breakpoints_in_frame_cache;
        cdef bint has_breakpoint_in_frame;
        cdef bint need_trace_return;
    # ELSE
#     def trace_dispatch(self, frame, event, arg):
    # ENDIF

        main_debugger, filename, info, thread, frame_skips_cache, frame_cache_key = self._args
        # print('frame trace_dispatch', frame.f_lineno, frame.f_code.co_name, event, info.pydev_step_cmd)
        try:
            info.is_tracing = True
            line = frame.f_lineno
            line_cache_key = (frame_cache_key, line)

            if main_debugger._finish_debugging_session:
                return None

            plugin_manager = main_debugger.plugin

            is_exception_event = event == 'exception'
            has_exception_breakpoints = main_debugger.break_on_caught_exceptions or main_debugger.has_plugin_exception_breaks

            if is_exception_event:
                if has_exception_breakpoints:
                    should_stop, frame = self.should_stop_on_exception(frame, event, arg)
                    if should_stop:
                        self.handle_exception(frame, event, arg)
                        return self.trace_dispatch
                is_line = False
                is_return = False
                is_call = False
            else:
                is_line = event == 'line'
                is_return = event == 'return'
                is_call = event == 'call'
                if not is_line and not is_return and not is_call:
                    # I believe this can only happen in jython on some frontiers on jython and java code, which we don't want to trace.
                    return None

            need_trace_return = False
            if main_debugger.signature_factory is not None:
                if is_call:
                    need_trace_return = send_signature_call_trace(main_debugger, frame, filename)
                elif is_return:
                    send_signature_return_trace(main_debugger, frame, filename, arg)

            stop_frame = info.pydev_step_stop
            step_cmd = info.pydev_step_cmd

            if is_exception_event:
                breakpoints_for_file = None
                # CMD_STEP_OVER = 108
                if stop_frame and stop_frame is not frame and step_cmd == 108 and \
                                arg[0] in (StopIteration, GeneratorExit) and arg[2] is None:
                    info.pydev_step_cmd = 107  # CMD_STEP_INTO = 107
                    info.pydev_step_stop = None
            else:
                # If we are in single step mode and something causes us to exit the current frame, we need to make sure we break
                # eventually.  Force the step mode to step into and the step stop frame to None.
                # I.e.: F6 in the end of a function should stop in the next possible position (instead of forcing the user
                # to make a step in or step over at that location).
                # Note: this is especially troublesome when we're skipping code with the
                # @DontTrace comment.
                if stop_frame is frame and is_return and step_cmd in (109, 108):  # CMD_STEP_RETURN = 109, CMD_STEP_OVER = 108
                    if not frame.f_code.co_flags & 0x20:  # CO_GENERATOR = 0x20 (inspect.CO_GENERATOR)
                        info.pydev_step_cmd = 107  # CMD_STEP_INTO = 107
                        info.pydev_step_stop = None

                breakpoints_for_file = main_debugger.breakpoints.get(filename)

                can_skip = False

                if info.pydev_state == 1:  # STATE_RUN = 1
                    #we can skip if:
                    #- we have no stop marked
                    #- we should make a step return/step over and we're not in the current frame
                    # CMD_STEP_RETURN = 109, CMD_STEP_OVER = 108
                    can_skip = (step_cmd == -1 and stop_frame is None) \
                        or (step_cmd in (109, 108) and stop_frame is not frame)

                    if can_skip:
                        if plugin_manager is not None and main_debugger.has_plugin_line_breaks:
                            can_skip = not plugin_manager.can_not_skip(main_debugger, self, frame)

                        # CMD_STEP_OVER = 108
                        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:
                            # trace function for showing return values after step over
                            can_skip = False

                # Let's check to see if we are in a function that has a breakpoint. If we don't have a breakpoint,
                # we will return nothing for the next trace
                # also, after we hit a breakpoint and go to some other debugging state, we have to force the set trace anyway,
                # so, that's why the additional checks are there.
                if not breakpoints_for_file:
                    if can_skip:
                        if has_exception_breakpoints:
                            return self.trace_exception
                        else:
                            if need_trace_return:
                                return self.trace_return
                            else:
                                return None

                else:
                    # When cached, 0 means we don't have a breakpoint and 1 means we have.
                    if can_skip:
                        breakpoints_in_line_cache = frame_skips_cache.get(line_cache_key, -1)
                        if breakpoints_in_line_cache == 0:
                            return self.trace_dispatch

                    breakpoints_in_frame_cache = frame_skips_cache.get(frame_cache_key, -1)
                    if breakpoints_in_frame_cache != -1:
                        # Gotten from cache.
                        has_breakpoint_in_frame = breakpoints_in_frame_cache == 1

                    else:
                        has_breakpoint_in_frame = False
                        # Checks the breakpoint to see if there is a context match in some function
                        curr_func_name = frame.f_code.co_name

                        #global context is set with an empty name
                        if curr_func_name in ('?', '<module>'):
                            curr_func_name = ''

                        for breakpoint in dict_iter_values(breakpoints_for_file): #jython does not support itervalues()
                            #will match either global or some function
                            if breakpoint.func_name in ('None', curr_func_name):
                                has_breakpoint_in_frame = True
                                break

                        # Cache the value (1 or 0 or -1 for default because of cython).
                        if has_breakpoint_in_frame:
                            frame_skips_cache[frame_cache_key] = 1
                        else:
                            frame_skips_cache[frame_cache_key] = 0


                    if can_skip and not has_breakpoint_in_frame:
                        if has_exception_breakpoints:
                            return self.trace_exception
                        else:
                            if need_trace_return:
                                return self.trace_return
                            else:
                                return None

            #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
            # print('NOT skipped', frame.f_lineno, frame.f_code.co_name, event)

            try:
                flag = False
                #return is not taken into account for breakpoint hit because we'd have a double-hit in this case
                #(one for the line and the other for the return).

                stop_info = {}
                breakpoint = None
                exist_result = False
                stop = False
                bp_type = None
                if not is_return and info.pydev_state != STATE_SUSPEND and breakpoints_for_file is not None and line in breakpoints_for_file:
                    breakpoint = breakpoints_for_file[line]
                    new_frame = frame
                    stop = True
                    if step_cmd == CMD_STEP_OVER and stop_frame is frame and (is_line or is_return):
                        stop = False #we don't stop on breakpoint if we have to stop by step-over (it will be processed later)
                elif plugin_manager is not None and main_debugger.has_plugin_line_breaks:
                    result = plugin_manager.get_breakpoint(main_debugger, self, frame, event, self._args)
                    if result:
                        exist_result = True
                        flag, breakpoint, new_frame, bp_type = result

                if breakpoint:
                    #ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint
                    # lets do the conditional stuff here
                    if stop or exist_result:
                        if breakpoint.has_condition:
                            eval_result = handle_breakpoint_condition(main_debugger, info, breakpoint, new_frame)
                            if not eval_result:
                                return self.trace_dispatch

                        if breakpoint.expression is not None:
                            handle_breakpoint_expression(breakpoint, info, new_frame)
                            if breakpoint.is_logpoint:
                                return self.trace_dispatch

                        if not main_debugger.first_breakpoint_reached:
                            if is_call:
                                back = frame.f_back
                                if back is not None:
                                    # When we start debug session, we call execfile in pydevd run function. It produces an additional
                                    # 'call' event for tracing and we stop on the first line of code twice.
                                    _, back_filename, base = get_abs_path_real_path_and_base_from_frame(back)
                                    if (base == DEBUG_START[0] and back.f_code.co_name == DEBUG_START[1]) or \
                                            (base == DEBUG_START_PY3K[0] and back.f_code.co_name == DEBUG_START_PY3K[1]):
                                        stop = False
                                        main_debugger.first_breakpoint_reached = True
                else:
                    # if the frame is traced after breakpoint stop,
                    # but the file should be ignored while stepping because of filters
                    if step_cmd != -1:
                        if main_debugger.is_filter_enabled and main_debugger.is_ignored_by_filters(filename):
                            # ignore files matching stepping filters
                            return self.trace_dispatch
                        if main_debugger.is_filter_libraries and not main_debugger.in_project_scope(filename):
                            # ignore library files while stepping
                            return self.trace_dispatch

                if main_debugger.show_return_values:
                    if is_return and info.pydev_step_cmd == CMD_STEP_OVER and frame.f_back == info.pydev_step_stop:
                        self.show_return_values(frame, arg)

                elif main_debugger.remove_return_values_flag:
                    try:
                        self.remove_return_values(main_debugger, frame)
                    finally:
                        main_debugger.remove_return_values_flag = False

                if stop:
                    self.set_suspend(thread, CMD_SET_BREAK)
                    if breakpoint and breakpoint.suspend_policy == "ALL":
                        main_debugger.suspend_all_other_threads(thread)
                elif flag and plugin_manager is not None:
                    result = plugin_manager.suspend(main_debugger, thread, frame, bp_type)
                    if result:
                        frame = result

                # if thread has a suspend flag, we suspend with a busy wait
                if info.pydev_state == STATE_SUSPEND:
                    self.do_wait_suspend(thread, frame, event, arg)
                    return self.trace_dispatch
                else:
                    if not breakpoint and is_line:
                        # No stop from anyone and no breakpoint found in line (cache that).
                        frame_skips_cache[line_cache_key] = 0

            except:
                traceback.print_exc()
                raise

            #step handling. We stop when we hit the right frame
            try:
                should_skip = 0
                if pydevd_dont_trace.should_trace_hook is not None:
                    if self.should_skip == -1:
                        # I.e.: cache the result on self.should_skip (no need to evaluate the same frame multiple times).
                        # Note that on a code reload, we won't re-evaluate this because in practice, the frame.f_code
                        # Which will be handled by this frame is read-only, so, we can cache it safely.
                        if not pydevd_dont_trace.should_trace_hook(frame, filename):
                            # -1, 0, 1 to be Cython-friendly
                            should_skip = self.should_skip = 1
                        else:
                            should_skip = self.should_skip = 0
                    else:
                        should_skip = self.should_skip

                plugin_stop = False
                if should_skip:
                    stop = False

                elif step_cmd == CMD_STEP_INTO:
                    stop = is_line or is_return
                    if plugin_manager is not None:
                        result = plugin_manager.cmd_step_into(main_debugger, frame, event, self._args, stop_info, stop)
                        if result:
                            stop, plugin_stop = result

                elif step_cmd == CMD_STEP_INTO_MY_CODE:
                    if main_debugger.in_project_scope(frame.f_code.co_filename):
                        stop = is_line

                elif step_cmd == CMD_STEP_OVER:
                    stop = stop_frame is frame and (is_line or is_return)

                    if frame.f_code.co_flags & CO_GENERATOR:
                        if is_return:
                            stop = False

                    if plugin_manager is not None:
                        result = plugin_manager.cmd_step_over(main_debugger, frame, event, self._args, stop_info, stop)
                        if result:
                            stop, plugin_stop = result

                elif step_cmd == CMD_SMART_STEP_INTO:
                    stop = False
                    if info.pydev_smart_step_stop is frame:
                        info.pydev_func_name = '.invalid.' # Must match the type in cython
                        info.pydev_smart_step_stop = None

                    if is_line or is_exception_event:
                        curr_func_name = frame.f_code.co_name

                        #global context is set with an empty name
                        if curr_func_name in ('?', '<module>') or curr_func_name is None:
                            curr_func_name = ''

                        if curr_func_name == info.pydev_func_name:
                            stop = True

                elif step_cmd == CMD_STEP_RETURN:
                    stop = is_return and stop_frame is frame

                elif step_cmd == CMD_RUN_TO_LINE or step_cmd == CMD_SET_NEXT_STATEMENT:
                    try:
                        stop, _, response_msg = main_debugger.set_next_statement(frame, event, info.pydev_func_name, info.pydev_next_line)
                    except ValueError:
                        pass

                else:
                    stop = False

                if stop and step_cmd != -1 and is_return and IS_PY3K and hasattr(frame, "f_back"):
                    f_code = getattr(frame.f_back, 'f_code', None)
                    if f_code is not None:
                        back_filename = os.path.basename(f_code.co_filename)
                        file_type = get_file_type(back_filename)
                        if file_type == PYDEV_FILE or file_tracing_filter(f_code.co_filename):
                            stop = False

                if plugin_stop:
                    stopped_on_plugin = plugin_manager.stop(main_debugger, frame, event, self._args, stop_info, arg, step_cmd)
                elif stop:
                    if is_line:
                        self.set_suspend(thread, step_cmd)
                        self.do_wait_suspend(thread, frame, event, arg)
                    else: #return event
                        back = frame.f_back
                        if back is not None:
                            #When we get to the pydevd run function, the debugging has actually finished for the main thread
                            #(note that it can still go on for other threads, but for this one, we just make it finish)
                            #So, just setting it to None should be OK
                            _, back_filename, base = get_abs_path_real_path_and_base_from_frame(back)
                            if base == DEBUG_START[0] and back.f_code.co_name == DEBUG_START[1]:
                                back = None

                            elif base == TRACE_PROPERTY:
                                # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging)
                                #if we're in a return, we want it to appear to the user in the previous frame!
                                return None

                            elif pydevd_dont_trace.should_trace_hook is not None:
                                if not pydevd_dont_trace.should_trace_hook(back, back_filename):
                                    # In this case, we'll have to skip the previous one because it shouldn't be traced.
                                    # Also, we have to reset the tracing, because if the parent's parent (or some
                                    # other parent) has to be traced and it's not currently, we wouldn't stop where
                                    # we should anymore (so, a step in/over/return may not stop anywhere if no parent is traced).
                                    # Related test: _debugger_case17a.py
                                    main_debugger.set_trace_for_frame_and_parents(back, overwrite_prev_trace=True)
                                    return None

                        if back is not None:
                            #if we're in a return, we want it to appear to the user in the previous frame!
                            self.set_suspend(thread, step_cmd)
                            self.do_wait_suspend(thread, back, event, arg)
                        else:
                            #in jython we may not have a back frame
                            info.pydev_step_stop = None
                            info.pydev_step_cmd = -1
                            info.pydev_state = STATE_RUN

            except KeyboardInterrupt:
                raise
            except:
                try:
                    traceback.print_exc()
                    info.pydev_step_cmd = -1
                except:
                    return None

            #if we are quitting, let's stop the tracing
            retVal = None
            if not main_debugger.quitting:
                retVal = self.trace_dispatch

            return retVal
        finally:
            info.is_tracing = False

        #end trace_dispatch
import traceback

from _pydev_bundle.pydev_is_thread_alive import is_thread_alive
from _pydev_imps._pydev_saved_modules import threading
from _pydevd_bundle.pydevd_constants import get_thread_id, IS_IRONPYTHON
from _pydevd_bundle.pydevd_dont_trace_files import DONT_TRACE
from _pydevd_bundle.pydevd_kill_all_pydevd_threads import kill_all_pydev_threads
from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER
from pydevd_tracing import SetTrace
# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
# In Cython, PyDBAdditionalThreadInfo is bundled in the file.
from cpython.object cimport PyObject
from cpython.ref cimport Py_INCREF, Py_XDECREF
# ELSE
# from _pydevd_bundle.pydevd_additional_thread_info import PyDBAdditionalThreadInfo
# from _pydevd_bundle.pydevd_frame import PyDBFrame
# 
# ENDIF

threadingCurrentThread = threading.currentThread
get_file_type = DONT_TRACE.get

# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
# cdef dict global_cache_skips
# cdef dict global_cache_frame_skips
# ELSE
# ENDIF


# Cache where we should keep that we completely skipped entering some context.
# It needs to be invalidated when:
# - Breakpoints are changed
# It can be used when running regularly (without step over/step in/step return)
global_cache_skips = {}
global_cache_frame_skips = {}

def trace_dispatch(py_db, frame, event, arg):
    # Note: this is always the first entry-point in the tracing for any thread.
    # After entering here we'll set a new tracing function for this thread 
    # where more information is cached (and will also setup the tracing for
    # frames where we should deal with unhandled exceptions).
    thread = None
    # Cache the frame which should be traced to deal with unhandled exceptions.
    # (i.e.: thread entry-points).
    from os.path import basename, splitext
    f_unhandled = frame
    only_trace_for_unhandled_exceptions = True
    # print('called at', f_unhandled.f_code.co_name, f_unhandled.f_code.co_filename, f_unhandled.f_code.co_firstlineno)
    while f_unhandled is not None:
        filename = f_unhandled.f_code.co_filename
        name = splitext(basename(filename))[0]
        if name == 'threading':
            if f_unhandled.f_code.co_name in ('__bootstrap', '_bootstrap'):
                # We need __bootstrap_inner, not __bootstrap.
                return py_db.trace_dispatch
            
            elif f_unhandled.f_code.co_name in ('__bootstrap_inner', '_bootstrap_inner'):
                # Note: be careful not to use threading.currentThread to avoid creating a dummy thread.
                t = f_unhandled.f_locals.get('self')
                if t is not None and isinstance(t, threading.Thread):
                    thread = t
                    only_trace_for_unhandled_exceptions = True
                    break
            
        elif name == 'pydevd':
            if f_unhandled.f_code.co_name == '_exec':
                only_trace_for_unhandled_exceptions = True
                break
            
        elif f_unhandled.f_back is None:
            only_trace_for_unhandled_exceptions = False
            break
            
        f_unhandled = f_unhandled.f_back
        
    if thread is None:
        # Important: don't call threadingCurrentThread if we're in the threading module
        # to avoid creating dummy threads.
        thread = threadingCurrentThread()

    if getattr(thread, 'pydev_do_not_trace', None):
        return None

    try:
        additional_info = thread.additional_info
        if additional_info is None:
            raise AttributeError()
    except:
        additional_info = thread.additional_info = PyDBAdditionalThreadInfo()
        
    # print('enter thread tracer', thread, get_thread_id(thread))
    thread_tracer = ThreadTracer((py_db, thread, additional_info, global_cache_skips, global_cache_frame_skips))
    
    if f_unhandled is not None:
        # print(' --> found', f_unhandled.f_code.co_name, f_unhandled.f_code.co_filename, f_unhandled.f_code.co_firstlineno)
        if only_trace_for_unhandled_exceptions:
            f_trace = thread_tracer.trace_unhandled_exceptions
        else:
            f_trace = thread_tracer.trace_dispatch_and_unhandled_exceptions
        # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
        f_unhandled.f_trace = SafeCallWrapper(f_trace)
        # ELSE
#         f_unhandled.f_trace = f_trace
        # ENDIF
        
    if frame is f_unhandled:
        if only_trace_for_unhandled_exceptions:
            return thread_tracer.trace_unhandled_exceptions(frame, event, arg)
        else:
            return thread_tracer.trace_dispatch_and_unhandled_exceptions(frame, event, arg)
    
# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
    thread._tracer = thread_tracer # Hack for cython to keep it alive while the thread is alive (just the method in the SetTrace is not enough).
# ELSE
# ENDIF
    SetTrace(thread_tracer.__call__)
    return thread_tracer.__call__(frame, event, arg)

# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
cdef class PyDbFrameTraceAndUnhandledExceptionsTrace(object):
    cdef object _pydb_frame_trace;
    cdef object _unhandled_trace;
# ELSE
# class PyDbFrameTraceAndUnhandledExceptionsTrace(object):
#     '''
#     A tracer which is meant to be put at entry points to trace PyDBFrames and unhandled
#     exceptions (only really activated when the user started running without debugging
#     and used a settrace later on -- and only in the frame which is the topmost frame as we
#     don't trace threading.py nor inside of pydevd, which are the other frames where
#     we deal with unhandled exceptions).
#     '''
# ENDIF
    def __init__(self, pydb_frame_trace, unhandled_trace):
        self._pydb_frame_trace = pydb_frame_trace
        self._unhandled_trace = unhandled_trace
    
    def trace_dispatch(self, frame, event, arg):
        if event == 'exception' and arg is not None:
            self._unhandled_trace(frame, event, arg)
        else:
            self._pydb_frame_trace(frame, event, arg)
        # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
        return SafeCallWrapper(self.trace_dispatch)
        # ELSE
#         return self.trace_dispatch
        # ENDIF


# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
cdef class SafeCallWrapper:
  cdef method_object
  def __init__(self, method_object):
      self.method_object = method_object
  def  __call__(self, *args):
      #Cannot use 'self' once inside the delegate call since we are borrowing the self reference f_trace field
      #in the frame, and that reference might get destroyed by set trace on frame and parents
      cdef PyObject* method_obj = <PyObject*> self.method_object
      Py_INCREF(<object>method_obj)
      ret = (<object>method_obj)(*args)
      Py_XDECREF (method_obj)
      return SafeCallWrapper(ret) if ret is not None else None
cdef class ThreadTracer:
    cdef public tuple _args;
    def __init__(self, tuple args):
        self._args = args
# ELSE
# class ThreadTracer:
#     def __init__(self, args):
#         self._args = args
# ENDIF

    def trace_unhandled_exceptions(self, frame, event, arg):
        # Note that we ignore the frame as this tracing method should only be put in topmost frames already.
        if event == 'exception' and arg is not None:
            from _pydevd_bundle.pydevd_breakpoints import stop_on_unhandled_exception
            py_db, t, additional_info = self._args[0:3]
            if arg is not None:
                exctype, value, tb = arg
                stop_on_unhandled_exception(py_db, t, additional_info, exctype, value, tb)        
        # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
        return SafeCallWrapper(self.trace_unhandled_exceptions)
        # ELSE
#         return self.trace_unhandled_exceptions
        # ENDIF
    
    def trace_dispatch_and_unhandled_exceptions(self, frame, event, arg):
        if event == 'exception' and arg is not None:
            self.trace_unhandled_exceptions(frame, event, arg)
            ret = self.trace_dispatch_and_unhandled_exceptions
        else:
            pydb_frame_trace = self.__call__(frame, event, arg)
            if pydb_frame_trace is None:
                # If the PyDBFrame did not return a tracer, just go with the simpler
                # tracer for unhandled exceptions. 
                ret = self.trace_unhandled_exceptions
            else:
                # Ok, this frame needs to be traced and needs to deal with unhandled exceptions. Create
                # a class which does this for us.
                py_db_frame_trace_and_unhandled_exceptions_trace = PyDbFrameTraceAndUnhandledExceptionsTrace(
                    self.trace_dispatch_and_unhandled_exceptions, pydb_frame_trace)
                ret = py_db_frame_trace_and_unhandled_exceptions_trace.trace_dispatch
        # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
        return SafeCallWrapper(ret)
        # ELSE
#         return ret
        # ENDIF

    def __call__(self, frame, event, arg):
        ''' This is the callback used when we enter some context in the debugger.

        We also decorate the thread we are in with info about the debugging.
        The attributes added are:
            pydev_state
            pydev_step_stop
            pydev_step_cmd
            pydev_notify_kill

        :param PyDB py_db:
            This is the global debugger (this method should actually be added as a method to it).
        '''
        # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
        cdef str filename;
        cdef str base;
        cdef int pydev_step_cmd;
        cdef tuple frame_cache_key;
        cdef dict cache_skips;
        cdef bint is_stepping;
        cdef tuple abs_path_real_path_and_base;
        cdef PyDBAdditionalThreadInfo additional_info;
        # ENDIF
        # print('ENTER: trace_dispatch', frame.f_code.co_filename, frame.f_lineno, event, frame.f_code.co_name)
        py_db, t, additional_info, cache_skips, frame_skips_cache = self._args
        pydev_step_cmd = additional_info.pydev_step_cmd
        is_stepping = pydev_step_cmd != -1

        try:
            if py_db._finish_debugging_session:
                if not py_db._termination_event_set:
                    # that was not working very well because jython gave some socket errors
                    try:
                        if py_db.output_checker is None:
                            kill_all_pydev_threads()
                    except:
                        traceback.print_exc()
                    py_db._termination_event_set = True
                return None

            # if thread is not alive, cancel trace_dispatch processing
            if not is_thread_alive(t):
                py_db.notify_thread_not_alive(get_thread_id(t))
                return None  # suspend tracing


            if py_db.thread_analyser is not None:
                py_db.thread_analyser.log_event(frame)

            if py_db.asyncio_analyser is not None:
                py_db.asyncio_analyser.log_event(frame)
                
            # Note: it's important that the context name is also given because we may hit something once
            # in the global context and another in the local context.
            frame_cache_key = (frame.f_code.co_firstlineno, frame.f_code.co_name, frame.f_code.co_filename)
            if not is_stepping and frame_cache_key in cache_skips:
                # print('skipped: trace_dispatch (cache hit)', frame_cache_key, frame.f_lineno, event, frame.f_code.co_name)
                return None

            try:
                # Make fast path faster!
                abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename]
            except:
                abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_frame(frame)
                
            filename = abs_path_real_path_and_base[1]
            file_type = get_file_type(abs_path_real_path_and_base[-1]) #we don't want to debug threading or anything related to pydevd

            if file_type is not None:
                if file_type == 1: # inlining LIB_FILE = 1
                    if not py_db.in_project_scope(filename):
                        # print('skipped: trace_dispatch (not in scope)', abs_path_real_path_and_base[-1], frame.f_lineno, event, frame.f_code.co_name, file_type)
                        cache_skips[frame_cache_key] = 1
                        return None
                else:
                    # print('skipped: trace_dispatch', abs_path_real_path_and_base[-1], frame.f_lineno, event, frame.f_code.co_name, file_type)
                    cache_skips[frame_cache_key] = 1
                    return None

            if is_stepping:
                if py_db.is_filter_enabled and py_db.is_ignored_by_filters(filename):
                    # ignore files matching stepping filters
                    return None
                if py_db.is_filter_libraries and not py_db.in_project_scope(filename):
                    # ignore library files while stepping
                    return None

            # print('trace_dispatch', base, frame.f_lineno, event, frame.f_code.co_name, file_type)
            if additional_info.is_tracing:
                return None  # we don't wan't to trace code invoked from pydevd_frame.trace_dispatch

            # Just create PyDBFrame directly (removed support for Python versions < 2.5, which required keeping a weak
            # reference to the frame).
            ret = PyDBFrame(
                (
                    py_db, filename, additional_info, t, frame_skips_cache, frame_cache_key,
                )
            ).trace_dispatch(frame, event, arg)
            if ret is None:
                cache_skips[frame_cache_key] = 1
                return None
            
            # IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
            return SafeCallWrapper(ret)
            # ELSE
#             return ret
            # ENDIF

        except SystemExit:
            return None

        except Exception:
            if py_db._finish_debugging_session:
                return None # Don't log errors when we're shutting down.
            # Log it
            try:
                if traceback is not None:
                    # This can actually happen during the interpreter shutdown in Python 2.7
                    traceback.print_exc()
            except:
                # Error logging? We're really in the interpreter shutdown...
                # (https://github.com/fabioz/PyDev.Debugger/issues/8)
                pass
            return None


if IS_IRONPYTHON:
    # This is far from ideal, as we'll leak frames (we'll always have the last created frame, not really
    # the last topmost frame saved -- this should be Ok for our usage, but it may leak frames and things
    # may live longer... as IronPython is garbage-collected, things should live longer anyways, so, it
    # shouldn't be an issue as big as it's in CPython -- it may still be annoying, but this should
    # be a reasonable workaround until IronPython itself is able to provide that functionality).
    #
    # See: https://github.com/IronLanguages/main/issues/1630
    from _pydevd_bundle.pydevd_additional_thread_info_regular import _tid_to_last_frame
    
    _original_call = ThreadTracer.__call__
    
    def __call__(self, frame, event, arg):
        _tid_to_last_frame[self._args[1].ident] = frame
        return _original_call(self, frame, event, arg)
    
    ThreadTracer.__call__ = __call__
    
