Example #1
0
 def _cmd_get_globals(self, cmd):
     warnings.warn("_cmd_get_globals is deprecated for CPython")
     try:
         return InlineResponse(
             "get_globals",
             module_name=cmd.module_name,
             globals=self.export_globals(cmd.module_name),
         )
     except Exception as e:
         return InlineResponse("get_globals",
                               module_name=cmd.module_name,
                               error=str(e))
Example #2
0
    def _cmd_editor_autocomplete(self, cmd):
        error = None
        try:
            from thonny import jedi_utils

            with warnings.catch_warnings():
                completions = jedi_utils.get_script_completions(
                    cmd.source,
                    cmd.row,
                    cmd.column,
                    cmd.filename,
                    sys_path=self._get_sys_path_for_analysis(),
                )
        except ImportError:
            completions = []
            error = "Could not import jedi"
        except Exception as e:
            completions = []
            logger.info("Autocomplete error", exc_info=e)
            error = "Autocomplete error: " + str(e)

        return InlineResponse(
            "editor_autocomplete",
            source=cmd.source,
            row=cmd.row,
            column=cmd.column,
            filename=cmd.filename,
            completions=completions,
            error=error,
        )
Example #3
0
    def _cmd_get_active_distributions(self, cmd):
        try:
            dists = {}
            for path in self._get_library_paths():
                children = self._get_dir_children_info(path)
                if children is None:
                    continue
                for name, info in children.items():
                    if info["kind"] == "dir":
                        key = name
                    elif name.endswith(".py"):
                        key = name[:-3]
                    elif name.endswith(".mpy"):
                        key = name[:-4]
                    else:
                        continue

                    dists[key] = {
                        "project_name": key,
                        "key": key,
                        "guessed_pypi_name":
                        self._guess_package_pypi_name(key),
                        "location": path,
                        "version": "n/a",
                    }

            return dict(
                distributions=dists,
                usersitepackages=None,
            )
        except Exception:
            return InlineResponse("get_active_distributions",
                                  error=traceback.format_exc())
Example #4
0
    def _cmd_shell_autocomplete(self, cmd):
        error = None
        try:
            from thonny import jedi_utils
        except ImportError:
            completions = []
            error = "Could not import jedi"
        else:
            import __main__

            try:
                with warnings.catch_warnings():
                    completions = jedi_utils.get_interpreter_completions(
                        cmd.source, [__main__.__dict__],
                        sys_path=self._get_sys_path_for_analysis())
            except Exception as e:
                completions = []
                logger.info("Autocomplete error", exc_info=e)
                error = "Autocomplete error: " + str(e)

        return InlineResponse(
            "shell_autocomplete",
            source=cmd.source,
            completions=completions,
            error=error,
            row=cmd.row,
            column=cmd.column,
        )
Example #5
0
        def create_error_response(**kw):
            if "error" not in kw:
                kw["error"] = traceback.format_exc()

            if isinstance(cmd, ToplevelCommand):
                return ToplevelResponse(command_name=cmd.name, **kw)
            else:
                return InlineResponse(command_name=cmd.name, **kw)
Example #6
0
    def _cmd_get_locals(self, cmd):
        for frame in inspect.stack():
            if id(frame) == cmd.frame_id:
                return InlineResponse("get_locals",
                                      locals=self.export_variables(
                                          frame.f_locals))

        raise RuntimeError("Frame '{0}' not found".format(cmd.frame_id))
Example #7
0
    def _cmd_get_completion_details(self, cmd):
        # it is assumed this gets called after requesting editor or shell completions
        from thonny import jedi_utils

        return InlineResponse(
            "get_completion_details",
            full_name=cmd.full_name,
            details=jedi_utils.get_completion_details(cmd.full_name),
        )
Example #8
0
    def _cmd_shell_autocomplete(self, cmd):
        # TODO:
        completions = []
        error = "Could not import jedi"

        return InlineResponse("shell_autocomplete",
                              source=cmd.source,
                              completions=completions,
                              error=error)
