Ejemplo n.º 1
0
 def __init__(self, master, show_expand_buttons=True):
     super().__init__(master, show_expand_buttons=show_expand_buttons)
     get_workbench().bind("WindowFocusIn", self.on_window_focus_in, True)
     get_workbench().bind("LocalFileOperation",
                          self.on_local_file_operation, True)
Ejemplo n.º 2
0
def load_plugin():
    get_workbench().add_view(NotesView,
                             _("Notes"),
                             "ne",
                             default_position_key="zz")
Ejemplo n.º 3
0
 def open_frontend_pip_gui(*args):
     pg = PluginsPipDialog(get_workbench())
     ui_utils.show_dialog(pg)
Ejemplo n.º 4
0
 def cmd_run_current_script_enabled(self) -> bool:
     return (
         get_workbench().get_editor_notebook().get_current_editor() is not None
         and "run" in get_runner().get_supported_features()
     )
Ejemplo n.º 5
0
    def cmd_stop_restart(self) -> None:
        if get_workbench().in_simple_mode():
            get_workbench().hide_view("VariablesView")

        self.restart_backend(True)
Ejemplo n.º 6
0
    def _init_commands(self) -> None:
        global RUN_COMMAND_CAPTION, RUN_COMMAND_LABEL

        RUN_COMMAND_LABEL = tr("Run current script")
        RUN_COMMAND_CAPTION = tr("Run")

        get_workbench().set_default("run.run_in_terminal_python_repl", False)
        get_workbench().set_default("run.run_in_terminal_keep_open", True)

        try:
            import thonny.plugins.debugger  # @UnusedImport

            debugger_available = True
        except ImportError:
            debugger_available = False

        get_workbench().add_command(
            "run_current_script",
            "run",
            RUN_COMMAND_LABEL,
            caption=RUN_COMMAND_CAPTION,
            handler=self.cmd_run_current_script,
            default_sequence="<F5>",
            extra_sequences=[select_sequence("<Control-r>", "<Command-r>")],
            tester=self.cmd_run_current_script_enabled,
            group=10,
            image="run-current-script",
            include_in_toolbar=not (get_workbench().in_simple_mode() and debugger_available),
            show_extra_sequences=True,
        )

        get_workbench().add_command(
            "run_current_script_in_terminal",
            "run",
            tr("Run current script in terminal"),
            caption="RunT",
            handler=self._cmd_run_current_script_in_terminal,
            default_sequence="<Control-t>",
            extra_sequences=["<<CtrlTInText>>"],
            tester=self._cmd_run_current_script_in_terminal_enabled,
            group=35,
            image="terminal",
        )

        get_workbench().add_command(
            "restart",
            "run",
            tr("Stop/Restart backend"),
            caption=tr("Stop"),
            handler=self.cmd_stop_restart,
            default_sequence="<Control-F2>",
            group=100,
            image="stop",
            include_in_toolbar=True,
        )

        get_workbench().add_command(
            "interrupt",
            "run",
            tr("Interrupt execution"),
            handler=self._cmd_interrupt,
            tester=self._cmd_interrupt_enabled,
            default_sequence=INTERRUPT_SEQUENCE,
            skip_sequence_binding=True,  # Sequence will be bound differently
            group=100,
            bell_when_denied=False,
        )
        get_workbench().bind(INTERRUPT_SEQUENCE, self._cmd_interrupt_with_shortcut, True)

        get_workbench().add_command(
            "ctrld",
            "run",
            tr("Send EOF / Soft reboot"),
            self.ctrld,
            self.ctrld_enabled,
            group=100,
            default_sequence="<Control-d>",
            extra_sequences=["<<CtrlDInText>>"],
        )

        get_workbench().add_command(
            "disconnect",
            "run",
            tr("Disconnect"),
            self.disconnect,
            self.disconnect_enabled,
            group=100,
        )
Ejemplo n.º 7
0
 def close(self):
     get_workbench().unbind("InlineResponse", self._on_response)
     get_workbench().unbind("InlineProgress", self._on_progress)
     super(InlineCommandDialog, self).close()
     get_shell().set_ignore_program_output(False)
