def _create_widgets(self, parent):
        bg = "#ffff99"
        banner = tk.Label(parent, background=bg)
        banner.grid(row=0, column=0, sticky="nsew")

        banner_msg = (_(
            "This dialog is for managing Thonny plug-ins and their dependencies.\n"
            +
            "If you want to install packages for your own programs then choose 'Tools → Manage packages...'"
        ) + "\n")

        runner = get_runner()
        if (runner is not None and runner.get_local_executable() is not None
                and is_same_path(self._get_interpreter(),
                                 get_runner().get_local_executable())):
            banner_msg += (_(
                "(In this case Thonny's back-end uses same interpreter, so both dialogs manage same packages.)"
            ) + "\n")

        banner_msg += "\n" + _(
            "NB! You need to restart Thonny after installing / upgrading / uninstalling a plug-in."
        )

        banner_text = tk.Label(banner,
                               text=banner_msg,
                               background=bg,
                               justify="left")
        banner_text.grid(pady=10, padx=10)

        PipDialog._create_widgets(self, parent)
Beispiel #2
0
    def write_remote_file(self, save_filename, content_bytes, save_copy):
        if get_runner().ready_for_remote_file_operations(show_message=True):
            target_filename = extract_target_path(save_filename)

            get_runner().send_command(
                InlineCommand(
                    "write_file",
                    path=target_filename,
                    content_bytes=content_bytes,
                    editor_id=id(self),
                    blocking=True,
                    description=_("Saving") + "...",
                ))

            if not save_copy:
                self._code_view.text.edit_modified(False)

            self.update_title()

            # NB! edit_modified is not falsed yet!
            get_workbench().event_generate("RemoteFileOperation",
                                           path=target_filename,
                                           operation="save")
            return True
        else:
            return False
Beispiel #3
0
    def check_issue_command(self, command, **kwargs):
        cmd = DebuggerCommand(command, **kwargs)
        self._last_debugger_command = cmd

        if get_runner().is_waiting_debugger_command():
            logging.debug("_check_issue_debugger_command: %s", cmd)

            # tell VM the state we are seeing
            cmd.setdefault(
                frame_id=self._last_progress_message.stack[-1].id,
                breakpoints=self.get_effective_breakpoints(command),
                state=self._last_progress_message.stack[-1].event,
                focus=self._last_progress_message.stack[-1].focus,
                allow_stepping_into_libraries=get_workbench().get_option(
                    "debugger.allow_stepping_into_libraries"),
            )
            if command == "run_to_cursor":
                # cursor position was added as another breakpoint
                cmd.name = "resume"

            get_runner().send_command(cmd)
            if command == "resume":
                self.clear_last_frame()
        else:
            logging.debug("Bad state for sending debugger command " +
                          str(command))
Beispiel #4
0
def check_upload_download_response(command_name, command_response):
    if command_response and command_response.get("existing_files"):
        # command was not performed because overwriting existing files need confirmation
        existing = sorted(command_response["existing_files"][:25])
        if len(command_response["existing_files"]) > 25:
            existing.append("...")

        user_response = messagebox.askokcancel(
            "Overwriting",
            "Some file(s) will be overwritten:\n\n" + "   " + "\n   ".join(existing),
            icon="info",
        )
        if not user_response:
            return

        else:
            get_runner().send_command(
                InlineCommand(
                    command_name,
                    allow_overwrite=True,
                    source_paths=command_response["source_paths"],
                    target_dir=command_response["target_dir"],
                    blocking=True,
                    description=command_response["description"],
                )
            )
Beispiel #5
0
def _request_debug(command_name):
    # Don't assume Debug command gets issued after this
    # This may just call the %cd command
    # or the user may deny saving current editor
    if get_workbench().in_simple_mode():
        get_workbench().show_view("VariablesView")

    get_runner().execute_current(command_name)
    def _start_update_list(self, name_to_show=None):
        assert self._get_state() in [None, "idle"]
        self._set_state("listing")

        get_workbench().bind("get_active_distributions_response",
                             self._complete_update_list, True)
        self._last_name_to_show = name_to_show
        get_runner().send_command(InlineCommand("get_active_distributions"))
