def open_path_in_system_file_manager(path): if running_on_mac_os(): # http://stackoverflow.com/a/3520693/261181 subprocess.Popen(["open", "-R", path]) elif running_on_linux(): subprocess.Popen(["xdg-open", path]) else: assert running_on_windows() subprocess.Popen(["explorer", path])
def listdir(self, path="", include_hidden_files=False): if path == "" and misc_utils.running_on_windows(): result = misc_utils.get_win_drives() else: if path == "": first_level = True path = "/" else: first_level = False result = [x for x in os.listdir(path) if include_hidden_files or not misc_utils.is_hidden_or_system_file(os.path.join(path, x))] if first_level: result = ["/" + x for x in result] return sorted(result, key=str.upper)
def __init__(self, master, msg, title): tk.Toplevel.__init__(self, master) self._frame_id = msg.frame_id self.title(title) self.transient(master) if misc_utils.running_on_windows(): self.wm_attributes('-toolwindow', 1) # TODO: take size from prefs self.geometry("{}x{}+{}+{}".format(master.winfo_width(), master.winfo_height(), master.winfo_toplevel().winfo_rootx(), master.winfo_toplevel().winfo_rooty())) self.protocol("WM_DELETE_WINDOW", self._on_close) self._init_layout_widgets(master, msg) self._load_function(msg) self._stepper = StatementStepper(msg.frame_id, self, self._workbench, self._code_view) self._code_view.text.focus()
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) from shutil import which 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 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, parent=get_workbench(), ) # 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?", master=self, ): return self.ask_new_local_path() return new_filename
def _start_new_process(self, cmd=None): # deque, because in one occasion I need to put messages back self._message_queue = collections.deque() # prepare environment my_env = get_environment_for_python_subprocess(self._executable) # variables controlling communication with the back-end process my_env["PYTHONIOENCODING"] = "utf-8" # Let back-end know about plug-ins my_env["THONNY_USER_DIR"] = THONNY_USER_DIR if get_workbench().in_debug_mode(): my_env["THONNY_DEBUG"] = "1" elif "THONNY_DEBUG" in my_env: del my_env["THONNY_DEBUG"] if not os.path.exists(self._executable): raise UserError( "Interpreter (%s) not found. Please recheck corresponding option!" % self._executable) import thonny.backend_launcher cmd_line = [ self._executable, "-u", # unbuffered IO "-B", # don't write pyo/pyc files # (to avoid problems when using different Python versions without write permissions) thonny.backend_launcher.__file__, ] if hasattr(cmd, "filename"): cmd_line.append(cmd.filename) if hasattr(cmd, "args"): cmd_line.extend(cmd.args) if hasattr(cmd, "environment"): my_env.update(cmd.environment) creationflags = 0 if running_on_windows(): creationflags = subprocess.CREATE_NEW_PROCESS_GROUP debug("Starting the backend: %s %s", cmd_line, get_workbench().get_cwd()) self._proc = subprocess.Popen( cmd_line, # bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=get_workbench().get_cwd(), env=my_env, universal_newlines=True, creationflags=creationflags, ) # send init message self._send_msg({"frontend_sys_path": sys.path}) if cmd: # Consume the ready message, cmd will get its own result message ready_line = self._proc.stdout.readline() if ready_line == "": # There was some problem error_msg = self._proc.stderr.read() raise Exception("Error starting backend process: " + error_msg) self._store_state_info(parse_message(ready_line)) # setup asynchronous output listeners Thread(target=self._listen_stdout, daemon=True).start() Thread(target=self._listen_stderr, daemon=True).start()
def _start_background_process(self, clean=None, extra_args=[]): # deque, because in one occasion I need to put messages back self._response_queue = collections.deque() # prepare environment env = get_environment_for_python_subprocess(self._executable) # variables controlling communication with the back-end process env["PYTHONIOENCODING"] = "utf-8" # because cmd line option -u won't reach child processes # see https://github.com/thonny/thonny/issues/808 env["PYTHONUNBUFFERED"] = "1" # Let back-end know about plug-ins env["THONNY_USER_DIR"] = THONNY_USER_DIR env["THONNY_FRONTEND_SYS_PATH"] = repr(sys.path) env["THONNY_LANGUAGE"] = get_workbench().get_option("general.language") env["FRIENDLY_TRACEBACK_LEVEL"] = str( get_workbench().get_option("assistance.friendly_traceback_level")) if thonny.in_debug_mode(): env["THONNY_DEBUG"] = "1" elif "THONNY_DEBUG" in env: del env["THONNY_DEBUG"] if not os.path.exists(self._executable): raise UserError( "Interpreter (%s) not found. Please recheck corresponding option!" % self._executable) cmd_line = ([ self._executable, "-u", # unbuffered IO "-B", # don't write pyo/pyc files # (to avoid problems when using different Python versions without write permissions) ] + self._get_launcher_with_args() + extra_args) creationflags = 0 if running_on_windows(): creationflags = subprocess.CREATE_NEW_PROCESS_GROUP debug("Starting the backend: %s %s", cmd_line, get_workbench().get_local_cwd()) extra_params = {} if sys.version_info >= (3, 6): extra_params["encoding"] = "utf-8" self._proc = subprocess.Popen(cmd_line, bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self._get_launch_cwd(), env=env, universal_newlines=True, creationflags=creationflags, **extra_params) # setup asynchronous output listeners Thread(target=self._listen_stdout, args=(self._proc.stdout, ), daemon=True).start() Thread(target=self._listen_stderr, args=(self._proc.stderr, ), daemon=True).start()
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)] } }, }