Ejemplo n.º 8
0
 def _append_image(self, name, extra_tags=()):
     index = self.text.index("end-1c")
     self.text.image_create(index,
                            image=get_workbench().get_image(name))
     for tag in self._get_effective_tags(extra_tags):
         self.text.tag_add(tag, index)
Ejemplo n.º 9
0
def _get_current_editor():
    return get_workbench().get_editor_notebook().get_current_editor()
Ejemplo n.º 10
0
 def get_toggler_image_name(kind):
     if get_workbench().uses_dark_ui_theme():
         return kind + "_light"
     else:
         return kind
Ejemplo n.º 11
0
 def handle_click(event):
     get_workbench().open_url(node.attributes["refuri"])
Ejemplo n.º 12
0
            def _visit_toggle_topic(self, node):
                tag = self._create_unique_tag()
                title_id_tag = tag + "_title"
                body_id_tag = tag + "_body"

                def get_toggler_image_name(kind):
                    if get_workbench().uses_dark_ui_theme():
                        return kind + "_light"
                    else:
                        return kind

                if "open" in node.attributes["classes"]:
                    initial_image = get_toggler_image_name("boxminus")
                    initial_elide = False
                else:
                    initial_image = get_toggler_image_name("boxplus")
                    initial_elide = True

                label = tk.Label(
                    self.text,
                    image=get_workbench().get_image(initial_image),
                    borderwidth=0,
                    background=self.text["background"],
                    cursor="arrow",
                )

                def toggle_body(event=None):
                    elide = self.text.tag_cget(body_id_tag, "elide")
                    if elide == "1":
                        elide = True
                    elif elide == "0":
                        elide = False
                    else:
                        elide = bool(elide)

                    elide = not elide

                    self.text.tag_configure(body_id_tag, elide=elide)
                    if self.text.has_selection():
                        self.text.tag_remove("sel", "1.0", "end")

                    if elide:
                        label.configure(image=get_workbench().get_image(
                            get_toggler_image_name("boxplus")))
                    else:
                        label.configure(image=get_workbench().get_image(
                            get_toggler_image_name("boxminus")))

                assert isinstance(node.children[0], docutils.nodes.title)

                # self.text.tag_bind(title_id_tag, "<1>", toggle_body, True)
                self._add_tag(title_id_tag)
                self._append_window(label)
                label.bind("<1>", toggle_body, True)
                node.children[0].walkabout(self)
                self._pop_tag(title_id_tag)

                self.text.tag_configure(body_id_tag, elide=initial_elide)
                self._add_tag(body_id_tag)
                self._add_tag("topic_body")
                for child in list(node.children)[1:]:
                    child.walkabout(self)
                self._pop_tag("topic_body")
                self._pop_tag(body_id_tag)

                if "tight" not in node.attributes["classes"]:
                    self._append_text("\n")

                raise docutils.nodes.SkipNode()
Ejemplo n.º 13
0
 def open_file(self, path):
     get_workbench().get_editor_notebook().show_file(path)
Ejemplo n.º 14
0
 def destroy(self):
     super().destroy()
     get_workbench().unbind("WindowFocusIn", self.on_window_focus_in)
     get_workbench().unbind("LocalFileOperation",
                            self.on_local_file_operation)
Ejemplo n.º 15
0
 def open_about(*args):
     ui_utils.show_dialog(AboutDialog(get_workbench()))
Ejemplo n.º 16
0
def load_plugin():
    add_program_analyzer(PylintAnalyzer)
    get_workbench().set_default("assistance.use_pylint", True)
Ejemplo n.º 17
0
 def _publish_cwd(self, cwd):
     if self.uses_local_filesystem():
         get_workbench().set_local_cwd(cwd)
Ejemplo n.º 18
0
 def is_enabled(self):
     return get_workbench().get_option("assistance.use_pylint")