Beispiel #7
0
 def handle_frame_click(event,
                        frame_id=frame_id,
                        filename=filename,
                        lineno=lineno):
     get_runner().send_command(
         InlineCommand("get_frame_info", frame_id=frame_id))
     if os.path.exists(filename):
         get_workbench().get_editor_notebook().show_file(
             filename, lineno, set_focus=False)
def choose_node_for_file_operations(master, prompt):
    if get_runner().supports_remote_files():
        dlg = NodeChoiceDialog(master, prompt)
        show_dialog(dlg, master)
        if dlg.result == "remote" and not get_runner().ready_for_remote_file_operations(
            show_message=True
        ):
            return None
        return dlg.result
    else:
        return "local"
Beispiel #9
0
 def handle_autocomplete_request(self):
     row, column = self._get_position()
     source = self.text.get("1.0", "end-1c")
     get_runner().send_command(
         InlineCommand(
             "editor_autocomplete",
             source=source,
             row=row,
             column=column,
             filename=self._get_filename(),
         ))
    def __init__(self, master, kind, initial_dir):
        super().__init__(master=master)
        self.result = None

        self.updating_selection = False

        self.kind = kind
        if kind == "open":
            self.title("Open from " + get_runner().get_node_label())
        else:
            assert kind == "save"
            self.title("Save to " + get_runner().get_node_label())

        background = ttk.Frame(self)
        background.grid(row=0, column=0, sticky="nsew")
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        self.browser = DialogRemoteFileBrowser(background, self)
        self.browser.grid(row=0, column=0, columnspan=4, sticky="nsew", pady=20, padx=20)
        self.browser.configure(borderwidth=1, relief="groove")
        self.browser.tree.configure(selectmode="browse")

        self.name_label = ttk.Label(background, text="File name:")
        self.name_label.grid(row=1, column=0, pady=(0, 20), padx=20, sticky="w")

        self.name_var = create_string_var("")
        self.name_entry = ttk.Entry(
            background, textvariable=self.name_var, state="normal" if kind == "save" else "disabled"
        )
        self.name_entry.grid(row=1, column=1, pady=(0, 20), padx=(0, 20), sticky="we")
        self.name_entry.bind("<KeyRelease>", self.on_name_edit, True)

        self.ok_button = ttk.Button(background, text="OK", command=self.on_ok)
        self.ok_button.grid(row=1, column=2, pady=(0, 20), padx=(0, 20), sticky="e")

        self.cancel_button = ttk.Button(background, text="Cancel", command=self.on_cancel)
        self.cancel_button.grid(row=1, column=3, pady=(0, 20), padx=(0, 20), sticky="e")

        background.rowconfigure(0, weight=1)
        background.columnconfigure(1, weight=1)

        self.bind("<Escape>", self.on_cancel, True)
        self.bind("<Return>", self.on_ok, True)
        self.protocol("WM_DELETE_WINDOW", self.on_cancel)

        self.tree_select_handler_id = self.browser.tree.bind(
            "<<TreeviewSelect>>", self.on_tree_select, True
        )

        self.browser.request_focus_into(initial_dir)
    def request_focus_into(self, path):
        if not get_runner().ready_for_remote_file_operations(show_message=True):
            return False

        super().request_focus_into(path)

        if not get_runner().supports_remote_directories():
            assert path == ""
            self.focus_into(path)
        elif self.current_focus == path:
            # refreshes
            self.focus_into(path)
        else:
            self.request_new_focus(path)
Beispiel #12
0
        def upload():
            selection = self.get_selection_info(True)
            if not selection:
                return

            if "dir" in selection["kinds"] and not proxy.supports_remote_directories():
                messagebox.showerror(
                    "Can't upload directory",
                    "%s does not support directories.\n" % proxy.get_node_label()
                    + "You can only upload files.",
                )
            else:
                response = get_runner().send_command(
                    InlineCommand(
                        "upload",
                        allow_overwrite=False,
                        source_paths=selection["paths"],
                        target_dir=target_dir,
                        blocking=True,
                        description=_("Uploading %s to %s")
                        % (selection["description"], target_dir),
                    )
                )
                check_upload_download_response("upload", response)
                self.master.remote_files.refresh_tree()
 def supports_directories(self):
     runner = get_runner()
     if not runner:
         return False
     proxy = runner.get_backend_proxy()
     if not proxy:
         return False
     return proxy.supports_remote_directories()
