Sat, 28 Sep 2013 13:16:58 +0200
Prepared new plug-in release.
# -*- coding: utf-8 -*- # Copyright (c) 2005 - 2013 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing a dialog to configure the PyLint process """ from __future__ import unicode_literals # __IGNORE_WARNING__ try: str = unicode # __IGNORE_WARNING__ except (NameError): pass import os import copy from PyQt4.QtCore import pyqtSlot, QProcess, SIGNAL from PyQt4.QtGui import QDialog from E5Gui.E5Application import e5App from E5Gui import E5FileDialog, E5MessageBox from E5Gui.E5Completers import E5FileCompleter from .Ui_PyLintConfigDialog import Ui_PyLintConfigDialog import Preferences import Utilities class PyLintConfigDialog(QDialog, Ui_PyLintConfigDialog): """ Class implementing a dialog to configure the PyLint process """ def __init__(self, ppath, exe, parms, version): """ Constructor @param ppath project path (string or QString) Used to set the default path for the rcfile selection dialog @param exe name of the pylint executable (string) @param parms parameters to set in the dialog @param version pylint version (string) """ super(PyLintConfigDialog, self).__init__(None) self.setupUi(self) self.version = version self.pylintProc = None self.lint = exe self.__initializeDefaults() # get a copy of the defaults to store the user settings self.parameters = copy.deepcopy(self.defaults) # combine it with the values of parms if parms is not None: for key, value in parms.items(): self.parameters[key] = parms[key] self.configfileCompleter = E5FileCompleter(self.configfileEdit) self.reportfileCompleter = E5FileCompleter(self.reportfileEdit) # initialize general tab self.configfileEdit.setText(self.parameters['configFile']) self.txtOutputButton.setChecked(self.parameters['txtReport']) self.htmlOutputButton.setChecked(self.parameters['htmlReport']) self.dialogOutputButton.setChecked(self.parameters['dialogReport']) self.reportfileEdit.setText(self.parameters['reportFile']) # initialize checkers tab self.basicCheckBox.setChecked(self.parameters['enableBasic']) self.classesCheckBox.setChecked(self.parameters['enableClasses']) self.designCheckBox.setChecked(self.parameters['enableDesign']) self.exceptionsCheckBox.setChecked(self.parameters['enableExceptions']) self.formatCheckBox.setChecked(self.parameters['enableFormat']) self.importsCheckBox.setChecked(self.parameters['enableImports']) self.metricsCheckBox.setChecked(self.parameters['enableMetrics']) self.miscellaneousCheckBox.setChecked(self.parameters['enableMiscellaneous']) self.newstyleCheckBox.setChecked(self.parameters['enableNewstyle']) self.similaritiesCheckBox.setChecked(self.parameters['enableSimilarities']) self.typecheckCheckBox.setChecked(self.parameters['enableTypecheck']) self.variablesCheckBox.setChecked(self.parameters['enableVariables']) self.loggingCheckBox.setChecked(self.parameters['enableLogging']) self.stringFormatCheckBox.setChecked(self.parameters['enableStringFormat']) # initialize messages tab self.enabledMessagesEdit.setText(self.parameters['enabledMessages']) self.disabledMessagesEdit.setText(self.parameters['disabledMessages']) self.ppath = ppath def __initializeDefaults(self): """ Private method to set the default values. These are needed later on to generate the commandline parameters. """ self.defaults = { # general options 'configFile': '', 'reportFile': '', 'txtReport': False, 'htmlReport': True, 'dialogReport': False, # enabled checkers 'enableBasic': True, 'enableClasses': True, 'enableDesign': True, 'enableExceptions': True, 'enableFormat': False, 'enableImports': False, 'enableLogging': True, 'enableMetrics': True, 'enableMiscellaneous': True, 'enableNewstyle': True, 'enableSimilarities': True, 'enableStringFormat': True, 'enableTypecheck': True, 'enableVariables': True, # messages 'enabledMessages': '', 'disabledMessages': '', } def generateParameters(self): """ Public method that generates the commandline parameters. It generates a QStringList to be used to set the QProcess arguments for the pylint call and a list containing the non default parameters. The second list can be passed back upon object generation to overwrite the default settings. <b>Note</b>: The arguments list contains the name of the pylint executable as the first parameter. @return a tuple of the commandline parameters and non default parameters (list of strings, dictionary) """ parms = {} args = [] # 1. the program name args.append(self.lint) # 2. the commandline options # 2.1 general options if self.parameters['configFile'] != self.defaults['configFile']: parms['configFile'] = self.parameters['configFile'] args.append('--rcfile={0}'.format(self.parameters['configFile'])) parms['txtReport'] = self.parameters['txtReport'] parms['htmlReport'] = self.parameters['htmlReport'] parms['dialogReport'] = self.parameters['dialogReport'] if self.parameters['htmlReport']: args.append('--output-format=html') elif self.parameters['dialogReport']: args.append('--output-format=parseable') args.append('--report=n') else: args.append('--output-format=text') if self.parameters['reportFile'] != self.defaults['reportFile']: parms['reportFile'] = self.parameters['reportFile'] # 2.2 checkers options parms['enableBasic'] = self.parameters['enableBasic'] parms['enableClasses'] = self.parameters['enableClasses'] parms['enableDesign'] = self.parameters['enableDesign'] parms['enableExceptions'] = self.parameters['enableExceptions'] parms['enableFormat'] = self.parameters['enableFormat'] parms['enableImports'] = self.parameters['enableImports'] parms['enableMetrics'] = self.parameters['enableMetrics'] parms['enableMiscellaneous'] = self.parameters['enableMiscellaneous'] parms['enableNewstyle'] = self.parameters['enableNewstyle'] parms['enableSimilarities'] = self.parameters['enableSimilarities'] parms['enableTypecheck'] = self.parameters['enableTypecheck'] parms['enableVariables'] = self.parameters['enableVariables'] parms['enableLogging'] = self.parameters['enableLogging'] parms['enableStringFormat'] = self.parameters['enableStringFormat'] checkers = [] if self.parameters['enableBasic']: checkers.append('basic') if self.parameters['enableClasses']: checkers.append('classes') if self.parameters['enableDesign']: checkers.append('design') if self.parameters['enableExceptions']: checkers.append('exceptions') if self.parameters['enableFormat']: checkers.append('format') if self.parameters['enableImports']: checkers.append('imports') if self.parameters['enableMetrics']: checkers.append('metrics') if self.parameters['enableMiscellaneous']: checkers.append('miscellaneous') if self.parameters['enableNewstyle']: checkers.append('newstyle') if self.parameters['enableSimilarities']: checkers.append('similarities') if self.parameters['enableTypecheck']: checkers.append('typecheck') if self.parameters['enableVariables']: checkers.append('variables') if self.parameters['enableLogging']: checkers.append('logging') if self.parameters['enableStringFormat']: if self.version > '0.27.0': checkers.append('string') else: checkers.append('string_format') args.append('--disable=all') if checkers: args.append('--enable={0}'.format(','.join(checkers))) # 2.3 messages options parms['enabledMessages'] = self.parameters['enabledMessages'] parms['disabledMessages'] = self.parameters['disabledMessages'] if parms['enabledMessages']: args.append('--enable={0}'.format(parms['enabledMessages'])) if parms['disabledMessages']: args.append('--disable={0}'.format(parms['disabledMessages'])) return (args, parms) @pyqtSlot() def on_configfileButton_clicked(self): """ Private slot to select the configuration file. It displays a file selection dialog to select the configuration file. """ startWith = self.configfileEdit.text() if startWith == "": startWith = self.ppath config = E5FileDialog.getOpenFileName( self, self.trUtf8("Select configuration file"), startWith, self.trUtf8("Configuration Files (*.cfg *.cnf *.rc);;All Files (*)")) if config: self.configfileEdit.setText(Utilities.toNativeSeparators(config)) @pyqtSlot() def on_reportfileButton_clicked(self): """ Private slot to select the report file. It displays a file selection dialog to select the report file. """ report = E5FileDialog.getSaveFileName( self, self.trUtf8("Select report file"), self.reportfileEdit.text(), None, None, E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)) if report: self.reportfileEdit.setText(Utilities.toNativeSeparators(report)) def accept(self): """ Protected slot called by the Ok button. It saves the values in the parameters dictionary. """ # get data of general tab self.parameters['configFile'] = self.configfileEdit.text() self.parameters['txtReport'] = self.txtOutputButton.isChecked() self.parameters['htmlReport'] = self.htmlOutputButton.isChecked() self.parameters['dialogReport'] = self.dialogOutputButton.isChecked() self.parameters['reportFile'] = self.reportfileEdit.text() # get data of checkers tab self.parameters['enableBasic'] = self.basicCheckBox.isChecked() self.parameters['enableClasses'] = self.classesCheckBox.isChecked() self.parameters['enableDesign'] = self.designCheckBox.isChecked() self.parameters['enableExceptions'] = self.exceptionsCheckBox.isChecked() self.parameters['enableFormat'] = self.formatCheckBox.isChecked() self.parameters['enableImports'] = self.importsCheckBox.isChecked() self.parameters['enableMetrics'] = self.metricsCheckBox.isChecked() self.parameters['enableMiscellaneous'] = self.miscellaneousCheckBox.isChecked() self.parameters['enableNewstyle'] = self.newstyleCheckBox.isChecked() self.parameters['enableSimilarities'] = self.similaritiesCheckBox.isChecked() self.parameters['enableTypecheck'] = self.typecheckCheckBox.isChecked() self.parameters['enableVariables'] = self.variablesCheckBox.isChecked() self.parameters['enableLogging'] = self.loggingCheckBox.isChecked() self.parameters['enableStringFormat'] = self.stringFormatCheckBox.isChecked() # get data of messages tab self.parameters['enabledMessages'] = ','.join( [m.strip() for m in self.enabledMessagesEdit.text().split(',')]) self.parameters['disabledMessages'] = ','.join( [m.strip() for m in self.disabledMessagesEdit.text().split(',')]) # call the accept slot of the base class super(PyLintConfigDialog, self).accept() ############################################################################ ## Methods below are needed to generate a configuration file template ############################################################################ @pyqtSlot() def on_configButton_clicked(self): """ Public slot to handle the generation of a sample configuration. """ self.buf = "" self.pylintProc = QProcess() args = [] self.__ioEncoding = Preferences.getSystem("IOEncoding") args.append('--generate-rcfile') self.pylintProc.readyReadStandardOutput.connect(self.__readStdout) self.pylintProc.readyReadStandardError.connect(self.__readStderr) self.pylintProc.finished.connect(self.__createConfigDone) self.pylintProc.start(self.lint, args) procStarted = self.pylintProc.waitForStarted() if procStarted: e5App().getObject("ViewManager").enableEditorsCheckFocusIn(False) else: E5MessageBox.critical(self, self.trUtf8('Process Generation Error'), self.trUtf8( 'Could not start {0}.<br>' 'Ensure that it is in the search path.' ).format(self.lint)) def __createConfigDone(self, exitCode, exitStatus): """ Private slot to handle the the finished signal of the pylint process. @param exitCode exit code of the process (integer) @param exitStatus exit status of the process (QProcess.ExitStatus) """ vm = e5App().getObject("ViewManager") vm.enableEditorsCheckFocusIn(True) if exitStatus == QProcess.NormalExit and exitCode == 0: vm.newEditor() aw = vm.activeWindow() aw.insertAt(self.buf, 0, 0) aw.setLanguage('dummy.rc') self.reject() def __readStdout(self): """ Private slot to handle the readyReadStandardOutput signal of the pylint process. """ if self.pylintProc is None: return self.pylintProc.setReadChannel(QProcess.StandardOutput) while self.pylintProc and self.pylintProc.canReadLine(): line = str(self.pylintProc.readLine(), self.__ioEncoding, "replace").rstrip() self.buf += line + os.linesep def __readStderr(self): """ Private slot to handle the readyReadStandardError signal of the pylint process. """ if self.pylintProc is None: return self.pylintProc.setReadChannel(QProcess.StandardError) while self.pylintProc and self.pylintProc.canReadLine(): s = 'pylint: ' + str( self.pylintProc.readLine(), self.__ioEncoding, "replace") e5App().getObject("UserInterface").emit(SIGNAL('appendStderr'), s)