Ejemplo n.º 19
0
def get_environment_overrides_for_python_subprocess(target_executable):
    """Take care of not not confusing different interpreter
    with variables meant for bundled interpreter"""

    # At the moment I'm tweaking the environment only if current
    # exe is bundled for Thonny.
    # In remaining cases it is user's responsibility to avoid
    # calling Thonny with environment which may be confusing for
    # different Pythons called in a subprocess.

    this_executable = sys.executable.replace("pythonw.exe", "python.exe")
    target_executable = target_executable.replace("pythonw.exe", "python.exe")

    interpreter_specific_keys = [
        "TCL_LIBRARY",
        "TK_LIBRARY",
        "LD_LIBRARY_PATH",
        "DYLD_LIBRARY_PATH",
        "SSL_CERT_DIR",
        "SSL_CERT_FILE",
        "PYTHONHOME",
        "PYTHONPATH",
        "PYTHONNOUSERSITE",
        "PYTHONUSERBASE",
    ]

    result = {}

    if os.path.samefile(
        target_executable, this_executable
    ) or is_venv_interpreter_of_current_interpreter(target_executable):
        # bring out some important variables so that they can
        # be explicitly set in macOS Terminal
        # (If they are set then it's most likely because current exe is in Thonny bundle)
        for key in interpreter_specific_keys:
            if key in os.environ:
                result[key] = os.environ[key]

        # never pass some variables to different interpreter
        # (even if it's venv or symlink to current one)
        if not is_same_path(target_executable, this_executable):
            for key in ["PYTHONPATH", "PYTHONHOME", "PYTHONNOUSERSITE", "PYTHONUSERBASE"]:
                if key in os.environ:
                    result[key] = None
    else:
        # interpreters are not related
        # interpreter specific keys most likely would confuse other interpreter
        for key in interpreter_specific_keys:
            if key in os.environ:
                result[key] = None

    # some keys should be never passed
    for key in [
        "PYTHONSTARTUP",
        "PYTHONBREAKPOINT",
        "PYTHONDEBUG",
        "PYTHONNOUSERSITE",
        "PYTHONASYNCIODEBUG",
    ]:
        if key in os.environ:
            result[key] = None

    # venv may not find (correct) Tk without assistance (eg. in Ubuntu)
    if is_venv_interpreter_of_current_interpreter(target_executable):
        try:
            if "TCL_LIBRARY" not in os.environ or "TK_LIBRARY" not in os.environ:
                result["TCL_LIBRARY"] = get_workbench().tk.exprstring("$tcl_library")
                result["TK_LIBRARY"] = get_workbench().tk.exprstring("$tk_library")
        except Exception:
            logging.exception("Can't compute Tcl/Tk library location")

    return result
Ejemplo n.º 20
0
def load_plugin() -> None:
    get_workbench().add_configuration_page("General", GeneralConfigurationPage)
Ejemplo n.º 21
0
 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