Example #9
0
    def _cmd_write_file(self, cmd):
        def generate_blocks(content_bytes, block_size):
            for i in range(0, len(content_bytes), block_size):
                yield content_bytes[i : i + block_size]

        self._write_file(generate_blocks(cmd["content_bytes"], BUFFER_SIZE), cmd["path"])

        return InlineResponse(
            command_name="write_file", path=cmd["path"], editor_id=cmd.get("editor_id")
        )
Example #10
0
    def _cmd_write_file(self, cmd):
        mount_name = self._get_fs_mount_name()
        if mount_name is not None:
            # CircuitPython devices only allow writing via mount,
            # other mounted devices may show outdated data in mount
            # when written via serial.
            self._write_file_via_mount(cmd)
        else:
            self._write_file_via_serial(cmd)

        return InlineResponse(command_name="write_file",
                              path=cmd["path"],
                              editor_id=cmd.get("editor_id"))
Example #11
0
    def _cmd_get_shell_calltip(self, cmd):
        from thonny import jedi_utils
        import __main__

        signatures = jedi_utils.get_interpreter_signatures(
            cmd.source, [__main__.__dict__],
            sys_path=self._get_sys_path_for_analysis())
        return InlineResponse(
            "get_shell_calltip",
            source=cmd.source,
            row=cmd.row,
            column=cmd.column,
            filename=cmd.filename,
            signatures=signatures,
        )
Example #12
0
    def handle_command(self, cmd):
        assert isinstance(cmd, (ToplevelCommand, InlineCommand))

        def create_error_response(**kw):
            if isinstance(cmd, ToplevelCommand):
                return ToplevelResponse(command_name=cmd.name, **kw)
            else:
                return InlineResponse(command_name=cmd.name, **kw)

        handler = getattr(self, "_cmd_" + cmd.name, None)

        if handler is None:
            response = create_error_response(error="Unknown command: " +
                                             cmd.name)
        else:
            try:
                response = handler(cmd)
            except SystemExit:
                # Must be caused by Thonny or plugins code
                if isinstance(cmd, ToplevelCommand):
                    traceback.print_exc()
                response = create_error_response(SystemExit=True)
            except UserError as e:
                sys.stderr.write(str(e) + "\n")
                response = create_error_response()
            except KeyboardInterrupt:
                response = create_error_response(
                    user_exception=self._prepare_user_exception())
            except Exception:
                _report_internal_error()
                response = create_error_response(
                    context_info="other unhandled exception")

        if response is False:
            # Command doesn't want to send any response
            return

        elif isinstance(response, dict):
            if isinstance(cmd, ToplevelCommand):
                response = ToplevelResponse(command_name=cmd.name, **response)
            elif isinstance(cmd, InlineCommand):
                response = InlineResponse(cmd.name, **response)

        debug("cmd: " + str(cmd) + ", respin: " + str(response))
        self.send_message(response)
Example #13
0
    def _cmd_write_file(self, cmd):
        def callback(completed, total):
            self._report_progress(cmd, cmd["path"], completed, total)

        try:
            with io.BytesIO() as fp:
                fp.write(cmd["content_bytes"])
                fp.seek(0)
                self._write_file(fp, cmd["path"], len(cmd["content_bytes"]), callback)

            error = None
        except Exception as e:
            self._report_internal_exception()
            error = str(e)

        return InlineResponse(
            command_name="write_file", path=cmd["path"], editor_id=cmd.get("editor_id"), error=error
        )
Example #14
0
    def _cmd_get_editor_calltip(self, cmd):
        from thonny import jedi_utils

        signatures = jedi_utils.get_script_signatures(
            cmd.source,
            cmd.row,
            cmd.column,
            cmd.filename,
            sys_path=self._get_sys_path_for_analysis(),
        )
        return InlineResponse(
            "get_editor_calltip",
            source=cmd.source,
            row=cmd.row,
            column=cmd.column,
            filename=cmd.filename,
            signatures=signatures,
        )
