/
plugin.py
162 lines (130 loc) · 5.17 KB
/
plugin.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
# Licensed under the terms of the MIT License
# (see spyder/__init__.py for details)
"""
Pylint Code Analysis Plugin.
"""
# Standard library imports
import os.path as osp
# Third party imports
from qtpy.QtCore import Signal, Slot
# Local imports
from spyder.plugins.mainmenu.api import ApplicationMenus
from spyder.api.translations import get_translation
from spyder.api.plugins import Plugins, SpyderDockablePlugin
from spyder.utils.programs import is_module_installed
from spyder.plugins.pylint.confpage import PylintConfigPage
from spyder.plugins.pylint.main_widget import (PylintWidget,
PylintWidgetActions)
# Localization
_ = get_translation("spyder")
class Pylint(SpyderDockablePlugin):
NAME = "pylint"
WIDGET_CLASS = PylintWidget
CONF_SECTION = NAME
CONF_WIDGET_CLASS = PylintConfigPage
REQUIRES = [Plugins.Preferences, Plugins.Editor]
OPTIONAL = [Plugins.MainMenu, Plugins.Projects]
CONF_FILE = False
DISABLE_ACTIONS_WHEN_HIDDEN = False
# --- Signals
sig_edit_goto_requested = Signal(str, int, str)
"""
This signal will request to open a file in a given row and column
using a code editor.
Parameters
----------
path: str
Path to file.
row: int
Cursor starting row position.
word: str
Word to select on given row.
"""
def get_name(self):
return _("Code Analysis")
def get_description(self):
return _("Run Code Analysis.")
def get_icon(self):
path = osp.join(self.get_path(), self.IMG_PATH)
return self.create_icon("pylint", path=path)
def register(self):
widget = self.get_widget()
editor = self.get_plugin(Plugins.Editor)
mainmenu = self.get_plugin(Plugins.MainMenu)
preferences = self.get_plugin(Plugins.Preferences)
preferences.register_plugin_preferences(self)
# Expose widget signals at the plugin level
widget.sig_edit_goto_requested.connect(self.sig_edit_goto_requested)
widget.sig_redirect_stdio_requested.connect(
self.sig_redirect_stdio_requested)
widget.sig_start_analysis_requested.connect(
lambda: self.start_code_analysis())
# Connect to Editor
widget.sig_edit_goto_requested.connect(editor.load)
editor.sig_editor_focus_changed.connect(self._set_filename)
# Connect to projects
projects = self.get_plugin(Plugins.Projects)
if projects:
projects.sig_project_loaded.connect(
lambda value: widget.change_option("project_dir", value))
projects.sig_project_closed.connect(
lambda value: widget.change_option("project_dir", None))
# Add action to application menus
pylint_act = self.get_action(PylintWidgetActions.RunCodeAnalysis)
pylint_act.setEnabled(is_module_installed("pylint"))
if mainmenu:
source_menu = mainmenu.get_application_menu(
ApplicationMenus.Source)
mainmenu.add_item_to_application_menu(pylint_act, menu=source_menu)
# TODO: use new API when editor has migrated
self.main.editor.pythonfile_dependent_actions += [pylint_act]
# --- Private API
# ------------------------------------------------------------------------
@Slot()
def _set_filename(self):
"""
Set filename without code analysis.
"""
editor = self.get_plugin(Plugins.Editor)
if editor:
self.get_widget().set_filename(editor.get_current_filename())
# --- Public API
# ------------------------------------------------------------------------
def change_history_depth(self, value=None):
"""
Change history maximum number of entries.
Parameters
----------
value: int or None, optional
The valur to set the maximum history depth. If no value is
provided, an input dialog will be launched. Default is None.
"""
self.get_widget().change_history_depth(value=value)
def get_filename(self):
"""
Get current filename in combobox.
"""
return self.get_widget().get_filename()
def start_code_analysis(self, filename=None):
"""
Perform code analysis for given `filename`.
If `filename` is None default to current filename in combobox.
If this method is called while still running it will stop the code
analysis.
"""
editor = self.get_plugin(Plugins.Editor)
if editor:
if self.get_conf_option("save_before", True) and not editor.save():
return
if filename is None:
filename = self.get_widget().get_filename()
self.switch_to_plugin(force_focus=True)
self.get_widget().start_code_analysis(filename)
def stop_code_analysis(self):
"""
Stop the code analysis process.
"""
self.get_widget().stop_code_analysis()