Beispiel #14
0
    def apply(self):
        if self._current_page is None:
            return None

        result = self._current_page.apply()

        if result is False:
            return False

        backend_desc = self._combo_variable.get()
        backend_name = self._backend_specs_by_desc[backend_desc].name
        get_workbench().set_option("run.backend_name", backend_name)

        if getattr(self._combo_variable,
                   "modified") or self._current_page.should_restart():
            get_runner().restart_backend(False)

        return None
def ask_backend_path(master, dialog_kind):
    proxy = get_runner().get_backend_proxy()
    if not proxy:
        return None

    assert proxy.supports_remote_files()

    dlg = BackendFileDialog(master, dialog_kind, proxy.get_cwd())
    show_dialog(dlg, master)
    return dlg.result
Beispiel #16
0
    def command_enabled(self, command):
        if not get_runner().is_waiting_debugger_command():
            return False

        if command == "run_to_cursor":
            return self.get_run_to_cursor_breakpoint() is not None
        elif command == "step_back":
            return (self._last_progress_message
                    and self._last_progress_message["tracer_class"]
                    == "NiceTracer")
        else:
            return True
Beispiel #17
0
    def request_focus_into(self, path):
        if path == "":
            if running_on_windows():
                # list of drives, can't cd
                return self.focus_into(path)
            else:
                path = "/"

        if not os.path.isdir(path):
            return

        proxy = get_runner().get_backend_proxy()
        if (
            proxy
            and proxy.uses_local_filesystem()
            and proxy.get_cwd() != path
            and get_runner().is_waiting_toplevel_command()
        ):
            get_shell().submit_magic_command(construct_cd_command(path))
        else:
            # it's OK, if it's already focused into this directory
            # focus again to refresh
            self.focus_into(path)
            get_workbench().set_local_cwd(path)
Beispiel #18
0
def _update_run_or_resume_button():
    if not get_workbench().in_simple_mode():
        return

    state = get_runner().get_state()
    if state == "waiting_debugger_command":
        caption = RESUME_COMMAND_CAPTION
        image = get_workbench().get_image("resume")
    elif state == "waiting_toplevel_command":
        caption = running.RUN_COMMAND_CAPTION
        image = get_workbench().get_image("run-current-script")
    else:
        return

    button = get_workbench().get_toolbar_button("runresume")
    button.configure(text=caption, image=image)
Beispiel #19
0
        def download():
            selection = self.get_selection_info(True)
            if not selection:
                return

            response = get_runner().send_command(
                InlineCommand(
                    "download",
                    allow_overwrite=False,
                    source_paths=selection["paths"],
                    target_dir=target_dir,
                    blocking=True,
                    description=_("Downloading %s to %s") % (selection["description"], target_dir),
                )
            )
            check_upload_download_response("download", response)
            self.master.local_files.refresh_tree()
    def handle_toplevel_response(self, msg: ToplevelResponse) -> None:
        # Can be called by event system or by Workbench
        # (if Assistant wasn't created yet but an error came)
        if not msg.get("user_exception") and msg.get("command_name") in [
                "execute_system_command",
                "execute_source",
        ]:
            # Shell commands may be used to investigate the problem, don't clear assistance
            return

        self._clear()

        if not isinstance(get_runner().get_backend_proxy(), CPythonProxy):
            return

        # prepare for snapshot
        key = msg.get("filename", "<pyshell>")
        self._current_snapshot = {
            "timestamp": datetime.datetime.now().isoformat()[:19],
            "main_file_path": key,
        }
        self._snapshots_per_main_file.setdefault(key, [])
        self._snapshots_per_main_file[key].append(self._current_snapshot)

        if msg.get("user_exception"):
            if not msg["user_exception"].get("message", None):
                msg["user_exception"]["message"] = "<no message>"

            self._exception_info = msg["user_exception"]
            self._explain_exception(msg["user_exception"])
            if get_workbench().get_option(
                    "assistance.open_assistant_on_errors"):
                get_workbench().show_view("AssistantView", set_focus=False)
        else:
            self._exception_info = None

        if msg.get("filename") and os.path.exists(msg["filename"]):
            self.main_file_path = msg["filename"]
            source = read_source(msg["filename"])
            self._start_program_analyses(
                msg["filename"], source,
                _get_imported_user_files(msg["filename"], source))
        else:
            self.main_file_path = None
            self._present_conclusion()
    def _get_3rd_party_modules(self):
        proxy = get_runner().get_backend_proxy()
        if not isinstance(proxy, CPythonProxy):
            return []

        try:
            sys_path = proxy.get_sys_path()
        except Exception:
            logging.exception("Can't get sys path from proxy")
            return []

        module_names = set()
        for item in sys_path:
            if os.path.isdir(item) and ("site-packages" in item
                                        or "dist-packages" in item):
                module_names.update(self._get_module_names(item))
                for name in os.listdir(item):
                    if "-" not in name:
                        module_names.add(name.replace(".py", ""))

        return module_names
