Skip to content

Commit

Permalink
Merge pull request #12324 from goanpeca/enh/api-breakpoints
Browse files Browse the repository at this point in the history
PR: Move Breakpoints Plugin to new API
  • Loading branch information
ccordoba12 authored Jun 10, 2020
2 parents 00ca227 + a0b43fa commit 667fa7f
Show file tree
Hide file tree
Showing 5 changed files with 608 additions and 359 deletions.
10 changes: 9 additions & 1 deletion spyder/app/mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -1271,7 +1271,15 @@ def create_edit_action(text, tr_text, icon):
# Load other plugins (former external plugins)
# TODO: Use this bucle to load all internall plugins and remove
# duplicated code
other_plugins = ['breakpoints', 'profiler', 'pylint']

# Breakpoints
if CONF.get('breakpoints', 'enable'):
from spyder.plugins.breakpoints.plugin import Breakpoints
self.breakpoints = Breakpoints(self, configuration=CONF)
self.register_plugin(self.breakpoints)
self.thirdparty_plugins.append(self.breakpoints)

other_plugins = ['profiler', 'pylint']
for plugin_name in other_plugins:
if CONF.get(plugin_name, 'enable'):
module = importlib.import_module(
Expand Down
14 changes: 14 additions & 0 deletions spyder/plugins/breakpoints/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2009- Spyder Project Contributors
#
# Distributed under the terms of the MIT License
# (see spyder/__init__.py for details)

"""
Breakpoints Plugin API.
"""

# Local imports
from spyder.plugins.breakpoints.plugin import BreakpointsActions
from spyder.plugins.breakpoints.widgets.main_widget import (
BreakpointTableViewActions)
219 changes: 143 additions & 76 deletions spyder/plugins/breakpoints/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,91 +6,158 @@
# (see spyder/__init__.py for details)
# -----------------------------------------------------------------------------


"""Breakpoint Plugin."""


# pylint: disable=C0103
# pylint: disable=R0903
# pylint: disable=R0911
# pylint: disable=R0201
"""
Breakpoint Plugin.
"""

# Standard library imports
import os.path as osp
import os

# Third party imports
from qtpy.QtWidgets import QVBoxLayout
from qtpy.QtCore import Signal

# Local imports
from spyder.config.base import _
from spyder.utils import icon_manager as ima
from spyder.utils.qthelpers import create_action
from spyder.api.plugins import SpyderPluginWidget

from .widgets.breakpointsgui import BreakpointWidget


class Breakpoints(SpyderPluginWidget):
"""Breakpoint list"""
CONF_SECTION = 'breakpoints'
from spyder.api.plugins import ApplicationMenus, Plugins, SpyderDockablePlugin
from spyder.api.translations import get_translation
from spyder.plugins.breakpoints.widgets.main_widget import BreakpointWidget

# Localization
_ = get_translation('spyder')


# --- Constants
# ----------------------------------------------------------------------------
class BreakpointsActions:
ListBreakpoints = 'list_breakpoints_action'


# --- Plugin
# ----------------------------------------------------------------------------
class Breakpoints(SpyderDockablePlugin):
"""
Breakpoint list Plugin.
"""
NAME = 'breakpoints'
REQUIRES = [Plugins.Editor]
TABIFY = [Plugins.Help]
WIDGET_CLASS = BreakpointWidget
CONF_SECTION = NAME
CONF_FILE = False

def __init__(self, parent=None):
"""Initialization."""
super().__init__(parent)

self.breakpoints = BreakpointWidget(self,
options_button=self.options_button)

layout = QVBoxLayout()
layout.addWidget(self.breakpoints)
self.setLayout(layout)

self.breakpoints.set_data()

path = osp.join(self.PLUGIN_PATH, self.IMG_PATH)
self.icon = ima.icon('breakpoints', icon_path=path)

# ----- SpyderPluginWidget API --------------------------------------------
def get_plugin_title(self):
"""Return widget title"""
# --- Signals
# ------------------------------------------------------------------------
sig_clear_all_breakpoints_requested = Signal()
"""
This signal is emitted to send a request to clear all assigned
breakpoints.
"""

sig_clear_breakpoint_requested = Signal(str, int)
"""
This signal is emitted to send a request to clear a single breakpoint.
Parameters
----------
filename: str
The path to filename containing the breakpoint.
line_number: int
The line number of the breakpoint.
"""

sig_edit_goto_requested = Signal(str, int, str)
"""
Send a request to open a file in the editor at a given row and word.
Parameters
----------
filename: str
The path to the filename containing the breakpoint.
line_number: int
The line number of the breakpoint.
word: str
Text `word` to select on given `line_number`.
"""

sig_conditional_breakpoint_requested = Signal()
"""
Send a request to set/edit a condition on a single selected breakpoint.
"""

# --- SpyderDockablePlugin API
# ------------------------------------------------------------------------
def get_name(self):
return _("Breakpoints")

def get_plugin_icon(self):
"""Return widget icon"""
return self.icon

def get_focus_widget(self):
def get_description(self):
return _("Manage code breakpoints in a unified pane.")

def get_icon(self):
path = os.path.join(self.get_path(), self.IMG_PATH)
return self.create_icon('breakpoints', path=path)

def register(self):
widget = self.get_widget()
editor = self.get_plugin(Plugins.Editor)

# TODO: change name of this signal on editor
editor.breakpoints_saved.connect(self.set_data)
widget.sig_clear_all_breakpoints_requested.connect(
editor.clear_all_breakpoints)
widget.sig_clear_breakpoint_requested.connect(editor.clear_breakpoint)
widget.sig_edit_goto_requested.connect(editor.load)
widget.sig_conditional_breakpoint_requested.connect(
editor.set_or_edit_conditional_breakpoint)

widget.sig_clear_all_breakpoints_requested.connect(
self.sig_clear_all_breakpoints_requested)
widget.sig_clear_breakpoint_requested.connect(
self.sig_clear_breakpoint_requested)
widget.sig_edit_goto_requested.connect(self.sig_edit_goto_requested)
widget.sig_conditional_breakpoint_requested.connect(
self.sig_conditional_breakpoint_requested)

list_action = self.create_action(
BreakpointsActions.ListBreakpoints,
_("List breakpoints"),
triggered=lambda: self.switch_to_plugin(),
icon=self.get_icon(),
)

# TODO: Fix location once the sections are defined
debug_menu = self.get_application_menu(ApplicationMenus.Debug)
self.add_item_to_application_menu(list_action, debug_menu)
editor.pythonfile_dependent_actions += [list_action]

# --- Private API
# ------------------------------------------------------------------------
def _load_data(self):
"""
Return the widget to give focus to when
this plugin's dockwidget is raised on top-level
Load breakpoint data from configuration file.
"""
return self.breakpoints.dictwidget

def on_first_registration(self):
"""Action to be performed on first plugin registration"""
self.tabify(self.main.help)

def register_plugin(self):
"""Register plugin in Spyder's main window"""
self.breakpoints.edit_goto.connect(self.main.editor.load)
self.breakpoints.clear_all_breakpoints.connect(
self.main.editor.clear_all_breakpoints)
self.breakpoints.clear_breakpoint.connect(
self.main.editor.clear_breakpoint)
self.main.editor.breakpoints_saved.connect(self.breakpoints.set_data)
self.breakpoints.set_or_edit_conditional_breakpoint.connect(
self.main.editor.set_or_edit_conditional_breakpoint)

self.add_dockwidget()

list_action = create_action(self, _("List breakpoints"),
triggered=self.show, icon=self.icon)
list_action.setEnabled(True)
pos = self.main.debug_menu_actions.index('list_breakpoints')
self.main.debug_menu_actions.insert(pos, list_action)
self.main.editor.pythonfile_dependent_actions += [list_action]

def show(self):
"""Show the breakpoints dockwidget"""
self.switch_to_plugin()
breakpoints_dict = self.get_conf_option(
'breakpoints',
default={},
section='run',
)
for filename in list(breakpoints_dict.keys()):
if not os.path.isfile(filename):
breakpoints_dict.pop(filename)

return breakpoints_dict

# --- Public API
# ------------------------------------------------------------------------
def set_data(self, data=None):
"""
Set breakpoint data on widget.
Parameters
----------
data: dict, optional
Breakpoint data to use. If None, data from the configuration
will be loaded. Default is None.
"""
if data is None:
data = self._load_data()

self.get_widget().set_data(data)
Loading

0 comments on commit 667fa7f

Please sign in to comment.