Esempio n. 1
0
 def __init__(self, socket, pydevd, logfile=None, killonclose=True):
     super(VSCodeMessageProcessor, self).__init__(socket=socket,
                                                  own_socket=False,
                                                  logfile=logfile)
     self.socket = socket
     self.pydevd = pydevd
     self.killonclose = killonclose
     self.is_process_created = False
     self.is_process_created_lock = threading.Lock()
     self.stack_traces = {}
     self.stack_traces_lock = threading.Lock()
     self.active_exceptions = {}
     self.active_exceptions_lock = threading.Lock()
     self.thread_map = IDMap()
     self.frame_map = IDMap()
     self.var_map = IDMap()
     self.bp_map = IDMap()
     self.next_var_ref = 0
     self.loop = futures.EventLoop()
     self.exceptions_mgr = ExceptionsManager(self)
     self.disconnect_request = None
     self.launch_arguments = None
     self.disconnect_request_event = threading.Event()
     pydevd._vscprocessor = self
     self._closed = False
     self.path_casing = PathUnNormcase()
     self.event_loop_thread = threading.Thread(target=self.loop.run_forever,
                                               name='ptvsd.EventLoop')
     self.event_loop_thread.daemon = True
     self.event_loop_thread.start()
Esempio n. 2
0
    def test_path_names_lowercase_disabled(self):
        tool = PathUnNormcase()
        expected = FILENAME.lower()
        result = tool.un_normcase(expected)

        # Since path tool is disabled we should get the same
        # path back
        self.assertEqual(result, expected)