Beispiel #22
0
    def reset_remote(self, msg=None):
        runner = get_runner()
        if not runner:
            return

        proxy = runner.get_backend_proxy()
        if not proxy:
            self.hide_remote()
            return

        if proxy.supports_remote_files():
            # remote pane is needed
            if not self.remote_added:
                self.add(self.remote_files, before=self.local_files, minsize=minsize)
                self.remote_added = True
                self.restore_split()
            self.remote_files.clear()
            self.remote_files.check_update_focus()
        else:
            # remote pane not needed
            self.hide_remote()
    def __init__(self, master, prompt):
        super().__init__(master=master)
        self.result = None

        self.title(prompt)

        background = ttk.Frame(self)
        background.grid(row=0, column=0, sticky="nsew")
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        local_caption = LOCAL_FILES_ROOT_TEXT
        remote_caption = get_runner().get_node_label()

        button_width = max(len(local_caption), len(remote_caption)) + 10

        self.local_button = ttk.Button(
            background,
            text=" \n" + local_caption + "\n ",
            width=button_width,
            command=self.on_local,
        )
        self.local_button.grid(row=0, column=0, pady=20, padx=20)

        self.remote_button = ttk.Button(
            background,
            text=" \n" + remote_caption + "\n ",
            width=button_width,
            command=self.on_remote,
        )
        self.remote_button.grid(row=1, column=0, pady=(0, 20), padx=20)

        self.local_button.focus_set()

        self.bind("<Escape>", self.on_cancel, True)
        self.bind("<Return>", self.on_return, True)
        self.bind("<Down>", self.on_down, True)
        self.bind("<Up>", self.on_up, True)
        self.protocol("WM_DELETE_WINDOW", self.on_cancel)
Beispiel #24
0
    def _load_remote_file(self, filename):
        self._filename = filename
        self._code_view.set_content("")
        self._code_view.text.set_read_only(True)

        target_filename = extract_target_path(self._filename)

        self.update_title()
        response = get_runner().send_command(
            InlineCommand("read_file",
                          path=target_filename,
                          blocking=True,
                          description=_("Loading") + "..."))

        if response.get("error"):
            # TODO: make it softer
            raise RuntimeError(response["error"])

        content = response["content_bytes"]
        self._code_view.text.set_read_only(False)
        self._code_view.set_content_as_bytes(content)
        self.get_text_widget().edit_modified(False)
        self.update_title()
Beispiel #25
0
def run_enabled():
    widget = get_workbench().focus_get()
    return isinstance(
        widget, CodeViewText) and get_runner().is_waiting_toplevel_command()
Beispiel #26
0
 def _request_heap_data(self, msg=None, even_when_hidden=False):
     if self.winfo_ismapped() or even_when_hidden:
         # TODO: update itself also when it becomes visible
         if get_runner() is not None:
             get_runner().send_command(InlineCommand("get_heap"))
Beispiel #27
0
 def show_remote_file(self, target_filename):
     if not get_runner().ready_for_remote_file_operations(
             show_message=True):
         return None
     else:
         return self.show_file(make_remote_path(target_filename))
Beispiel #28
0
def make_remote_path(target_path):
    return get_runner().get_node_label() + REMOTE_PATH_MARKER + target_path
Beispiel #29
0
def _run_or_resume():
    state = get_runner().get_state()
    if state == "waiting_debugger_command":
        _issue_debugger_command("resume")
    elif state == "waiting_toplevel_command":
        get_runner().cmd_run_current_script()
Beispiel #30
0
def _run_or_resume_enabled():
    return get_runner().cmd_run_current_script_enabled(
    ) or _debugger_command_enabled("resume")