# Buggy code
def change_mode(self, mode):
    """
    Given the name of a mode, will make the necessary changes to put the
    editor into the new mode.
    """
    # Remove the old mode's REPL / filesystem / plotter if required.
    old_mode = self.modes[self.mode]
    if hasattr(old_mode, "remove_repl"):
        old_mode.remove_repl()
    if hasattr(old_mode, "remove_fs"):
        old_mode.remove_fs()
    if hasattr(old_mode, "remove_plotter"):
        if old_mode.plotter:
            old_mode.remove_plotter()
    # Deactivate old mode
    self.modes[self.mode].deactivate()
    # Re-assign to new mode.
    self.mode = mode
    # Activate new mode
    self.modes[mode].activate()
    # Update buttons.
    self._view.change_mode(self.modes[mode])
    button_bar = self._view.button_bar
    button_bar.connect("modes", self.select_mode, "Ctrl+Shift+M")
    button_bar.connect("new", self.new, "Ctrl+N")
    button_bar.connect("load", self.load, "Ctrl+O")
    button_bar.connect("save", self.save, "Ctrl+S")
    for action in self.modes[mode].actions():
        button_bar.connect(action["name"], action["handler"], action["shortcut"])
    button_bar.connect("zoom-in", self.zoom_in, "Ctrl++")
    button_bar.connect("zoom-out", self.zoom_out, "Ctrl+-")
    button_bar.connect("theme", self.toggle_theme, "F1")
    button_bar.connect("check", self.check_code, "F2")
    if sys.version_info[:2] >= (3, 6):
        button_bar.connect("tidy", self.tidy_code, "F10")
    button_bar.connect("help", self.show_help, "Ctrl+H")
    button_bar.connect("quit", self.quit, "Ctrl+Q")
    self._view.status_bar.set_mode(self.modes[mode].name)
    # Update references to default file locations.
    logger.info("Workspace directory: {}".format(self.modes[mode].workspace_dir()))
    # Reset remembered current path for load/save dialogs.
    self.current_path = ""
    # Ensure auto-save timeouts are set.
    if self.modes[mode].save_timeout > 0:
        # Start the timer
        self._view.set_timer(self.modes[mode].save_timeout, self.autosave)
    else:
        # Stop the timer
        self._view.stop_timer()
    # Update breakpoint states.
    if not (self.modes[mode].is_debugger or self.modes[mode].has_debugger):
        for tab in self._view.widgets:
            tab.breakpoint_handles = set()
            tab.reset_annotations()
    self.show_status_message(_("Changed to {} mode.").format(self.modes[mode].name))


# Traceback (PermissionError)
(base) me@ubuntu:~$ mu-editor
Logging to /home/me/snap/mu-editor/common/.cache/mu/log/mu.log
Gtk-Message: Failed to load module "gail"
Gtk-Message: Failed to load module "atk-bridge"
Gtk-Message: Failed to load module "canberra-gtk-module"
Traceback (most recent call last):
File "/snap/mu-editor/4/lib/python3.5/site-packages/mu/logic.py", line 1075, in select_mode
self.change_mode(new_mode)
File "/snap/mu-editor/4/lib/python3.5/site-packages/mu/logic.py", line 1112, in change_mode
self.modes[mode].workspace_dir()))
File "/snap/mu-editor/4/lib/python3.5/site-packages/mu/modes/adafruit.py", line 98, in workspace_dir
mount_output = check_output(mount_command).splitlines()
File "/snap/mu-editor/4/usr/lib/python3.5/subprocess.py", line 626, in check_output
**kwargs).stdout
File "/snap/mu-editor/4/usr/lib/python3.5/subprocess.py", line 693, in run
with Popen(*popenargs, **kwargs) as process:
File "/snap/mu-editor/4/usr/lib/python3.5/subprocess.py", line 947, in __init__
restore_signals, start_new_session)
File "/snap/mu-editor/4/usr/lib/python3.5/subprocess.py", line 1551, in _execute_child
raise child_exception_type(errno_num, err_msg)
PermissionError: [Errno 13] Permission denied

# Fixed code
def change_mode(self, mode):
    """
    Given the name of a mode, will make the necessary changes to put the
    editor into the new mode.
    """
    # Remove the old mode's REPL / filesystem / plotter if required.
    old_mode = self.modes[self.mode]
    if hasattr(old_mode, "remove_repl"):
        old_mode.remove_repl()
    if hasattr(old_mode, "remove_fs"):
        old_mode.remove_fs()
    if hasattr(old_mode, "remove_plotter"):
        if old_mode.plotter:
            old_mode.remove_plotter()
    # Deactivate old mode
    self.modes[self.mode].deactivate()
    # Re-assign to new mode.
    self.mode = mode
    # Activate new mode
    self.modes[mode].activate()
    # Update buttons.
    self._view.change_mode(self.modes[mode])
    button_bar = self._view.button_bar
    button_bar.connect("modes", self.select_mode, "Ctrl+Shift+M")
    button_bar.connect("new", self.new, "Ctrl+N")
    button_bar.connect("load", self.load, "Ctrl+O")
    button_bar.connect("save", self.save, "Ctrl+S")
    for action in self.modes[mode].actions():
        button_bar.connect(action["name"], action["handler"], action["shortcut"])
    button_bar.connect("zoom-in", self.zoom_in, "Ctrl++")
    button_bar.connect("zoom-out", self.zoom_out, "Ctrl+-")
    button_bar.connect("theme", self.toggle_theme, "F1")
    button_bar.connect("check", self.check_code, "F2")
    if sys.version_info[:2] >= (3, 6):
        button_bar.connect("tidy", self.tidy_code, "F10")
    button_bar.connect("help", self.show_help, "Ctrl+H")
    button_bar.connect("quit", self.quit, "Ctrl+Q")
    self._view.status_bar.set_mode(self.modes[mode].name)
    # Update references to default file locations.
    try:
        workspace_dir = self.modes[mode].workspace_dir()
        logger.info("Workspace directory: {}".format(workspace_dir))
    except Exception as e:
        # Avoid crashing if workspace_dir raises, use default path instead
        workspace_dir = self.modes["python"].workspace_dir()
        logger.error(
            (
                "Could not open {} mode workspace directory, "
                'due to exception "{}".'
                "Using:\n\n{}\n\n...to store your code instead"
            ).format(mode, repr(e), workspace_dir)
        )
    # Reset remembered current path for load/save dialogs.
    self.current_path = ""
    # Ensure auto-save timeouts are set.
    if self.modes[mode].save_timeout > 0:
        # Start the timer
        self._view.set_timer(self.modes[mode].save_timeout, self.autosave)
    else:
        # Stop the timer
        self._view.stop_timer()
    # Update breakpoint states.
    if not (self.modes[mode].is_debugger or self.modes[mode].has_debugger):
        for tab in self._view.widgets:
            tab.breakpoint_handles = set()
            tab.reset_annotations()
    self.show_status_message(_("Changed to {} mode.").format(self.modes[mode].name))