Esempio n. 3
0
class VSCodeMessageProcessor(ipcjson.SocketIO, ipcjson.IpcChannel):
    """IPC JSON message processor for VSC debugger protocol.

    This translates between the VSC debugger protocol and the pydevd
    protocol.
    """
    def __init__(self, socket, pydevd, logfile=None, killonclose=True):
        super(VSCodeMessageProcessor, self).__init__(socket=socket,
                                                     own_socket=False,
                                                     logfile=logfile)
        self.socket = socket
        self.pydevd = pydevd
        self.killonclose = killonclose
        self.is_process_created = False
        self.is_process_created_lock = threading.Lock()
        self.stack_traces = {}
        self.stack_traces_lock = threading.Lock()
        self.active_exceptions = {}
        self.active_exceptions_lock = threading.Lock()
        self.thread_map = IDMap()
        self.frame_map = IDMap()
        self.var_map = IDMap()
        self.bp_map = IDMap()
        self.next_var_ref = 0
        self.loop = futures.EventLoop()
        self.exceptions_mgr = ExceptionsManager(self)
        self.disconnect_request = None
        self.launch_arguments = None
        self.disconnect_request_event = threading.Event()
        pydevd._vscprocessor = self
        self._closed = False
        self.path_casing = PathUnNormcase()
        self.event_loop_thread = threading.Thread(target=self.loop.run_forever,
                                                  name='ptvsd.EventLoop')
        self.event_loop_thread.daemon = True
        self.event_loop_thread.start()

    def close(self):
        """Stop the message processor and release its resources."""
        if self._closed:
            return
        self._closed = True

        pydevd = self.pydevd
        self.pydevd = None
        pydevd.shutdown(socket.SHUT_RDWR)
        pydevd.close()

        global ptvsd_sys_exit_code
        self.send_event('exited', exitCode=ptvsd_sys_exit_code)
        self.send_event('terminated')

        self.disconnect_request_event.wait(WAIT_FOR_DISCONNECT_REQUEST_TIMEOUT)
        if self.disconnect_request is not None:
            self.send_response(self.disconnect_request)
            self.disconnect_request = None

        self.set_exit()
        self.loop.stop()
        self.event_loop_thread.join(WAIT_FOR_THREAD_FINISH_TIMEOUT)

        if self.socket:
            self.socket.shutdown(socket.SHUT_RDWR)
            self.socket.close()

    def pydevd_notify(self, cmd_id, args):
        # TODO: docstring
        try:
            return self.pydevd.pydevd_notify(cmd_id, args)
        except BaseException:
            traceback.print_exc(file=sys.__stderr__)
            raise

    def pydevd_request(self, cmd_id, args):
        # TODO: docstring
        return self.pydevd.pydevd_request(self.loop, cmd_id, args)

    # Instances of this class provide decorators to mark methods as
    # handlers for various # pydevd messages - a decorated method is
    # added to the map with the corresponding message ID, and is
    # looked up there by pydevd event handler below.
    class EventHandlers(dict):
        def handler(self, cmd_id):
            def decorate(f):
                self[cmd_id] = f
                return f

            return decorate

    pydevd_events = EventHandlers()

    def on_pydevd_event(self, cmd_id, seq, args):
        # TODO: docstring
        try:
            f = self.pydevd_events[cmd_id]
        except KeyError:
            raise UnsupportedPyDevdCommandError(cmd_id)
        return f(self, seq, args)

    def async_handler(m):
        # TODO: docstring
        m = futures.wrap_async(m)

        def f(self, *args, **kwargs):
            fut = m(self, self.loop, *args, **kwargs)

            def done(fut):
                try:
                    fut.result()
                except BaseException:
                    traceback.print_exc(file=sys.__stderr__)

            fut.add_done_callback(done)

        return f

    @async_handler
    def on_initialize(self, request, args):
        # TODO: docstring
        cmd = pydevd_comm.CMD_VERSION
        os_id = 'WINDOWS' if platform.system() == 'Windows' else 'UNIX'
        msg = '1.1\t{}\tID'.format(os_id)
        yield self.pydevd_request(cmd, msg)
        self.send_response(
            request,
            supportsExceptionInfoRequest=True,
            supportsConfigurationDoneRequest=True,
            supportsConditionalBreakpoints=True,
            supportsSetVariable=True,
            supportsExceptionOptions=True,
            supportsEvaluateForHovers=True,
            supportsValueFormattingOptions=True,
            exceptionBreakpointFilters=[
                {
                    'filter': 'raised',
                    'label': 'Raised Exceptions',
                    'default': 'false'
                },
                {
                    'filter': 'uncaught',
                    'label': 'Uncaught Exceptions',
                    'default': 'true'
                },
            ],
        )
        self.send_event('initialized')

    @async_handler
    def on_configurationDone(self, request, args):
        # TODO: docstring
        self.send_response(request)
        self.process_launch_arguments()
        self.pydevd_request(pydevd_comm.CMD_RUN, '')

    def process_launch_arguments(self):
        """
        Process the launch arguments to configure the debugger.
        Further information can be found here https://code.visualstudio.com/docs/editor/debugging#_launchjson-attributes
        {
            type:'python',
            request:'launch'|'attach',
            name:'friendly name for debug config',
            // Custom attributes supported by PTVSD.
            redirectOutput:true|false,
        }
        """  # noqa
        if self.launch_arguments is None:
            return

        if self.launch_arguments.get('fixFilePathCase', False):
            self.path_casing.enable()

        if self.launch_arguments.get('redirectOutput', False):
            redirect_output = 'STDOUT\tSTDERR'
        else:
            redirect_output = ''
        self.pydevd_request(pydevd_comm.CMD_REDIRECT_OUTPUT, redirect_output)

    def on_disconnect(self, request, args):
        # TODO: docstring
        if self.start_reason == 'launch':
            self.disconnect_request = request
            self.disconnect_request_event.set()
            killProcess = not self._closed
            self.close()
            if killProcess and self.killonclose:
                os.kill(os.getpid(), signal.SIGTERM)
        else:
            self.send_response(request)

    @async_handler
    def on_attach(self, request, args):
        # TODO: docstring
        self.start_reason = 'attach'
        self.send_response(request)

    @async_handler
    def on_launch(self, request, args):
        # TODO: docstring
        self.start_reason = 'launch'
        self.launch_arguments = request.get('arguments', None)
        self.send_response(request)

    def send_process_event(self, start_method):
        # TODO: docstring
        evt = {
            'name': sys.argv[0],
            'systemProcessId': os.getpid(),
            'isLocalProcess': True,
            'startMethod': start_method,
        }
        self.send_event('process', **evt)

    def is_debugger_internal_thread(self, thread_name):
        if thread_name:
            if thread_name.startswith('pydevd.'):
                return True
            elif thread_name.startswith('ptvsd.'):
                return True
        return False

    @async_handler
    def on_threads(self, request, args):
        # TODO: docstring
        cmd = pydevd_comm.CMD_LIST_THREADS
        _, _, resp_args = yield self.pydevd_request(cmd, '')
        xml = untangle.parse(resp_args).xml
        try:
            xthreads = xml.thread
        except AttributeError:
            xthreads = []

        threads = []
        for xthread in xthreads:
            try:
                name = unquote(xthread['name'])
            except KeyError:
                name = None

            if not self.is_debugger_internal_thread(name):
                pyd_tid = xthread['id']
                try:
                    vsc_tid = self.thread_map.to_vscode(pyd_tid, autogen=False)
                except KeyError:
                    # This is a previously unseen thread
                    vsc_tid = self.thread_map.to_vscode(pyd_tid, autogen=True)
                    self.send_event('thread',
                                    reason='started',
                                    threadId=vsc_tid)

                threads.append({'id': vsc_tid, 'name': name})

        self.send_response(request, threads=threads)

    @async_handler
    def on_stackTrace(self, request, args):
        # TODO: docstring
        vsc_tid = int(args['threadId'])
        startFrame = int(args.get('startFrame', 0))
        levels = int(args.get('levels', 0))

        pyd_tid = self.thread_map.to_pydevd(vsc_tid)
        with self.stack_traces_lock:
            try:
                xframes = self.stack_traces[pyd_tid]
            except KeyError:
                # This means the stack was requested before the
                # thread was suspended
                xframes = []
        totalFrames = len(xframes)

        if levels == 0:
            levels = totalFrames

        stackFrames = []
        for xframe in xframes:
            if startFrame > 0:
                startFrame -= 1
                continue
            if levels <= 0:
                break
            levels -= 1
            key = (pyd_tid, int(xframe['id']))
            fid = self.frame_map.to_vscode(key, autogen=True)
            name = unquote(xframe['name'])
            file = self.path_casing.un_normcase(unquote(xframe['file']))
            line = int(xframe['line'])
            stackFrames.append({
                'id': fid,
                'name': name,
                'source': {
                    'path': file
                },
                'line': line,
                'column': 1,
            })

        self.send_response(request,
                           stackFrames=stackFrames,
                           totalFrames=totalFrames)

    @async_handler
    def on_scopes(self, request, args):
        # TODO: docstring
        vsc_fid = int(args['frameId'])
        pyd_tid, pyd_fid = self.frame_map.to_pydevd(vsc_fid)
        pyd_var = (pyd_tid, pyd_fid, 'FRAME')
        vsc_var = self.var_map.to_vscode(pyd_var, autogen=True)
        scope = {
            'name': 'Locals',
            'expensive': False,
            'variablesReference': vsc_var,
        }
        self.send_response(request, scopes=[scope])

    @async_handler
    def on_variables(self, request, args):
        # TODO: docstring
        vsc_var = int(args['variablesReference'])
        pyd_var = self.var_map.to_pydevd(vsc_var)

        safe_repr_provider.convert_to_hex = args.get('format',
                                                     {}).get('hex', False)

        if len(pyd_var) == 3:
            cmd = pydevd_comm.CMD_GET_FRAME
        else:
            cmd = pydevd_comm.CMD_GET_VARIABLE
        cmdargs = (str(s) for s in pyd_var)
        msg = '\t'.join(cmdargs)
        _, _, resp_args = yield self.pydevd_request(cmd, msg)
        xml = untangle.parse(resp_args).xml
        try:
            xvars = xml.var
        except AttributeError:
            xvars = []

        variables = VariablesSorter()
        for xvar in xvars:
            var_name = unquote(xvar['name'])
            var_type = unquote(xvar['type'])
            var_value = unquote(xvar['value'])
            var = {
                'name': var_name,
                'type': var_type,
                'value': var_value,
            }

            if bool(xvar['isContainer']):
                pyd_child = pyd_var + (var_name, )
                var['variablesReference'] = self.var_map.to_vscode(
                    pyd_child, autogen=True)

            eval_name = self.__get_variable_evaluate_name(pyd_var, var_name)
            if eval_name:
                var['evaluateName'] = eval_name

            variables.append(var)

        # Reset hex format since this is per request.
        safe_repr_provider.convert_to_hex = False
        self.send_response(request, variables=variables.get_sorted_variables())

    def __get_variable_evaluate_name(self, pyd_var_parent, var_name):
        # TODO: docstring
        eval_name = None
        if len(pyd_var_parent) > 3:
            # This means the current variable has a parent i.e, it is not a
            # FRAME variable. These require evaluateName to work in VS
            # watch window
            var = pyd_var_parent + (var_name, )
            eval_name = var[3]
            for s in var[4:]:
                try:
                    # Check and get the dictionary key or list index.
                    # Note: this is best effort, keys that are object references
                    # will not work
                    i = self.__get_index_or_key(s)
                    eval_name += '[{}]'.format(i)
                except:
                    eval_name += '.' + s

        return eval_name

    def __get_index_or_key(self, text):
        # Dictionary resolver in pydevd provides key in '<repr> (<hash>)' format
        result = re.match(r"(.*)\ \(([0-9]*)\)", text,
                          re.IGNORECASE | re.UNICODE)
        if result and len(result.groups()) == 2:
            try:
                # check if group 2 is a hash
                int(result.group(2))
                return result.group(1)
            except:
                pass
        # In the result XML from pydevd list indexes appear
        # as names. If the name is a number then it is a index.
        return int(text)

    @async_handler
    def on_setVariable(self, request, args):
        vsc_var = int(args['variablesReference'])
        pyd_var = self.var_map.to_pydevd(vsc_var)

        var_name = args['name']
        var_value = args['value']

        lhs_expr = self.__get_variable_evaluate_name(pyd_var, var_name)
        if not lhs_expr:
            lhs_expr = var_name
        expr = '%s = %s' % (lhs_expr, var_value)
        # pydevd message format doesn't permit tabs in expressions
        expr = expr.replace('\t', ' ')

        pyd_tid = str(pyd_var[0])
        pyd_fid = str(pyd_var[1])

        safe_repr_provider.convert_to_hex = args.get('format',
                                                     {}).get('hex', False)

        # VSC gives us variablesReference to the parent of the variable
        # being set, and variable name; but pydevd wants the ID
        # (or rather path) of the variable itself.
        pyd_var += (var_name, )
        vsc_var = self.var_map.to_vscode(pyd_var, autogen=True)

        cmd_args = [pyd_tid, pyd_fid, 'LOCAL', expr, '1']
        yield self.pydevd_request(
            pydevd_comm.CMD_EXEC_EXPRESSION,
            '\t'.join(cmd_args),
        )

        cmd_args = [pyd_tid, pyd_fid, 'LOCAL', lhs_expr, '1']
        _, _, resp_args = yield self.pydevd_request(
            pydevd_comm.CMD_EVALUATE_EXPRESSION,
            '\t'.join(cmd_args),
        )

        xml = untangle.parse(resp_args).xml
        xvar = xml.var

        response = {
            'type': unquote(xvar['type']),
            'value': unquote(xvar['value']),
        }
        if bool(xvar['isContainer']):
            response['variablesReference'] = vsc_var

        # Reset hex format since this is per request.
        safe_repr_provider.convert_to_hex = False
        self.send_response(request, **response)

    @async_handler
    def on_evaluate(self, request, args):
        # pydevd message format doesn't permit tabs in expressions
        expr = args['expression'].replace('\t', ' ')

        vsc_fid = int(args['frameId'])
        pyd_tid, pyd_fid = self.frame_map.to_pydevd(vsc_fid)

        safe_repr_provider.convert_to_hex = args.get('format',
                                                     {}).get('hex', False)

        cmd_args = (pyd_tid, pyd_fid, 'LOCAL', expr, '1')
        _, _, resp_args = yield self.pydevd_request(
            pydevd_comm.CMD_EVALUATE_EXPRESSION,
            '\t'.join(str(s) for s in cmd_args))
        xml = untangle.parse(resp_args).xml
        xvar = xml.var

        context = args.get('context', '')
        is_eval_error = xvar['isErrorOnEval']
        if context == 'hover' and is_eval_error == 'True':
            self.send_response(request, result=None, variablesReference=0)
            return

        pyd_var = (pyd_tid, pyd_fid, 'EXPRESSION', expr)
        vsc_var = self.var_map.to_vscode(pyd_var, autogen=True)
        response = {
            'type': unquote(xvar['type']),
            'result': unquote(xvar['value']),
        }
        if bool(xvar['isContainer']):
            response['variablesReference'] = vsc_var

        # Reset hex format since this is per request.
        safe_repr_provider.convert_to_hex = False
        self.send_response(request, **response)

    @async_handler
    def on_pause(self, request, args):
        # TODO: docstring

        # Pause requests cannot be serviced until pydevd is fully initialized.
        with self.is_process_created_lock:
            if not self.is_process_created:
                self.send_response(
                    request,
                    success=False,
                    message='Cannot pause while debugger is initializing',
                )
                return

        vsc_tid = int(args['threadId'])
        if vsc_tid == 0:  # VS does this to mean "stop all threads":
            for pyd_tid in self.thread_map.pydevd_ids():
                self.pydevd_notify(pydevd_comm.CMD_THREAD_SUSPEND, pyd_tid)
        else:
            pyd_tid = self.thread_map.to_pydevd(vsc_tid)
            self.pydevd_notify(pydevd_comm.CMD_THREAD_SUSPEND, pyd_tid)
        self.send_response(request)

    @async_handler
    def on_continue(self, request, args):
        # TODO: docstring
        tid = self.thread_map.to_pydevd(int(args['threadId']))
        self.pydevd_notify(pydevd_comm.CMD_THREAD_RUN, tid)
        self.send_response(request)

    @async_handler
    def on_next(self, request, args):
        # TODO: docstring
        tid = self.thread_map.to_pydevd(int(args['threadId']))
        self.pydevd_notify(pydevd_comm.CMD_STEP_OVER, tid)
        self.send_response(request)

    @async_handler
    def on_stepIn(self, request, args):
        # TODO: docstring
        tid = self.thread_map.to_pydevd(int(args['threadId']))
        self.pydevd_notify(pydevd_comm.CMD_STEP_INTO, tid)
        self.send_response(request)

    @async_handler
    def on_stepOut(self, request, args):
        # TODO: docstring
        tid = self.thread_map.to_pydevd(int(args['threadId']))
        self.pydevd_notify(pydevd_comm.CMD_STEP_RETURN, tid)
        self.send_response(request)

    @async_handler
    def on_setBreakpoints(self, request, args):
        # TODO: docstring
        bps = []
        path = args['source']['path']
        self.path_casing.track_file_path_case(path)
        src_bps = args.get('breakpoints', [])

        # First, we must delete all existing breakpoints in that source.
        cmd = pydevd_comm.CMD_REMOVE_BREAK
        for pyd_bpid, vsc_bpid in self.bp_map.pairs():
            if pyd_bpid[0] == path:
                msg = 'python-line\t{}\t{}'.format(path, vsc_bpid)
                self.pydevd_notify(cmd, msg)
                self.bp_map.remove(pyd_bpid, vsc_bpid)

        cmd = pydevd_comm.CMD_SET_BREAK
        msgfmt = '{}\tpython-line\t{}\t{}\tNone\t{}\tNone'
        for src_bp in src_bps:
            line = src_bp['line']
            vsc_bpid = self.bp_map.add(lambda vsc_bpid: (path, vsc_bpid))
            self.path_casing.track_file_path_case(path)
            msg = msgfmt.format(vsc_bpid, path, line,
                                src_bp.get('condition', None))
            self.pydevd_notify(cmd, msg)
            bps.append({
                'id': vsc_bpid,
                'verified': True,
                'line': line,
            })

        self.send_response(request, breakpoints=bps)

    @async_handler
    def on_setExceptionBreakpoints(self, request, args):
        # TODO: docstring
        filters = args['filters']
        exception_options = args.get('exceptionOptions', [])

        if exception_options:
            self.exceptions_mgr.apply_exception_options(exception_options)
        else:
            self.exceptions_mgr.remove_all_exception_breaks()
            break_raised = 'raised' in filters
            break_uncaught = 'uncaught' in filters
            if break_raised or break_uncaught:
                self.exceptions_mgr.add_exception_break(
                    'BaseException', break_raised, break_uncaught)
        self.send_response(request)

    @async_handler
    def on_exceptionInfo(self, request, args):
        # TODO: docstring
        pyd_tid = self.thread_map.to_pydevd(args['threadId'])
        with self.active_exceptions_lock:
            try:
                exc = self.active_exceptions[pyd_tid]
            except KeyError:
                exc = ExceptionInfo('BaseException',
                                    'exception: no description', None, None)
        self.send_response(
            request,
            exceptionId=exc.name,
            description=exc.description,
            breakMode=self.exceptions_mgr.get_break_mode(exc.name),
            details={
                'typeName': exc.name,
                'message': exc.description,
                'stackTrace': exc.stack,
                'source': exc.source
            },
        )

    @pydevd_events.handler(pydevd_comm.CMD_THREAD_CREATE)
    def on_pydevd_thread_create(self, seq, args):
        # If this is the first thread reported, report process creation
        # as well.
        with self.is_process_created_lock:
            if not self.is_process_created:
                self.is_process_created = True
                self.send_process_event(self.start_reason)

        # TODO: docstring
        xml = untangle.parse(args).xml
        try:
            name = unquote(xml.thread['name'])
        except KeyError:
            name = None
        if not self.is_debugger_internal_thread(name):
            # Any internal pydevd or ptvsd threads will be ignored everywhere
            tid = self.thread_map.to_vscode(xml.thread['id'], autogen=True)
            self.send_event('thread', reason='started', threadId=tid)

    @pydevd_events.handler(pydevd_comm.CMD_THREAD_KILL)
    def on_pydevd_thread_kill(self, seq, args):
        # TODO: docstring
        pyd_tid = args.strip()
        try:
            vsc_tid = self.thread_map.to_vscode(pyd_tid, autogen=False)
        except KeyError:
            pass
        else:
            self.thread_map.remove(pyd_tid, vsc_tid)
            self.send_event('thread', reason='exited', threadId=vsc_tid)

    @pydevd_events.handler(pydevd_comm.CMD_THREAD_SUSPEND)
    @async_handler
    def on_pydevd_thread_suspend(self, seq, args):
        # TODO: docstring
        xml = untangle.parse(args).xml
        pyd_tid = xml.thread['id']
        reason = int(xml.thread['stop_reason'])
        STEP_REASONS = {
            pydevd_comm.CMD_STEP_INTO,
            pydevd_comm.CMD_STEP_OVER,
            pydevd_comm.CMD_STEP_RETURN,
        }
        EXCEPTION_REASONS = {
            pydevd_comm.CMD_STEP_CAUGHT_EXCEPTION,
            pydevd_comm.CMD_ADD_EXCEPTION_BREAK
        }

        try:
            vsc_tid = self.thread_map.to_vscode(pyd_tid, autogen=False)
        except KeyError:
            return

        with self.stack_traces_lock:
            self.stack_traces[pyd_tid] = xml.thread.frame

        description = None
        text = None
        if reason in STEP_REASONS:
            reason = 'step'
        elif reason in EXCEPTION_REASONS:
            reason = 'exception'
        elif reason == pydevd_comm.CMD_SET_BREAK:
            reason = 'breakpoint'
        else:
            reason = 'pause'

        # For exception cases both raise and uncaught, pydevd adds a
        # __exception__ object to the top most frame. Extracting the
        # exception name and description from that frame gives accurate
        # exception information.
        if reason == 'exception':
            # Get exception info from frame
            try:
                xframes = list(xml.thread.frame)
                xframe = xframes[0]
                pyd_fid = xframe['id']
                cmdargs = '{}\t{}\tFRAME\t__exception__'.format(
                    pyd_tid, pyd_fid)
                cmdid = pydevd_comm.CMD_GET_VARIABLE
                _, _, resp_args = yield self.pydevd_request(cmdid, cmdargs)
                xml = untangle.parse(resp_args).xml
                text = unquote(xml.var[1]['type'])
                description = unquote(xml.var[1]['value'])
                frame_data = ((unquote(f['file']), int(f['line']),
                               unquote(f['name']), None) for f in xframes)
                stack = ''.join(traceback.format_list(frame_data))
                source = unquote(xframe['file'])
            except Exception:
                text = 'BaseException'
                description = 'exception: no description'
                stack = None
                source = None

            with self.active_exceptions_lock:
                self.active_exceptions[pyd_tid] = ExceptionInfo(
                    text, description, stack, source)

        self.send_event('stopped',
                        reason=reason,
                        threadId=vsc_tid,
                        text=text,
                        description=description)

    @pydevd_events.handler(pydevd_comm.CMD_THREAD_RUN)
    def on_pydevd_thread_run(self, seq, args):
        # TODO: docstring
        pyd_tid, reason = args.split('\t')
        pyd_tid = pyd_tid.strip()

        # Stack trace, active exception, all frames, and variables for
        # this thread are now invalid; clear their IDs.
        with self.stack_traces_lock:
            try:
                del self.stack_traces[pyd_tid]
            except KeyError:
                pass

        with self.active_exceptions_lock:
            try:
                del self.active_exceptions[pyd_tid]
            except KeyError:
                pass

        for pyd_fid, vsc_fid in self.frame_map.pairs():
            if pyd_fid[0] == pyd_tid:
                self.frame_map.remove(pyd_fid, vsc_fid)

        for pyd_var, vsc_var in self.var_map.pairs():
            if pyd_var[0] == pyd_tid:
                self.var_map.remove(pyd_var, vsc_var)

        try:
            vsc_tid = self.thread_map.to_vscode(pyd_tid, autogen=False)
        except KeyError:
            pass
        else:
            self.send_event('continued', threadId=vsc_tid)

    @pydevd_events.handler(pydevd_comm.CMD_SEND_CURR_EXCEPTION_TRACE)
    def on_pydevd_send_curr_exception_trace(self, seq, args):
        # TODO: docstring
        pass

    @pydevd_events.handler(pydevd_comm.CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED)
    def on_pydevd_send_curr_exception_trace_proceeded(self, seq, args):
        # TODO: docstring
        pyd_tid = args.strip()
        with self.active_exceptions_lock:
            try:
                del self.active_exceptions[pyd_tid]
            except KeyError:
                pass

    @pydevd_events.handler(pydevd_comm.CMD_WRITE_TO_CONSOLE)
    def on_pydevd_cmd_write_to_console2(self, seq, args):
        """Handle console output"""
        xml = untangle.parse(args).xml
        ctx = xml.io['ctx']
        category = 'stdout' if ctx == '1' else 'stderr'
        content = unquote(xml.io['s'])
        self.send_event('output', category=category, output=content)
