Пример #1
0
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])
Пример #2
0
 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)
Пример #3
0
 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()
Пример #4
0
    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)
Пример #5
0
    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
Пример #6
0
    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()
Пример #7
0
    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()
Пример #8
0
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)]
            }
        },
    }