File: C:/Users/fred/anaconda3/Lib/site-packages/spyder/plugins/pylint/plugin.py
# -*- 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.
"""
# Third party imports
from qtpy.QtCore import Qt, Signal, Slot
# Local imports
from spyder.api.exceptions import SpyderAPIError
from spyder.api.plugins import Plugins, SpyderDockablePlugin
from spyder.api.plugin_registration.decorators import (
on_plugin_available, on_plugin_teardown)
from spyder.api.translations import _
from spyder.utils.programs import is_module_installed
from spyder.plugins.mainmenu.api import ApplicationMenus
from spyder.plugins.pylint.confpage import PylintConfigPage
from spyder.plugins.pylint.main_widget import PylintWidget
class PylintActions:
AnalyzeCurrentFile = 'run analysis'
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]
TABIFY = [Plugins.Help]
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.
"""
@staticmethod
def get_name():
return _("Code Analysis")
def get_description(self):
return _("Run Code Analysis.")
def get_icon(self):
return self.create_icon("pylint")
def on_initialize(self):
widget = self.get_widget()
# Expose widget signals at the plugin level
widget.sig_edit_goto_requested.connect(self.sig_edit_goto_requested)
widget.sig_start_analysis_requested.connect(self.start_code_analysis)
# Add action to application menus
pylint_act = self.create_action(
PylintActions.AnalyzeCurrentFile,
text=_("Run code analysis"),
tip=_("Run code analysis"),
icon=self.create_icon("pylint"),
triggered=self.start_code_analysis,
context=Qt.ApplicationShortcut,
register_shortcut=True
)
pylint_act.setEnabled(is_module_installed("pylint"))
@on_plugin_available(plugin=Plugins.Editor)
def on_editor_available(self):
widget = self.get_widget()
editor = self.get_plugin(Plugins.Editor)
# Connect to Editor
widget.sig_edit_goto_requested.connect(editor.load)
editor.sig_editor_focus_changed.connect(self._set_filename)
pylint_act = self.get_action(PylintActions.AnalyzeCurrentFile)
# TODO: use new API when editor has migrated
editor.pythonfile_dependent_actions += [pylint_act]
@on_plugin_available(plugin=Plugins.Preferences)
def on_preferences_available(self):
preferences = self.get_plugin(Plugins.Preferences)
preferences.register_plugin_preferences(self)
@on_plugin_available(plugin=Plugins.Projects)
def on_projects_available(self):
# Connect to projects
projects = self.get_plugin(Plugins.Projects)
projects.sig_project_loaded.connect(self._set_project_dir)
projects.sig_project_closed.connect(self._unset_project_dir)
@on_plugin_available(plugin=Plugins.MainMenu)
def on_main_menu_available(self):
mainmenu = self.get_plugin(Plugins.MainMenu)
pylint_act = self.get_action(PylintActions.AnalyzeCurrentFile)
mainmenu.add_item_to_application_menu(
pylint_act, menu_id=ApplicationMenus.Source)
@on_plugin_teardown(plugin=Plugins.Editor)
def on_editor_teardown(self):
widget = self.get_widget()
editor = self.get_plugin(Plugins.Editor)
# Connect to Editor
widget.sig_edit_goto_requested.disconnect(editor.load)
editor.sig_editor_focus_changed.disconnect(self._set_filename)
pylint_act = self.get_action(PylintActions.AnalyzeCurrentFile)
# TODO: use new API when editor has migrated
pylint_act.setVisible(False)
editor.pythonfile_dependent_actions.remove(pylint_act)
@on_plugin_teardown(plugin=Plugins.Preferences)
def on_preferences_teardown(self):
preferences = self.get_plugin(Plugins.Preferences)
preferences.deregister_plugin_preferences(self)
@on_plugin_teardown(plugin=Plugins.Projects)
def on_projects_teardown(self):
# Disconnect from projects
projects = self.get_plugin(Plugins.Projects)
projects.sig_project_loaded.disconnect(self._set_project_dir)
projects.sig_project_closed.disconnect(self._unset_project_dir)
@on_plugin_teardown(plugin=Plugins.MainMenu)
def on_main_menu_teardown(self):
mainmenu = self.get_plugin(Plugins.MainMenu)
mainmenu.remove_item_from_application_menu(
PylintActions.AnalyzeCurrentFile,
menu_id=ApplicationMenus.Source
)
# --- Private API
# ------------------------------------------------------------------------
@Slot()
def _set_filename(self):
"""
Set filename without code analysis.
"""
try:
editor = self.get_plugin(Plugins.Editor)
if editor:
self.get_widget().set_filename(editor.get_current_filename())
except SpyderAPIError:
# Editor was deleted
pass
def _set_project_dir(self, value):
widget = self.get_widget()
widget.set_conf("project_dir", value)
def _unset_project_dir(self, _unused):
widget = self.get_widget()
widget.set_conf("project_dir", None)
# --- 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()
@Slot()
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("save_before", True) and not editor.save():
return
if filename is None or isinstance(filename, bool):
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()