Example #15
0
    def _prepare_command_response(
            self, response: Union[MessageFromBackend, Dict, None],
            command: CommandToBackend) -> MessageFromBackend:
        if "id" in command and "command_id" not in response:
            response["command_id"] = command["id"]

        if isinstance(response, MessageFromBackend):
            return response
        else:
            if isinstance(response, dict):
                args = response
            else:
                args = {}

            if isinstance(command, ToplevelCommand):
                return ToplevelResponse(command_name=command.name, **args)
            else:
                assert isinstance(command, InlineCommand)
                return InlineResponse(command_name=command.name, **args)
Example #16
0
    def handle_command(self, cmd):
        self._report_time("before " + cmd.name)
        assert isinstance(cmd, (ToplevelCommand, InlineCommand))

        if "local_cwd" in cmd:
            self._local_cwd = cmd["local_cwd"]

        def create_error_response(**kw):
            if "error" not in kw:
                kw["error"] = traceback.format_exc()

            if isinstance(cmd, ToplevelCommand):
                return ToplevelResponse(command_name=cmd.name, **kw)
            else:
                return InlineResponse(command_name=cmd.name, **kw)

        handler = getattr(self, "_cmd_" + cmd.name, None)

        if handler is None:
            response = create_error_response(error="Unknown command: " +
                                             cmd.name)
        else:
            try:
                response = handler(cmd)
            except SystemExit:
                # Must be caused by Thonny or plugins code
                if isinstance(cmd, ToplevelCommand):
                    traceback.print_exc()
                response = create_error_response(SystemExit=True)
            except UserError as e:
                sys.stderr.write(str(e) + "\n")
                response = create_error_response()
            except KeyboardInterrupt:
                response = create_error_response(error="Interrupted",
                                                 interrupted=True)
            except ProtocolError as e:
                self._send_output(
                    "THONNY FAILED TO EXECUTE %s (%s)\n" %
                    (cmd.name, e.message), "stderr")
                self._send_output("CAPTURED DATA: %r\n" % e.captured, "stderr")
                self._send_output("TRYING TO RECOVER ...\n", "stderr")
                # TODO: detect when there is no output for long time and suggest interrupt
                self._forward_output_until_active_prompt("stdout")
                response = create_error_response(error=e.message)
            except Exception:
                _report_internal_error()
                response = create_error_response(
                    context_info="other unhandled exception")

        if response is None:
            response = {}

        if response is False:
            # Command doesn't want to send any response
            return

        elif isinstance(response, dict):
            if isinstance(cmd, ToplevelCommand):
                response = ToplevelResponse(command_name=cmd.name, **response)
            elif isinstance(cmd, InlineCommand):
                response = InlineResponse(cmd.name, **response)

        if "id" in cmd and "command_id" not in response:
            response["command_id"] = cmd["id"]

        debug("cmd: " + str(cmd) + ", respin: " + str(response))
        self.send_message(response)

        self._report_time("after " + cmd.name)
