def get_kill_process_instructions(self): s = ( "Let's say you need port 5000. If you don't know which process is using it," + " then enter following system command into Thonny's Shell:\n\n" ) if running_on_windows(): s += ( "``!netstat -ano | findstr :5000``\n\n" + "You should see the process ID in the last column.\n\n" ) else: s += ( "``!lsof -i:5000``\n\n" + "You should see the process ID under the heading PID.\n\n" ) s += ( "Let's pretend the ID is 12345." " You can try hard-killing the process with following command:\n\n" ) if running_on_windows(): s += "``!tskill 12345``\n" else: s += ( "``!kill -9 12345``\n\n" + "Both steps can be combined into single command:\n\n" + "``!kill -9 $(lsof -t -i:5000)``\n\n" ) return s
def ask_new_local_path(self): if self._filename is None: initialdir = get_workbench().get_local_cwd() initialfile = None else: initialdir = os.path.dirname(self._filename) initialfile = os.path.basename(self._filename) # http://tkinter.unpythonic.net/wiki/tkFileDialog new_filename = asksaveasfilename( filetypes=_dialog_filetypes, defaultextension=".py", initialdir=initialdir, initialfile=initialfile, ) # Different tkinter versions may return different values if new_filename in ["", (), None]: return None # Seems that in some Python versions defaultextension # acts funny if new_filename.lower().endswith(".py.py"): new_filename = new_filename[:-3] if running_on_windows(): # may have /-s instead of \-s and wrong case new_filename = os.path.join( normpath_with_actual_case(os.path.dirname(new_filename)), os.path.basename(new_filename), ) if new_filename.endswith(".py"): base = os.path.basename(new_filename) mod_name = base[:-3].lower() if running_on_windows(): mod_name = mod_name.lower() if mod_name in [ "math", "turtle", "random", "statistics", "pygame", "matplotlib", "numpy", ]: # More proper name analysis will be performed by ProgramNamingAnalyzer if not tk.messagebox.askyesno( "Potential problem", "If you name your script '%s', " % base + "you won't be able to import the library module named '%s'" % mod_name + ".\n\n" + "Do you still want to use this name for your script?", ): return self.ask_new_local_path() return new_filename
def _text_settings() -> BasicUiThemeSettings: return { "Text": { "configure": { "background": "SystemWindow" if running_on_windows() else "white", "foreground": "SystemWindowText" if running_on_windows() else "black", } }, "Syntax.Text": {"map": {"background": [("readonly", "Yellow")]}}, "Gutter": {"configure": {"background": "#e0e0e0", "foreground": "#999999"}}, }
def __init__(self, master, frame_info): CommonDialog.__init__(self, master) self.transient(master) if misc_utils.running_on_windows(): self.wm_attributes("-toolwindow", 1) # TODO: take size from prefs editor_notebook = get_workbench().get_editor_notebook() if master.winfo_toplevel() == get_workbench(): position_reference = editor_notebook else: # align to previous frame position_reference = master.winfo_toplevel() self.geometry("{}x{}+{}+{}".format( editor_notebook.winfo_width(), editor_notebook.winfo_height() - 20, position_reference.winfo_rootx(), position_reference.winfo_rooty(), )) self.protocol("WM_DELETE_WINDOW", self._on_close) self.bind("<FocusIn>", self._on_focus, True) self._init_layout_widgets(master, frame_info) FrameVisualizer.__init__(self, self._text_frame, frame_info) self._firstlineno = frame_info.firstlineno self._load_code(frame_info) self._text_frame.text.focus() self.update()
def __init__(self, master): super().__init__(master) self._configuration_variable = create_string_var( get_workbench().get_option("CustomInterpreter.path")) entry_label = ttk.Label(self, text=_("Known interpreters")) entry_label.grid(row=0, column=0, columnspan=2, sticky=tk.W) self._entry = ttk.Combobox( self, exportselection=False, textvariable=self._configuration_variable, values=self._get_interpreters(), ) self._entry.grid(row=1, column=0, columnspan=2, sticky=tk.NSEW) self._entry.state(["!disabled", "readonly"]) another_label = ttk.Label( self, text=_("Your interpreter isn't in the list?")) another_label.grid(row=2, column=0, columnspan=2, sticky=tk.W, pady=(10, 0)) ttk.Style().configure("Centered.TButton", justify="center") self._select_button = ttk.Button( self, style="Centered.TButton", text=_("Locate another") + " " + ("python.exe ..." if running_on_windows() else _("python executable") + " ...") + "\n" + _("NB! Thonny only supports Python 3.5 and later"), command=self._select_executable, ) self._select_button.grid(row=3, column=0, columnspan=2, sticky=tk.NSEW) self._venv_button = ttk.Button( self, style="Centered.TButton", text=_("Create new virtual environment") + " ...\n" + "(" + _("Select existing or create a new empty directory") + ")", command=self._create_venv, ) self._venv_button.grid(row=4, column=0, columnspan=2, sticky=tk.NSEW, pady=(5, 0)) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=1)
def add_middle_menu_items(self): if self.supports_trash(): if running_on_windows(): trash_label = _("Move to Recycle Bin") else: trash_label = _("Move to Trash") self.menu.add_command(label=trash_label, command=self.move_to_trash) else: self.menu.add_command(label=_("Delete"), command=self.delete) if self.supports_directories(): self.menu.add_command(label=_("New directory") + "...", command=self.mkdir)
def _select_executable(self): # TODO: get dir of current interpreter options = {"master": self} if running_on_windows(): options["filetypes"] = [ (_("Python interpreters"), "python.exe"), (_("all files"), ".*"), ] filename = askopenfilename(**options) if filename: self._configuration_variable.set(filename)
def split_path(self, path): parts = super().split_path(path) if running_on_windows() and path.startswith("\\\\"): # Don't split a network name! sep = self.get_dir_separator() for i in reversed(range(len(parts))): prefix = sep.join(parts[: i + 1]) if os.path.ismount(prefix): return [prefix] + parts[i + 1 :] # Could not find the prefix corresponding to mount return [path] else: return parts
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." ), ) 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, ) 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 move_to_trash(self): assert self.supports_trash() selection = self.get_selection_info(True) if not selection: return trash = "Recycle Bin" if running_on_windows() else "Trash" if not messagebox.askokcancel( "Moving to %s" % trash, "I'll try to move %s to %s,\n" % (selection["description"], trash) + "but my method is not always reliable —\n" + "in some cases the files will be deleted\n" + "without the possibility to restore.", icon="info", ): return self.perform_move_to_trash( selection["paths"], _("Moving %s to %s") % (selection["description"], trash) ) self.refresh_tree()
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)
def _get_interpreters(self): result = set() if running_on_windows(): # registry result.update(self._get_interpreters_from_windows_registry()) for minor in [5, 6, 7, 8]: for dir_ in [ "C:\\Python3%d" % minor, "C:\\Python3%d-32" % minor, "C:\\Python3%d-64" % minor, "C:\\Program Files\\Python 3.%d" % minor, "C:\\Program Files\\Python 3.%d-64" % minor, "C:\\Program Files (x86)\\Python 3.%d" % minor, "C:\\Program Files (x86)\\Python 3.%d-32" % minor, ]: path = os.path.join(dir_, WINDOWS_EXE) if os.path.exists(path): result.add(normpath_with_actual_case(path)) # other locations for dir_ in ["C:\\Anaconda3", os.path.expanduser("~/Anaconda3")]: path = os.path.join(dir_, WINDOWS_EXE) if os.path.exists(path): result.add(normpath_with_actual_case(path)) else: # Common unix locations dirs = [ "/bin", "/usr/bin", "/usr/local/bin", os.path.expanduser("~/.local/bin") ] for dir_ in dirs: # if the dir_ is just a link to another dir_, skip it # (not to show items twice) # for example on Fedora /bin -> usr/bin if not os.path.exists(dir_): continue apath = normpath_with_actual_case(dir_) if apath != dir_ and apath in dirs: continue for name in [ "python3", "python3.5", "python3.6", "python3.7", "python3.8" ]: path = os.path.join(dir_, name) if os.path.exists(path): result.add(path) if running_on_mac_os(): for version in ["3.5", "3.6", "3.7", "3.8"]: dir_ = os.path.join( "/Library/Frameworks/Python.framework/Versions", version, "bin") path = os.path.join(dir_, "python3") if os.path.exists(path): result.add(path) for command in [ "python3", "python3.5", "python3.5", "python3.6", "python3.7", "python3.8" ]: path = which(command) if path is not None and os.path.isabs(path): result.add(path) for path in get_workbench().get_option("CustomInterpreter.used_paths"): if os.path.exists(path): result.add(normpath_with_actual_case(path)) return sorted(result)
def clean( frame_background: str, text_background: str, normal_detail: str, high_detail: str, low_detail: str, normal_foreground: str, high_foreground: str, low_foreground: str, custom_menubar: Optional[ int] = None, # NB! Should be 1 or 0, not True or False (Tk would convert False to "False") ) -> UiThemeSettings: # https://wiki.tcl.tk/37973 (Changing colors) # https://github.com/tcltk/tk/blob/master/library/ttk/clamTheme.tcl # https://github.com/tcltk/tk/blob/master/generic/ttk/ttkClamTheme.c return { ".": { "configure": { "foreground": normal_foreground, "background": frame_background, "lightcolor": frame_background, "darkcolor": frame_background, "bordercolor": frame_background, "selectbackground": high_detail, "selectforeground": high_foreground, }, "map": { "foreground": [("disabled", low_foreground), ("active", high_foreground)], "background": [("disabled", frame_background), ("active", high_detail)], "selectbackground": [("!focus", low_detail)], "selectforeground": [("!focus", normal_foreground)], }, }, "TNotebook": { # https://github.com/tcltk/tk/blob/master/generic/ttk/ttkNotebook.c "configure": { "bordercolor": normal_detail, "tabmargins": [scale(1), 0, 0, 0], # Margins around tab row } }, "ButtonNotebook.TNotebook": { "configure": { "bordercolor": frame_background } }, "AutomaticNotebook.TNotebook": { "configure": { "bordercolor": frame_background } }, "TNotebook.Tab": { "configure": { "background": frame_background, "bordercolor": normal_detail }, "map": { "background": [ ("selected", normal_detail), ("!selected", "!active", frame_background), ("active", "!selected", high_detail), ], "bordercolor": [("selected", frame_background), ("!selected", normal_detail)], "lightcolor": [("selected", normal_detail), ("!selected", frame_background)], }, }, "Treeview": { "configure": { "background": text_background, "borderwidth": 0, "relief": "flat" }, "map": { "background": [ ("selected", "focus", high_detail), ("selected", "!focus", low_detail), ], "foreground": [ ("selected", "focus", high_foreground), ("selected", "!focus", normal_foreground), ], }, }, "Treeview.Heading": { # https://stackoverflow.com/questions/32051780/how-to-edit-the-style-of-a-heading-in-treeview-python-ttk "configure": { "background": normal_detail, "lightcolor": normal_detail, "borderwidth": 0, }, "map": { "background": [("!active", normal_detail), ("active", normal_detail)] }, }, "TEntry": { "configure": { "fieldbackground": text_background, "lightcolor": normal_detail, "insertcolor": normal_foreground, }, "map": { "background": [("readonly", text_background)], "bordercolor": [], "lightcolor": [("focus", high_detail)], "darkcolor": [], }, }, "TCombobox": { "configure": { "background": text_background, "fieldbackground": text_background, "selectbackground": text_background, "lightcolor": text_background, "darkcolor": text_background, "bordercolor": text_background, "arrowcolor": normal_foreground, "foreground": normal_foreground, "seleftforeground": normal_foreground, # "padding" : [12,2,12,2], }, "map": { "background": [("active", text_background)], "fieldbackground": [], "selectbackground": [], "selectforeground": [], "foreground": [], "arrowcolor": [], }, }, "TScrollbar": { "configure": { "gripcount": 0, "borderwidth": 0, "relief": "flat", "darkcolor": normal_detail, "lightcolor": normal_detail, "bordercolor": text_background, "troughcolor": text_background, # arrowcolor="white" }, "map": { "background": [("!disabled", normal_detail), ("disabled", normal_detail)], "darkcolor": [("!disabled", text_background), ("disabled", text_background)], "lightcolor": [("!disabled", text_background), ("disabled", text_background)], }, }, "Vertical.TScrollbar": { # Remove scrollbar buttons/arrows: "layout": [( "Vertical.Scrollbar.trough", { "sticky": "ns", "children": [("Vertical.Scrollbar.thumb", { "expand": "1", "sticky": "nswe" })], }, )] }, "Horizontal.TScrollbar": { # Remove scrollbar buttons/arrows: "layout": [( "Horizontal.Scrollbar.trough", { "sticky": "we", "children": [("Horizontal.Scrollbar.thumb", { "expand": "1", "sticky": "nswe" })], }, )], "map": { # Make disabled Hor Scrollbar invisible "background": [("disabled", frame_background), ("!disabled", normal_detail)], "troughcolor": [("disabled", frame_background)], "bordercolor": [("disabled", frame_background)], "darkcolor": [("disabled", frame_background)], "lightcolor": [("disabled", frame_background)], }, }, "TButton": { "configure": { "background": normal_detail, "foreground": normal_foreground }, "map": { "foreground": [("disabled", low_foreground), ("alternate", high_foreground)], "background": [("pressed", low_detail), ("active", high_detail)], "bordercolor": [("alternate", high_detail)], }, }, "TCheckbutton": { "configure": { "indicatorforeground": normal_foreground, "indicatorbackground": text_background, }, "map": { "indicatorforeground": [ ("disabled", "alternate", low_foreground), ("disabled", low_foreground), ] }, }, "TRadiobutton": { "configure": { "indicatorforeground": normal_foreground, "indicatorbackground": text_background, }, "map": { "indicatorforeground": [ ("disabled", "alternate", low_foreground), ("disabled", low_foreground), ] }, }, "Toolbutton": { "configure": { "background": frame_background }, "map": { "background": [("disabled", frame_background), ("active", high_detail)] }, }, "TLabel": { "configure": { "foreground": normal_foreground } }, "Url.TLabel": { "configure": { "foreground": high_foreground } }, "TScale": { "configure": { "background": high_detail, "troughcolor": normal_detail, "lightcolor": high_detail, "darkcolor": high_detail, # "bordercolor" : "red", # "sliderlength" : 40, # "sliderthickness" : 60, "gripcount": 0, }, "map": { "background": [], "troughcolor": [] }, }, "TScale.slider": { "configure": { "background": "red", "troughcolor": "yellow", "lightcolor": "green", "darkcolor": "white", # "sliderlength" : 40, # "sliderthickness" : 60, } }, "ViewBody.TFrame": { "configure": { "background": text_background } }, "ViewToolbar.TFrame": { "configure": { "background": normal_detail } }, "ViewToolbar.Toolbutton": { "configure": { "background": normal_detail } }, "ViewTab.TLabel": { "configure": { "background": normal_detail, "padding": [5, 0] } }, "ViewToolbar.TLabel": { "configure": { "background": normal_detail, "padding": [scale(4), 0] } }, "Active.ViewTab.TLabel": { "configure": { "foreground": high_foreground, # "font" : "BoldTkDefaultFont", "background": text_background, } }, "Inactive.ViewTab.TLabel": { "configure": { "foreground": normal_foreground, "font": "UnderlineTkDefaultFont" }, "map": { "background": [("hover", high_detail)] }, }, "Text": { "configure": { "background": text_background, "foreground": normal_foreground } }, "Gutter": { "configure": { "background": low_detail, "foreground": low_foreground } }, "Listbox": { "configure": { "background": text_background, "foreground": normal_foreground, "selectbackground": high_detail, "selectforeground": high_foreground, "disabledforeground": low_foreground, "highlightbackground": normal_detail, "highlightcolor": high_detail, "highlightthickness": 1, } }, "Menubar": { "configure": { # Regular, system-provided Windows menubar doesn't allow changing colors. # custom=True replaces it with a custom-built menubar. "custom": running_on_windows() if custom_menubar is None else custom_menubar, "background": frame_background, "foreground": normal_foreground, "activebackground": normal_foreground, "activeforeground": frame_background, "relief": "flat", } }, "Menu": { "configure": { "background": normal_detail, "foreground": high_foreground, "selectcolor": normal_foreground, # "borderwidth": 0, # Interacts badly with right-clicks in Linux "activebackground": normal_foreground, "activeforeground": frame_background, # "activeborderwidth": 0, # Interacts badly with right-clicks in Linux "relief": "flat", } }, "CustomMenubarLabel.TLabel": { "configure": { "padding": [scale(10), scale(2), 0, scale(15)] } }, }