def test_pylint_widget_pylintrc( pylint_test_script, pylintrc_files, mocker, qtbot): """Test that entire pylint widget gets results depending on pylintrc.""" search_paths, __, bad_names = pylintrc_files mocker.patch("pylint.config.os.path.expanduser", return_value=search_paths[HOME_DIR]) mocker.patch("spyder.plugins.pylint.widgets.pylintgui.getcwd_or_home", return_value=search_paths[WORKING_DIR]) mocker.patch("spyder.plugins.pylint.widgets.pylintgui.osp.expanduser", return_value=search_paths[HOME_DIR]) main_window = MainWindowMock() main_window.projects.get_active_project_path = mocker.MagicMock( return_value=search_paths[PROJECT_DIR]) pylint_sw = Pylint(parent=main_window) pylint_widget = PylintWidget(parent=pylint_sw) pylint_widget.analyze(filename=pylint_test_script) qtbot.waitUntil( lambda: pylint_widget.get_data(pylint_test_script)[1] is not None, timeout=5000) pylint_data = pylint_widget.get_data(filename=pylint_test_script) print(pylint_data) assert pylint_data conventions = pylint_data[1][3]["C:"] assert conventions assert len(conventions) == len(bad_names) assert all([sum([bad_name in message[2] for message in conventions]) == 1 for bad_name in bad_names])
def test_pylint_max_history_conf(pylint_test_script, mocker, qtbot): """Regression test for checking max_entries configuration. For further information see spyder-ide/spyder#12874 """ # Create the pylint widget for code analysis main_window = MainWindowMock() main_window.projects.get_active_project_path = mocker.MagicMock( return_value=None) pylint_sw = Pylint(parent=main_window) pylint_widget = PylintWidget(parent=pylint_sw) # Change the max_entry to 2 pylint_widget.parent.set_option('max_entries', 2) assert pylint_widget.parent.get_option('max_entries') == 2 # Analyze the test script with 1 as max_entry pylint_widget.analyze(filename=pylint_test_script) qtbot.waitUntil( lambda: pylint_widget.get_data(pylint_test_script)[1] is not None, timeout=5000) pylint_data = pylint_widget.get_data(filename=pylint_test_script) results = pylint_data[1][-1] max_entries = pylint_widget.parent.get_option('max_entries') for key in results: assert len(results[key]) <= max_entries
def test_pylint_widget_noproject(pylint_test_script, qtbot): """Test that pylint works without errors with no project open.""" pylint_widget = PylintWidget(parent=None) pylint_widget.analyze(filename=pylint_test_script) qtbot.waitUntil( lambda: pylint_widget.get_data(pylint_test_script)[1] is not None, timeout=5000) pylint_data = pylint_widget.get_data(filename=pylint_test_script) print(pylint_data) assert pylint_data assert pylint_data[0] is not None assert pylint_data[1] is not None
def test_pylint_widget_noproject(pylint_test_script, mocker, qtbot): """Test that pylint works without errors with no project open.""" main_window = MainWindowMock() main_window.projects.get_active_project_path = mocker.MagicMock( return_value=None) pylint_sw = Pylint(parent=main_window) pylint_widget = PylintWidget(parent=pylint_sw) pylint_widget.analyze(filename=pylint_test_script) qtbot.waitUntil( lambda: pylint_widget.get_data(pylint_test_script)[1] is not None, timeout=5000) pylint_data = pylint_widget.get_data(filename=pylint_test_script) print(pylint_data) assert pylint_data assert pylint_data[0] is not None assert pylint_data[1] is not None
class Pylint(SpyderPluginWidget): """Python source code analysis based on pylint.""" CONF_SECTION = 'pylint' CONFIGWIDGET_CLASS = PylintConfigPage CONF_FILE = False def __init__(self, parent=None): SpyderPluginWidget.__init__(self, parent) max_entries = self.get_option('max_entries', 50) self.pylint = PylintWidget(self, max_entries=max_entries, options_button=self.options_button, text_color=MAIN_TEXT_COLOR, prevrate_color=MAIN_PREVRATE_COLOR) layout = QVBoxLayout() layout.addWidget(self.pylint) self.setLayout(layout) # Add history_action to treewidget context menu history_action = create_action(self, _("History..."), None, ima.icon('history'), _("Set history maximum entries"), triggered=self.change_history_depth) self.pylint.treewidget.common_actions += (None, history_action) # Follow editorstacks tab change self.main.editor.sig_editor_focus_changed.connect(self.set_filename) # Used by Analyze button to check if file should be saved and start # analysis self.pylint.start_analysis.connect(self.run_pylint_from_analyze_button) #------ SpyderPluginWidget API -------------------------------------------- def get_plugin_title(self): """Return widget title""" return _("Code Analysis") def get_plugin_icon(self): """Return widget icon""" path = osp.join(self.PLUGIN_PATH, self.IMG_PATH) return ima.icon('pylint', icon_path=path) def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self.pylint.treewidget def get_plugin_actions(self): """Return a list of actions related to plugin""" return self.pylint.treewidget.get_menu_actions() def on_first_registration(self): """Action to be performed on first plugin registration""" self.tabify(self.main.help) self.dockwidget.hide() def register_plugin(self): """Register plugin in Spyder's main window""" self.pylint.treewidget.sig_edit_goto.connect(self.main.editor.load) self.pylint.redirect_stdio.connect( self.main.redirect_internalshell_stdio) self.add_dockwidget() pylint_act = create_action(self, _("Run static code analysis"), triggered=self.run_pylint) pylint_act.setEnabled(is_module_installed('pylint')) self.register_shortcut(pylint_act, context="Pylint", name="Run analysis") self.main.source_menu_actions += [MENU_SEPARATOR, pylint_act] self.main.editor.pythonfile_dependent_actions += [pylint_act] def refresh_plugin(self): """Refresh pylint widget""" self.pylint.remove_obsolete_items() def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" # The history depth option will be applied at # next Spyder startup, which is soon enough pass #------ Public API -------------------------------------------------------- @Slot() def change_history_depth(self): "Change history max entries""" depth, valid = QInputDialog.getInt(self, _('History'), _('Maximum entries'), self.get_option('max_entries'), 10, 10000) if valid: self.set_option('max_entries', depth) def get_filename(self): """Get current filename in combobox.""" return self.pylint.get_filename() @Slot() def set_filename(self): """Set filename without code analysis.""" self.pylint.set_filename(self.main.editor.get_current_filename()) @Slot() def run_pylint(self): """Run pylint code analysis""" if (self.get_option('save_before', True) and not self.main.editor.save()): return self.switch_to_plugin() self.analyze(self.main.editor.get_current_filename()) def analyze(self, filename): """Reimplement analyze method""" if self.dockwidget: self.switch_to_plugin() self.pylint.analyze(filename) @Slot() def run_pylint_from_analyze_button(self): """ See if file should and can be saved and run pylint code analysis. Does not check that file name is valid etc, so should only be used for Analyze button. """ if (self.get_option('save_before', True) and not self.main.editor.save()): return self.pylint.start()
class Pylint(SpyderPluginWidget): """Python source code analysis based on pylint.""" CONF_SECTION = 'pylint' CONFIGWIDGET_CLASS = PylintConfigPage def __init__(self, parent=None): SpyderPluginWidget.__init__(self, parent) max_entries = self.get_option('max_entries', 50) self.pylint = PylintWidget(self, max_entries=max_entries, options_button=self.options_button, text_color=MAIN_TEXT_COLOR, prevrate_color=MAIN_PREVRATE_COLOR) layout = QVBoxLayout() layout.addWidget(self.pylint) self.setLayout(layout) # Add history_action to treewidget context menu history_action = create_action(self, _("History..."), None, ima.icon('history'), _("Set history maximum entries"), triggered=self.change_history_depth) self.pylint.treewidget.common_actions += (None, history_action) # Initialize plugin self.initialize_plugin() #------ SpyderPluginWidget API -------------------------------------------- def get_plugin_title(self): """Return widget title""" return _("Static code analysis") def get_plugin_icon(self): """Return widget icon""" path = osp.join(self.PLUGIN_PATH, self.IMG_PATH) return ima.icon('pylint', icon_path=path) def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self.pylint.treewidget def get_plugin_actions(self): """Return a list of actions related to plugin""" return self.pylint.treewidget.get_menu_actions() def on_first_registration(self): """Action to be performed on first plugin registration""" self.main.tabify_plugins(self.main.help, self) self.dockwidget.hide() def register_plugin(self): """Register plugin in Spyder's main window""" self.pylint.treewidget.sig_edit_goto.connect(self.main.editor.load) self.pylint.redirect_stdio.connect( self.main.redirect_internalshell_stdio) self.main.add_dockwidget(self) pylint_act = create_action(self, _("Run static code analysis"), triggered=self.run_pylint) pylint_act.setEnabled(is_module_installed('pylint')) self.register_shortcut(pylint_act, context="Pylint", name="Run analysis") self.main.source_menu_actions += [MENU_SEPARATOR, pylint_act] self.main.editor.pythonfile_dependent_actions += [pylint_act] def refresh_plugin(self): """Refresh pylint widget""" self.pylint.remove_obsolete_items() def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" return True def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" # The history depth option will be applied at # next Spyder startup, which is soon enough pass #------ Public API -------------------------------------------------------- @Slot() def change_history_depth(self): "Change history max entries""" depth, valid = QInputDialog.getInt(self, _('History'), _('Maximum entries'), self.get_option('max_entries'), 10, 10000) if valid: self.set_option('max_entries', depth) @Slot() def run_pylint(self): """Run pylint code analysis""" if (self.get_option('save_before', True) and not self.main.editor.save()): return self.switch_to_plugin() self.analyze(self.main.editor.get_current_filename()) def analyze(self, filename): """Reimplement analyze method""" if self.dockwidget and not self.ismaximized: self.dockwidget.setVisible(True) self.dockwidget.setFocus() self.dockwidget.raise_() self.pylint.analyze(filename)