Example #17
0
    def _handle_normal_command(self, cmd: CommandToBackend) -> None:

        self._report_time("before " + cmd.name)
        assert isinstance(cmd, (ToplevelCommand, InlineCommand))

        if "local_cwd" in cmd:
            self._local_cwd = cmd["local_cwd"]

        def create_error_response(**kw):
            if "error" not in kw:
                kw["error"] = traceback.format_exc()

            if isinstance(cmd, ToplevelCommand):
                return ToplevelResponse(command_name=cmd.name, **kw)
            else:
                return InlineResponse(command_name=cmd.name, **kw)

        handler = getattr(self, "_cmd_" + cmd.name, None)

        if handler is None:
            response = create_error_response(error="Unknown command: " +
                                             cmd.name)
        else:
            try:
                response = handler(cmd)
            except SystemExit:
                # Must be caused by Thonny or plugins code
                if isinstance(cmd, ToplevelCommand):
                    traceback.print_exc()
                response = create_error_response(SystemExit=True)
            except UserError as e:
                sys.stderr.write(str(e) + "\n")
                response = create_error_response()
            except KeyboardInterrupt:
                response = create_error_response(error="Interrupted",
                                                 interrupted=True)
            except ConnectionClosedException as e:
                self._on_connection_closed(e)
            except ManagementError as e:
                if "KeyboardInterrupt" in e.err:
                    response = create_error_response(error="Interrupted",
                                                     interrupted=True)
                else:
                    self._send_output(
                        "THONNY FAILED TO EXECUTE COMMAND %s\n" % cmd.name,
                        "stderr")
                    # traceback.print_exc() # I'll know the trace from command
                    self._show_error("\n")
                    self._show_error("SCRIPT:\n" + e.script + "\n")
                    self._show_error("STDOUT:\n" + e.out + "\n")
                    self._show_error("STDERR:\n" + e.err + "\n")

                    response = create_error_response(error="ManagementError")
            except Exception:
                _report_internal_error()
                response = create_error_response(
                    context_info="other unhandled exception")

        if response is None:
            response = {}

        if response is False:
            # Command doesn't want to send any response
            return

        elif isinstance(response, dict):
            if isinstance(cmd, ToplevelCommand):
                response = ToplevelResponse(command_name=cmd.name, **response)
            elif isinstance(cmd, InlineCommand):
                response = InlineResponse(cmd.name, **response)

        debug("cmd: " + str(cmd) + ", respin: " + str(response))
        self.send_message(self._prepare_command_response(response, cmd))

        self._check_perform_just_in_case_gc()

        self._report_time("after " + cmd.name)
Example #18
0
 def create_error_response(**kw):
     if isinstance(cmd, ToplevelCommand):
         return ToplevelResponse(command_name=cmd.name, **kw)
     else:
         return InlineResponse(command_name=cmd.name, **kw)
Example #19
0
    def _cmd_get_heap(self, cmd):
        result = {}
        for key in self._heap:
            result[key] = self.export_value(self._heap[key])

        return InlineResponse("get_heap", heap=result)
Example #20
0
    def _cmd_get_object_info(self, cmd):
        if isinstance(self._current_executor,
                      NiceTracer) and self._current_executor.is_in_past():
            info = {"id": cmd.object_id, "error": "past info not available"}

        elif cmd.object_id in self._heap:
            value = self._heap[cmd.object_id]
            attributes = {}
            if cmd.include_attributes:
                for name in dir(value):
                    if not name.startswith("__") or cmd.all_attributes:
                        # attributes[name] = inspect.getattr_static(value, name)
                        try:
                            attributes[name] = getattr(value, name)
                        except Exception:
                            pass

            self._heap[id(type(value))] = type(value)
            info = {
                "id":
                cmd.object_id,
                "repr":
                repr(value),
                "type":
                str(type(value)),
                "full_type_name":
                str(type(value)).replace("<class '", "").replace("'>",
                                                                 "").strip(),
                "type_id":
                id(type(value)),
                "attributes":
                self.export_variables(attributes),
            }

            if isinstance(value, io.TextIOWrapper):
                self._add_file_handler_info(value, info)
            elif isinstance(
                    value,
                (
                    types.BuiltinFunctionType,
                    types.BuiltinMethodType,
                    types.FunctionType,
                    types.LambdaType,
                    types.MethodType,
                ),
            ):
                self._add_function_info(value, info)
            elif isinstance(value, (list, tuple, set)):
                self._add_elements_info(value, info)
            elif isinstance(value, dict):
                self._add_entries_info(value, info)
            elif hasattr(value, "image_data"):
                info["image_data"] = value.image_data

            for tweaker in self._object_info_tweakers:
                try:
                    tweaker(value, info, cmd)
                except Exception:
                    logger.exception("Failed object info tweaker: " +
                                     str(tweaker))

        else:
            info = {"id": cmd.object_id, "error": "object info not available"}

        return InlineResponse("get_object_info", id=cmd.object_id, info=info)