def _create_venv(self): path = askdirectory( parent=self.winfo_toplevel(), initialdir=None, title=tr( "Select an existing virtual environemnt or an empty directory for new virtual environment" ), ) assert os.path.isdir(path) path = normpath_with_actual_case(path) if not os.listdir(path): proc = subprocess.Popen( [running.get_interpreter_for_subprocess(), "-m", "venv", path], stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, ) dlg = SubprocessDialog(self, proc, tr("Creating virtual environment")) ui_utils.show_dialog(dlg) if running_on_windows(): exe_path = normpath_with_actual_case( os.path.join(path, "Scripts", "python.exe")) else: exe_path = os.path.join(path, "bin", "python3") if os.path.exists(exe_path): self._configuration_variable.set(exe_path) else: # Undefined error handling. pass
def choose_node_for_file_operations(master, prompt): if get_runner().has_own_filesystem(): dlg = NodeChoiceDialog(master, prompt) show_dialog(dlg, master) return dlg.result else: return "local"
def _create_private_venv(self, path, description, clear=False, upgrade=False): if not _check_venv_installed(self): return # Don't include system site packages # This way all students will have similar configuration # independently of system Python (if Thonny is used with system Python) # NB! Cant run venv.create directly, because in Windows bundle # it tries to link venv to thonny.exe. # Need to run it via proper python args = ["-m", "venv"] if clear: args.append("--clear") if upgrade: args.append("--upgrade") try: import ensurepip except ImportError: args.append("--without-pip") args.append(path) proc = create_frontend_python_process(args) from thonny.workdlg import SubprocessDialog dlg = SubprocessDialog( get_workbench(), proc, "Preparing the backend", long_description=description, autostart=True, ) try: ui_utils.show_dialog(dlg) except Exception: # if using --without-pip the dialog may close very quickly # and for some reason wait_window would give error then logging.exception("Problem with waiting for venv creation dialog") get_workbench().become_active_window( ) # Otherwise focus may get stuck somewhere bindir = os.path.dirname(get_private_venv_executable()) # create private env marker marker_path = os.path.join(bindir, "is_private") with open(marker_path, mode="w") as fp: fp.write("# This file marks Thonny-private venv") # Create recommended pip conf to get rid of list deprecation warning # https://github.com/pypa/pip/issues/4058 pip_conf = "pip.ini" if running_on_windows() else "pip.conf" with open(os.path.join(path, pip_conf), mode="w") as fp: fp.write("[list]\nformat = columns") assert os.path.isdir(path)
def _run_pip_with_dialog(self, args, title) -> Tuple[int, str, str]: args = ["-m", "thonny.plugins.micropython.minipip"] + args proc = running.create_frontend_python_process(args, stderr=subprocess.STDOUT) cmd = proc.cmd dlg = SubprocessDialog(self, proc, "minipip", long_description=title, autostart=True) ui_utils.show_dialog(dlg) return dlg.returncode, dlg.stdout, dlg.stderr
def send_command_and_wait(self, cmd: CommandToBackend, dialog_title: str) -> MessageFromBackend: dlg = InlineCommandDialog(get_workbench(), cmd, title=dialog_title + " ...") show_dialog(dlg) return dlg.response
def _ask_feedback(self, event=None): all_snapshots = self._snapshots_per_main_file[self._current_snapshot["main_file_path"]] # TODO: select only snapshots which are not sent yet snapshots = all_snapshots ui_utils.show_dialog(FeedbackDialog(get_workbench(), self.main_file_path, snapshots))
def ask_backend_path(master, dialog_kind): proxy = get_runner().get_backend_proxy() if not proxy: return None assert proxy.has_own_filesystem() dlg = BackendFileDialog(master, dialog_kind, proxy.get_default_directory()) show_dialog(dlg, master) return dlg.result
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
def choose_node_for_file_operations(master, prompt): if get_runner().supports_remote_files(): dlg = NodeChoiceDialog(master, prompt) show_dialog(dlg, master) if not get_runner().ready_for_remote_file_operations( propose_waiting=True): return None return dlg.result else: return "local"
def _create_venv(self, event=None): if not _check_venv_installed(self): return messagebox.showinfo( "Creating new virtual environment", "After clicking 'OK' you need to choose an empty directory, " "which will be the root of your new virtual environment.", parent=self, ) path = None while True: path = askdirectory( parent=self.winfo_toplevel(), initialdir=path, title=tr("Select empty directory for new virtual environment"), ) if not path: return if os.listdir(path): messagebox.showerror( tr("Bad directory"), tr("Selected directory is not empty.\nSelect another or cancel." ), master=self, ) else: break assert os.path.isdir(path) path = normpath_with_actual_case(path) proc = subprocess.Popen( [running.get_interpreter_for_subprocess(), "-m", "venv", path], stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, ) from thonny.workdlg import SubprocessDialog dlg = SubprocessDialog(self, proc, tr("Creating virtual environment"), autostart=True) ui_utils.show_dialog(dlg) if running_on_windows(): exe_path = normpath_with_actual_case( os.path.join(path, "Scripts", "python.exe")) else: exe_path = os.path.join(path, "bin", "python3") if os.path.exists(exe_path): self._configuration_variable.set(exe_path)
def launch(): _prepare_thonny_user_dir() _misc_prepare() try: from thonny import workbench if _should_delegate(): # First check if there is existing Thonny instance to handle the request delegation_result = _try_delegate_to_existing_instance( sys.argv[1:]) if delegation_result == True: # pylint: disable=singleton-comparison # we're done print("Delegated to an existing Thonny instance. Exiting now.") return 0 if hasattr(delegation_result, "accept"): # we have server socket to put in use server_socket = delegation_result else: server_socket = None bench = workbench.Workbench(server_socket) else: bench = workbench.Workbench() try: bench.mainloop() except SystemExit: bench.destroy() return 0 except SystemExit as e: from tkinter import messagebox messagebox.showerror("System exit", str(e), parent=get_workbench()) return -1 except Exception: from logging import exception exception("Internal launch or mainloop error") from thonny import ui_utils import traceback dlg = ui_utils.LongTextDialog("Internal error", traceback.format_exc(), parent=get_workbench()) ui_utils.show_dialog(dlg, get_workbench()) return -1 finally: runner = get_runner() if runner is not None: runner.destroy_backend() return 0
def _open_flashing_dialog(self): mount_path = find_volume_by_name( "MICROBIT", not_found_msg=_("Could not find disk '%s'.") + "\n" + _("Make sure you have micro:bit plugged in!") + "\n\n" + _("Do you want to continue and locate the disk yourself?"), ) if mount_path is None: return dlg = FlashingDialog(get_workbench(), mount_path) ui_utils.show_dialog(dlg)
def download(): selection = self.get_selection_info(True) if not selection: return dlg = DownloadDialog( self, selection["paths"], selection["description"], target_dir, ) ui_utils.show_dialog(dlg) if dlg.response is not None: self.master.local_files.refresh_tree()
def flash_the_firmware(hex_path): mount_path = find_volume_by_name( "MINI", not_found_msg="Could not find disk '%s'.\n" + "Make sure you have Calliope Mini plugged in!\n\n" + "Do you want to continue and locate the disk yourself?") if mount_path is None: return destination_path = os.path.join(mount_path, os.path.basename(hex_path)) dlg = FileCopyDialog( get_workbench(), hex_path, destination_path, "Uploading %s to %s" % (os.path.basename(hex_path), mount_path)) ui_utils.show_dialog(dlg)
def _open_flashing_dialog(self): esptool_command = self._get_esptool_command() if not esptool_command: messagebox.showerror( "Can't find esptool", "esptool not found.\n" + "Install it via 'Tools => Manage plug-ins'\n" + "or " "using your OP-system package manager.", master=self, ) return dlg = ESPFlashingDialog(self.winfo_toplevel(), self._chip, self._firmware_start_address, esptool_command) ui_utils.show_dialog(dlg)
def _run_pip_with_dialog(self, args, title) -> Tuple[int, str, str]: proxy = get_runner().get_backend_proxy() assert isinstance(proxy, CPythonProxy) sub_cmd = [proxy._reported_executable, "-m", "pip"] + args + self._get_extra_switches() back_cmd = InlineCommand("execute_system_command", cmd_line=sub_cmd) dlg = InlineCommandDialog( self, back_cmd, title="pip", instructions=title, autostart=True, output_prelude=subprocess.list2cmdline(sub_cmd) + "\n\n", ) ui_utils.show_dialog(dlg) return dlg.returncode, dlg.stdout, dlg.stderr
def open_backend_pip_gui(*args): pg_class = get_pip_gui_class() if pg_class is None: showerror(tr("Not supported"), get_not_supported_translation()) return if not get_runner().is_waiting_toplevel_command(): showerror( tr("Not available"), tr("You need to stop your program before launching the package manager."), master=get_workbench(), ) return pg = pg_class(get_workbench()) ui_utils.show_dialog(pg)
def load_plugin(): add_micropython_backend("CircuitPython", CircuitPythonProxy, "CircuitPython (generic)", CircuitPythonConfigPage) get_workbench().add_command("installcp", "device", "Install CircuitPython firmware ...", lambda: show_dialog(FlashingDialog()), group=40)
def _run_pip_with_dialog(self, args, title) -> Tuple[int, str, str]: args = ["-m", "thonny.plugins.micropython.minipip"] + args proc = running.create_frontend_python_process(args, stderr=subprocess.STDOUT) cmd = proc.cmd dlg = InstallAndUploadDialog( self, proc, back_cmd=self._create_upload_command, title="minipip", instructions=title, autostart=True, output_prelude=subprocess.list2cmdline(cmd) + "\n", ) ui_utils.show_dialog(dlg) assert dlg.returncode is not None return dlg.returncode, dlg.stdout, dlg.stderr
def get_ssh_password(conf_group): host = get_workbench().get_option(conf_group + ".host") user = get_workbench().get_option(conf_group + ".user") method = get_workbench().get_option(conf_group + ".auth_method") if method == PUBLIC_KEY_NO_PASS_METHOD: return None elif os.path.exists(get_ssh_password_file_path()): with open(get_ssh_password_file_path()) as fp: return fp.read().strip() else: dlg = PasswordDialog(get_workbench(), host, user, method) ui_utils.show_dialog(dlg) if dlg.password and dlg.save_password: with open(get_ssh_password_file_path(), "w") as fp: fp.write(dlg.password) if not dlg.save_password or not dlg.password: delete_stored_ssh_password() return dlg.password
def _create_venv(self): path = None while True: path = askdirectory( master=self, initialdir=path, title=_("Select empty directory for new virtual environment"), ) if not path: return if os.listdir(path): messagebox.showerror( _("Bad directory"), _("Selected directory is not empty.\nSelect another or cancel." ), parent=get_workbench(), ) else: break assert os.path.isdir(path) path = normpath_with_actual_case(path) proc = subprocess.Popen( [running.get_frontend_python(), "-m", "venv", path], stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, ) dlg = SubprocessDialog(self, proc, _("Creating virtual environment")) ui_utils.show_dialog(dlg) if running_on_windows(): exe_path = normpath_with_actual_case( os.path.join(path, "Scripts", "python.exe")) else: exe_path = os.path.join(path, "bin", "python3") if os.path.exists(exe_path): self._configuration_variable.set(exe_path)
def open_replayer(): win = ReplayWindow() ui_utils.show_dialog(win)
def _open_flashing_dialog(self): dlg = MicrobitFlashingDialog(self) ui_utils.show_dialog(dlg)
def open_about(*args): ui_utils.show_dialog(AboutDialog(get_workbench()))
def _open_flashing_dialog(self): dlg = CircuitPythonFlashingDialog(self) ui_utils.show_dialog(dlg)
def open_frontend_pip_gui(*args): pg = PluginsPipDialog(get_workbench()) ui_utils.show_dialog(pg)
def open_backend_pip_gui(*args): pg = BackendPipDialog(get_workbench()) ui_utils.show_dialog(pg)
def _ask_installation_details(master, data, selected_version): dlg = DetailsDialog(master, data, selected_version) ui_utils.show_dialog(dlg, master) return dlg.result
def _show_subprocess_dialog(master, proc, title): dlg = SubprocessDialog(master, proc, title) ui_utils.show_dialog(dlg, master) return dlg.returncode, dlg.stdout, dlg.stderr
def launch(): import runpy if sys.executable.endswith("thonny.exe"): # otherwise some library may try to run its subprocess with thonny.exe # NB! Must be pythonw.exe not python.exe, otherwise Runner thinks console # is already allocated. sys.executable = sys.executable[:-len("thonny.exe")] + "pythonw.exe" set_dpi_aware() try: runpy.run_module("thonny.customize", run_name="__main__") except ImportError: pass _prepare_thonny_user_dir() if not _check_welcome(): return 0 if _should_delegate(): try: _delegate_to_existing_instance(sys.argv[1:]) print("Delegated to an existing Thonny instance. Exiting now.") return 0 except Exception: traceback.print_exc() # Did not or could not delegate try: from thonny import workbench bench = workbench.Workbench() try: bench.mainloop() except SystemExit: bench.destroy() return 0 except SystemExit as e: from tkinter import messagebox messagebox.showerror("System exit", str(e)) return -1 except Exception: from logging import exception exception("Internal launch or mainloop error") from thonny import ui_utils dlg = ui_utils.LongTextDialog("Internal error", traceback.format_exc()) ui_utils.show_dialog(dlg, get_workbench()) return -1 finally: runner = get_runner() if runner is not None: runner.destroy_backend() return 0