Esempio n. 4
0
 def test_invalid_path_names(self):
     tool = PathUnNormcase()
     file_path = 'x:/this is an/invalid/file/invalid_file_.csv'
     self.assertEqual(file_path, tool.un_normcase(file_path))
Esempio n. 5
0
 def test_path_names_lowercase_enabled(self):
     tool = PathUnNormcase()
     tool.enable()
     file_path = __file__
     self.assertEqual(file_path, tool.un_normcase(file_path.lower()))
Esempio n. 6
0
 def test_path_names_uppercase_disabled(self):
     tool = PathUnNormcase()
     file_path = __file__
     self.assertNotEqual(file_path, tool.un_normcase(file_path.upper()))
Esempio n. 7
0
 def test_path_names_normcased(self):
     tool = PathUnNormcase()
     tool.enable()
     file_path = __file__
     self.assertEqual(file_path,
                      tool.un_normcase(os.path.normcase(file_path)))
Esempio n. 8
0
 def test_valid_names(self):
     tool = PathUnNormcase()
     file_path = __file__
     self.assertEqual(file_path, tool.un_normcase(file_path))
Esempio n. 9
0
 def test_empty_path_names(self):
     tool = PathUnNormcase()
     file_path = ''
     self.assertEqual(file_path, tool.un_normcase(file_path))
Esempio n. 10
0
    def test_path_names_lowercase_enabled(self):
        tool = PathUnNormcase()
        tool.enable()
        result = tool.un_normcase(FILENAME.lower())

        self.assertEqual(result, ACTUAL)
Esempio n. 11
0
    def test_path_names_normcased(self):
        tool = PathUnNormcase()
        tool.enable()
        result = tool.un_normcase(os.path.normcase(FILENAME))

        self.assertEqual(result, ACTUAL)
Esempio n. 12
0
    def test_valid_names(self):
        tool = PathUnNormcase()
        result = tool.un_normcase(FILENAME)

        self.assertEqual(result, FILENAME)
Esempio n. 13
0
    def test_empty_path_names(self):
        tool = PathUnNormcase()
        file_path = ''
        result = tool.un_normcase(file_path)

        self.assertEqual(result, file_path)