Ejemplo n.º 22
0
    def __init__(self, master):
        ConfigurationPage.__init__(self, master)

        self.add_checkbox(
            "general.single_instance",
            "Allow only single Thonny instance",
            row=1,
            columnspan=2,
        )
        self.add_checkbox(
            "general.debug_mode",
            "Debug mode (provides more detailed logs)",
            row=3,
            columnspan=2,
        )
        self.add_checkbox(
            "file.reopen_all_files",
            "Reopen all files from previous session",
            row=4,
            columnspan=2,
        )
        self.add_checkbox(
            "general.disable_notification_sound",
            "Disable notification sound",
            row=5,
            columnspan=2,
        )

        ttk.Label(self, text="UI mode").grid(row=6,
                                             column=0,
                                             sticky=tk.W,
                                             padx=(0, 10),
                                             pady=(10, 0))
        self.add_combobox("general.ui_mode", ["simple", "regular", "expert"],
                          row=6,
                          column=1,
                          pady=(10, 0))

        self._scaling_var = get_workbench().get_variable("general.scaling")
        self._scaling_label = ttk.Label(self, text="UI scaling factor")
        self._scaling_label.grid(row=7,
                                 column=0,
                                 sticky=tk.W,
                                 padx=(0, 10),
                                 pady=(10, 0))
        scalings = sorted(
            {0.5, 0.75, 1.0, 1.25, 1.33, 1.5, 2.0, 2.5, 3.0, 4.0})
        self._scaling_combo = ttk.Combobox(
            self,
            width=7,
            exportselection=False,
            textvariable=self._scaling_var,
            state="readonly",
            height=15,
            values=["default"] + scalings,
        )
        self._scaling_combo.grid(row=7, column=1, sticky=tk.W, pady=(10, 0))

        self._font_scaling_var = get_workbench().get_variable(
            "general.font_scaling_mode")
        self._font_scaling_label = ttk.Label(self, text="Font scaling mode")
        self._font_scaling_label.grid(row=8,
                                      column=0,
                                      sticky=tk.W,
                                      padx=(0, 10),
                                      pady=(10, 0))
        scalings = sorted(
            {0.5, 0.75, 1.0, 1.25, 1.33, 1.5, 2.0, 2.5, 3.0, 4.0})
        self._font_scaling_combo = ttk.Combobox(
            self,
            width=10,
            exportselection=False,
            textvariable=self._font_scaling_var,
            state="readonly",
            height=15,
            values=["default", "extra", "automatic"],
        )
        self._font_scaling_combo.grid(row=8,
                                      column=1,
                                      sticky=tk.W,
                                      pady=(10, 0))

        reopen_label = ttk.Label(
            self,
            text="NB! Restart Thonny after changing these options" +
            "\nin order to see the full effect",
            font="BoldTkDefaultFont",
        )
        reopen_label.grid(row=20, column=0, sticky=tk.W, pady=20, columnspan=2)

        self.columnconfigure(1, weight=1)
Ejemplo n.º 23
0
 def cmd_run_current_script(self) -> None:
     if get_workbench().in_simple_mode():
         get_workbench().hide_view("VariablesView")
     self.execute_current("Run")
import uuid
import copy
import threading

import tkinter as tk
import paho.mqtt.client as mqtt_client
import paho.mqtt.publish as mqtt_publish
import paho.mqtt.subscribe as mqtt_subscribe

import thonnycontrib.codelive.utils as utils
import thonnycontrib.codelive.client as thonny_client

from thonnycontrib.codelive.user import UserDecoder, UserEncoder
from thonny import get_workbench

WORKBENCH = get_workbench()

BROKER_URLS = [
    "test.mosquitto.org",
    "mqtt.eclipse.org",
    "broker.hivemq.com",
    "mqtt.fluux.io",
    "broker.emqx.io",
]

USER_COLORS = [
    "blue", "green", "red", "pink", "orange", "black", "white", "purple"
]
SINGLE_PUBLISH_HEADER = b"CODELIVE_MSG:"

Ejemplo n.º 25
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")

        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()
Ejemplo n.º 26
0
 def destroy(self):
     MemoryFrame.destroy(self)
     get_workbench().unbind("ShowView", self._update_memory_model)
     get_workbench().unbind("HideView", self._update_memory_model)
Ejemplo n.º 27
0
 def open_backend_pip_gui(*args):
     pg = BackendPipDialog(get_workbench())
     ui_utils.show_dialog(pg)
Ejemplo n.º 28
0
 def open_replayer():
     win = ReplayWindow(get_workbench())
     ui_utils.show_dialog(win)
Ejemplo n.º 29
0
 def add_entry(self, option_name, row=None, column=0, pady=0, padx=0, columnspan=1, **kw):
     variable = get_workbench().get_variable(option_name)
     entry = ttk.Entry(self, textvariable=variable, **kw)
     entry.grid(row=row, column=column, sticky=tk.W, pady=pady, columnspan=columnspan, padx=padx)
Ejemplo n.º 30
0
 def should_open_name_in_thonny(self, name):
     ext = self.get_extension_from_name(name)
     return get_workbench().get_option(get_file_handler_conf_key(ext),
                                       "system") == "thonny"