PluginPyLint.py

branch
eric7
changeset 107
3bd2806a6ada
parent 105
ab6d2ee7171e
child 108
b452f300e6c7
equal deleted inserted replaced
106:40db039eb51f 107:3bd2806a6ada
48 48
49 49
50 def exeDisplayDataList(): 50 def exeDisplayDataList():
51 """ 51 """
52 Public method to support the display of some executable info. 52 Public method to support the display of some executable info.
53 53
54 @return list of dictionaries containing the data to query the presence of 54 @return list of dictionaries containing the data to query the presence of
55 the executable 55 the executable
56 @rtype list of dict 56 @rtype list of dict
57 """ 57 """
58 dataList = [] 58 dataList = []
59 data = { 59 data = {
60 "programEntry": True, 60 "programEntry": True,
61 "header": QCoreApplication.translate( 61 "header": QCoreApplication.translate("PyLintPlugin", "Checkers - Pylint"),
62 "PyLintPlugin", "Checkers - Pylint"), 62 "exe": "dummypylint",
63 "exe": 'dummypylint', 63 "versionCommand": "--version",
64 "versionCommand": '--version', 64 "versionStartsWith": "dummypylint",
65 "versionStartsWith": 'dummypylint',
66 "versionPosition": -1, 65 "versionPosition": -1,
67 "version": "", 66 "version": "",
68 "versionCleanup": None, 67 "versionCleanup": None,
69 } 68 }
70 if _checkProgram(): 69 if _checkProgram():
79 78
80 79
81 def __getProgramVersion(exe): 80 def __getProgramVersion(exe):
82 """ 81 """
83 Private method to generate a program entry. 82 Private method to generate a program entry.
84 83
85 @param exe name of the executable program 84 @param exe name of the executable program
86 @type str 85 @type str
87 @return version string of detected version 86 @return version string of detected version
88 @rtype str 87 @rtype str
89 """ 88 """
90 proc = QProcess() 89 proc = QProcess()
91 proc.setProcessChannelMode(QProcess.ProcessChannelMode.MergedChannels) 90 proc.setProcessChannelMode(QProcess.ProcessChannelMode.MergedChannels)
92 proc.start(exe, ['--version']) 91 proc.start(exe, ["--version"])
93 finished = proc.waitForFinished(10000) 92 finished = proc.waitForFinished(10000)
94 if finished: 93 if finished:
95 output = str(proc.readAllStandardOutput(), 94 output = str(
96 Preferences.getSystem("IOEncoding"), 95 proc.readAllStandardOutput(), Preferences.getSystem("IOEncoding"), "replace"
97 'replace') 96 )
98 versionRe = re.compile('^pylint', re.UNICODE) 97 versionRe = re.compile("^pylint", re.UNICODE)
99 for line in output.splitlines(): 98 for line in output.splitlines():
100 if versionRe.search(line): 99 if versionRe.search(line):
101 return line.split()[-1] 100 return line.split()[-1]
102 101
103 return '0.0.0' 102 return "0.0.0"
104 103
105 104
106 def _findExecutable(majorVersion): 105 def _findExecutable(majorVersion):
107 """ 106 """
108 Restricted function to determine the name and path of the executable. 107 Restricted function to determine the name and path of the executable.
109 108
110 @param majorVersion major python version of the executables 109 @param majorVersion major python version of the executables
111 @type int 110 @type int
112 @return path name of the executable 111 @return path name of the executable
113 @rtype str 112 @rtype str
114 """ 113 """
115 # Determine Python Version 114 # Determine Python Version
116 if majorVersion == 3: 115 if majorVersion == 3:
117 minorVersions = range(10) 116 minorVersions = range(10)
118 else: 117 else:
119 return [] 118 return []
120 119
121 executables = set() 120 executables = set()
122 if Utilities.isWindowsPlatform(): 121 if Utilities.isWindowsPlatform():
123 # 122 #
124 # Windows 123 # Windows
125 # 124 #
126 try: 125 try:
127 import winreg 126 import winreg
128 except ImportError: 127 except ImportError:
129 import _winreg as winreg # __IGNORE_WARNING__ 128 import _winreg as winreg # __IGNORE_WARNING__
130 129
131 def getExePath(branch, access, versionStr): 130 def getExePath(branch, access, versionStr):
132 exes = [] 131 exes = []
133 with contextlib.suppress(WindowsError, OSError): 132 with contextlib.suppress(WindowsError, OSError):
134 software = winreg.OpenKey(branch, 'Software', 0, access) 133 software = winreg.OpenKey(branch, "Software", 0, access)
135 python = winreg.OpenKey(software, 'Python', 0, access) 134 python = winreg.OpenKey(software, "Python", 0, access)
136 pcore = winreg.OpenKey(python, 'PythonCore', 0, access) 135 pcore = winreg.OpenKey(python, "PythonCore", 0, access)
137 version = winreg.OpenKey(pcore, versionStr, 0, access) 136 version = winreg.OpenKey(pcore, versionStr, 0, access)
138 installpath = winreg.QueryValue(version, 'InstallPath') 137 installpath = winreg.QueryValue(version, "InstallPath")
139 # Look for the batch script variant 138 # Look for the batch script variant
140 exe = os.path.join(installpath, 'Scripts', 'pylint.bat') 139 exe = os.path.join(installpath, "Scripts", "pylint.bat")
141 if os.access(exe, os.X_OK): 140 if os.access(exe, os.X_OK):
142 exes.append(exe) 141 exes.append(exe)
143 # Look for the executable variant 142 # Look for the executable variant
144 exe = os.path.join(installpath, 'Scripts', 'pylint.exe') 143 exe = os.path.join(installpath, "Scripts", "pylint.exe")
145 if os.access(exe, os.X_OK): 144 if os.access(exe, os.X_OK):
146 exes.append(exe) 145 exes.append(exe)
147 return exes 146 return exes
148 147
149 versionSuffixes = ["", "-32", "-64"] 148 versionSuffixes = ["", "-32", "-64"]
150 for minorVersion in minorVersions: 149 for minorVersion in minorVersions:
151 for versionSuffix in versionSuffixes: 150 for versionSuffix in versionSuffixes:
152 versionStr = '{0}.{1}{2}'.format(majorVersion, minorVersion, 151 versionStr = "{0}.{1}{2}".format(
153 versionSuffix) 152 majorVersion, minorVersion, versionSuffix
153 )
154 exePaths = getExePath( 154 exePaths = getExePath(
155 winreg.HKEY_CURRENT_USER, 155 winreg.HKEY_CURRENT_USER,
156 winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr) 156 winreg.KEY_WOW64_32KEY | winreg.KEY_READ,
157 versionStr,
158 )
157 if exePaths: 159 if exePaths:
158 for exePath in exePaths: 160 for exePath in exePaths:
159 executables.add(exePath) 161 executables.add(exePath)
160 162
161 exePaths = getExePath( 163 exePaths = getExePath(
162 winreg.HKEY_LOCAL_MACHINE, 164 winreg.HKEY_LOCAL_MACHINE,
163 winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr) 165 winreg.KEY_WOW64_32KEY | winreg.KEY_READ,
166 versionStr,
167 )
164 if exePaths: 168 if exePaths:
165 for exePath in exePaths: 169 for exePath in exePaths:
166 executables.add(exePath) 170 executables.add(exePath)
167 171
168 # Even on Intel 64-bit machines it's 'AMD64' 172 # Even on Intel 64-bit machines it's 'AMD64'
169 if platform.machine() == 'AMD64': 173 if platform.machine() == "AMD64":
170 exePaths = getExePath( 174 exePaths = getExePath(
171 winreg.HKEY_CURRENT_USER, 175 winreg.HKEY_CURRENT_USER,
172 winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr) 176 winreg.KEY_WOW64_64KEY | winreg.KEY_READ,
177 versionStr,
178 )
173 if exePaths: 179 if exePaths:
174 for exePath in exePaths: 180 for exePath in exePaths:
175 executables.add(exePath) 181 executables.add(exePath)
176 182
177 exePaths = getExePath( 183 exePaths = getExePath(
178 winreg.HKEY_LOCAL_MACHINE, 184 winreg.HKEY_LOCAL_MACHINE,
179 winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr) 185 winreg.KEY_WOW64_64KEY | winreg.KEY_READ,
186 versionStr,
187 )
180 if exePaths: 188 if exePaths:
181 for exePath in exePaths: 189 for exePath in exePaths:
182 executables.add(exePath) 190 executables.add(exePath)
183 191
184 if not executables and majorVersion >= 3: 192 if not executables and majorVersion >= 3:
185 # check the PATH environment variable if nothing was found 193 # check the PATH environment variable if nothing was found
186 # Python 3 only 194 # Python 3 only
187 path = Utilities.getEnvironmentEntry('PATH') 195 path = Utilities.getEnvironmentEntry("PATH")
188 if path: 196 if path:
189 dirs = path.split(os.pathsep) 197 dirs = path.split(os.pathsep)
190 for directory in dirs: 198 for directory in dirs:
191 for suffix in (".bat", ".exe"): 199 for suffix in (".bat", ".exe"):
192 exe = os.path.join(directory, "pylint" + suffix) 200 exe = os.path.join(directory, "pylint" + suffix)
193 if os.access(exe, os.X_OK): 201 if os.access(exe, os.X_OK):
194 executables.add(exe) 202 executables.add(exe)
195 else: 203 else:
196 # 204 #
197 # Linux, Unix ... 205 # Linux, Unix ...
198 pylintScript = 'pylint' 206 pylintScript = "pylint"
199 scriptSuffixes = ["", 207 scriptSuffixes = [
200 "-python{0}".format(majorVersion), 208 "",
201 "{0}".format(majorVersion), 209 "-python{0}".format(majorVersion),
202 ] 210 "{0}".format(majorVersion),
211 ]
203 for minorVersion in minorVersions: 212 for minorVersion in minorVersions:
204 scriptSuffixes.append( 213 scriptSuffixes.append("-python{0}.{1}".format(majorVersion, minorVersion))
205 "-python{0}.{1}".format(majorVersion, minorVersion))
206 # There could be multiple pylint executables in the path 214 # There could be multiple pylint executables in the path
207 # e.g. for different python variants 215 # e.g. for different python variants
208 path = Utilities.getEnvironmentEntry('PATH') 216 path = Utilities.getEnvironmentEntry("PATH")
209 # environment variable not defined 217 # environment variable not defined
210 if path is None: 218 if path is None:
211 return [] 219 return []
212 220
213 # step 1: determine possible candidates 221 # step 1: determine possible candidates
214 exes = [] 222 exes = []
215 dirs = path.split(os.pathsep) 223 dirs = path.split(os.pathsep)
216 for directory in dirs: 224 for directory in dirs:
217 for suffix in scriptSuffixes: 225 for suffix in scriptSuffixes:
218 exe = os.path.join(directory, pylintScript + suffix) 226 exe = os.path.join(directory, pylintScript + suffix)
219 if os.access(exe, os.X_OK): 227 if os.access(exe, os.X_OK):
220 exes.append(exe) 228 exes.append(exe)
221 229
222 # step 2: determine the Python variant 230 # step 2: determine the Python variant
223 _exePy3 = set() 231 _exePy3 = set()
224 versionArgs = ["-c", "import sys; print(sys.version_info[0])"] 232 versionArgs = ["-c", "import sys; print(sys.version_info[0])"]
225 for exe in exes: 233 for exe in exes:
226 with open(exe, "r") as f: 234 with open(exe, "r") as f:
229 process = QProcess() 237 process = QProcess()
230 process.start(program, versionArgs) 238 process.start(program, versionArgs)
231 process.waitForFinished(5000) 239 process.waitForFinished(5000)
232 # get a QByteArray of the output 240 # get a QByteArray of the output
233 versionBytes = process.readAllStandardOutput() 241 versionBytes = process.readAllStandardOutput()
234 versionStr = str(versionBytes, encoding='utf-8').strip() 242 versionStr = str(versionBytes, encoding="utf-8").strip()
235 if versionStr == "3": 243 if versionStr == "3":
236 _exePy3.add(exe) 244 _exePy3.add(exe)
237 245
238 executables = _exePy3 246 executables = _exePy3
239 247
240 # Find the executable with the highest version number 248 # Find the executable with the highest version number
241 maxVersion = '0.0.0' 249 maxVersion = "0.0.0"
242 maxExe = '' 250 maxExe = ""
243 for executable in list(executables): 251 for executable in list(executables):
244 version = __getProgramVersion(executable) 252 version = __getProgramVersion(executable)
245 if version > maxVersion: 253 if version > maxVersion:
246 maxVersion = version 254 maxVersion = version
247 maxExe = executable 255 maxExe = executable
250 258
251 259
252 def _checkProgram(): 260 def _checkProgram():
253 """ 261 """
254 Restricted function to check the availability of pylint. 262 Restricted function to check the availability of pylint.
255 263
256 @return flag indicating availability 264 @return flag indicating availability
257 @rtype bool 265 @rtype bool
258 """ 266 """
259 global error, exePy3 267 global error, exePy3
260 268
261 exePy3 = _findExecutable(3) 269 exePy3 = _findExecutable(3)
262 if exePy3[0] == '': 270 if exePy3[0] == "":
263 error = QCoreApplication.translate( 271 error = QCoreApplication.translate(
264 "PyLintPlugin", "The pylint executable could not be found.") 272 "PyLintPlugin", "The pylint executable could not be found."
273 )
265 return False 274 return False
266 else: 275 else:
267 return True 276 return True
268 277
269 278
270 class PyLintPlugin(QObject): 279 class PyLintPlugin(QObject):
271 """ 280 """
272 Class implementing the PyLint plug-in. 281 Class implementing the PyLint plug-in.
273 """ 282 """
283
274 def __init__(self, ui): 284 def __init__(self, ui):
275 """ 285 """
276 Constructor 286 Constructor
277 287
278 @param ui reference to the user interface object 288 @param ui reference to the user interface object
279 @type UserInterface 289 @type UserInterface
280 """ 290 """
281 QObject.__init__(self, ui) 291 QObject.__init__(self, ui)
282 self.__ui = ui 292 self.__ui = ui
283 self.__initialize() 293 self.__initialize()
284 294
285 self.__translator = None 295 self.__translator = None
286 self.__loadTranslator() 296 self.__loadTranslator()
287 297
288 def __initialize(self): 298 def __initialize(self):
289 """ 299 """
290 Private slot to (re)initialize the plugin. 300 Private slot to (re)initialize the plugin.
291 """ 301 """
292 self.__projectAct = None 302 self.__projectAct = None
293 self.__projectShowAct = None 303 self.__projectShowAct = None
294 self.__pylintPDialog = None 304 self.__pylintPDialog = None
295 305
296 self.__projectBrowserAct = None 306 self.__projectBrowserAct = None
297 self.__projectBrowserShowAct = None 307 self.__projectBrowserShowAct = None
298 self.__projectBrowserMenu = None 308 self.__projectBrowserMenu = None
299 self.__pylintPsbDialog = None 309 self.__pylintPsbDialog = None
300 310
301 self.__editors = [] 311 self.__editors = []
302 self.__editorAct = None 312 self.__editorAct = None
303 self.__editorPylintDialog = None 313 self.__editorPylintDialog = None
304 self.__editorParms = None 314 self.__editorParms = None
305 315
306 def activate(self): 316 def activate(self):
307 """ 317 """
308 Public method to activate this plugin. 318 Public method to activate this plugin.
309 319
310 @return tuple of None and activation status 320 @return tuple of None and activation status
311 @rtype tuple of (None, bool) 321 @rtype tuple of (None, bool)
312 """ 322 """
313 global error 323 global error
314 324
315 # There is already an error, don't activate 325 # There is already an error, don't activate
316 if error: 326 if error:
317 return None, False 327 return None, False
318 # pylint is only activated if it is available 328 # pylint is only activated if it is available
319 if not _checkProgram(): 329 if not _checkProgram():
320 return None, False 330 return None, False
321 331
322 menu = ericApp().getObject("Project").getMenu("Checks") 332 menu = ericApp().getObject("Project").getMenu("Checks")
323 if menu: 333 if menu:
324 self.__projectAct = EricAction( 334 self.__projectAct = EricAction(
325 self.tr('Run PyLint'), 335 self.tr("Run PyLint"),
326 self.tr('Run &PyLint...'), 0, 0, 336 self.tr("Run &PyLint..."),
327 self, 'project_check_pylint') 337 0,
338 0,
339 self,
340 "project_check_pylint",
341 )
328 self.__projectAct.setStatusTip( 342 self.__projectAct.setStatusTip(
329 self.tr('Check project, packages or modules with pylint.')) 343 self.tr("Check project, packages or modules with pylint.")
330 self.__projectAct.setWhatsThis(self.tr( 344 )
331 """<b>Run PyLint...</b>""" 345 self.__projectAct.setWhatsThis(
332 """<p>This checks the project, packages or modules using""" 346 self.tr(
333 """ pylint.</p>""" 347 """<b>Run PyLint...</b>"""
334 )) 348 """<p>This checks the project, packages or modules using"""
349 """ pylint.</p>"""
350 )
351 )
335 self.__projectAct.triggered.connect(self.__projectPylint) 352 self.__projectAct.triggered.connect(self.__projectPylint)
336 ericApp().getObject("Project").addEricActions([self.__projectAct]) 353 ericApp().getObject("Project").addEricActions([self.__projectAct])
337 menu.addAction(self.__projectAct) 354 menu.addAction(self.__projectAct)
338 355
339 self.__projectShowAct = EricAction( 356 self.__projectShowAct = EricAction(
340 self.tr('Show PyLint Dialog'), 357 self.tr("Show PyLint Dialog"),
341 self.tr('Show Py&Lint Dialog...'), 0, 0, 358 self.tr("Show Py&Lint Dialog..."),
342 self, 'project_check_pylintshow') 359 0,
343 self.__projectShowAct.setStatusTip(self.tr( 360 0,
344 'Show the PyLint dialog with the results of the last run.')) 361 self,
345 self.__projectShowAct.setWhatsThis(self.tr( 362 "project_check_pylintshow",
346 """<b>Show PyLint Dialog...</b>""" 363 )
347 """<p>This shows the PyLint dialog with the results""" 364 self.__projectShowAct.setStatusTip(
348 """ of the last run.</p>""" 365 self.tr("Show the PyLint dialog with the results of the last run.")
349 )) 366 )
350 self.__projectShowAct.triggered.connect( 367 self.__projectShowAct.setWhatsThis(
351 self.__projectPylintShow) 368 self.tr(
352 ericApp().getObject("Project").addEricActions( 369 """<b>Show PyLint Dialog...</b>"""
353 [self.__projectShowAct]) 370 """<p>This shows the PyLint dialog with the results"""
371 """ of the last run.</p>"""
372 )
373 )
374 self.__projectShowAct.triggered.connect(self.__projectPylintShow)
375 ericApp().getObject("Project").addEricActions([self.__projectShowAct])
354 menu.addAction(self.__projectShowAct) 376 menu.addAction(self.__projectShowAct)
355 377
356 self.__editorAct = EricAction( 378 self.__editorAct = EricAction(
357 self.tr('Run PyLint'), 379 self.tr("Run PyLint"), self.tr("Run &PyLint..."), 0, 0, self, ""
358 self.tr('Run &PyLint...'), 0, 0, 380 )
359 self, "") 381 self.__editorAct.setWhatsThis(
360 self.__editorAct.setWhatsThis(self.tr( 382 self.tr(
361 """<b>Run PyLint...</b>""" 383 """<b>Run PyLint...</b>"""
362 """<p>This checks the loaded module using pylint.</p>""" 384 """<p>This checks the loaded module using pylint.</p>"""
363 )) 385 )
386 )
364 self.__editorAct.triggered.connect(self.__editorPylint) 387 self.__editorAct.triggered.connect(self.__editorPylint)
365 388
366 ericApp().getObject("Project").showMenu.connect(self.__projectShowMenu) 389 ericApp().getObject("Project").showMenu.connect(self.__projectShowMenu)
367 ericApp().getObject("ProjectBrowser").getProjectBrowser( 390 ericApp().getObject("ProjectBrowser").getProjectBrowser(
368 "sources").showMenu.connect(self.__projectBrowserShowMenu) 391 "sources"
369 ericApp().getObject("ViewManager").editorOpenedEd.connect( 392 ).showMenu.connect(self.__projectBrowserShowMenu)
370 self.__editorOpened) 393 ericApp().getObject("ViewManager").editorOpenedEd.connect(self.__editorOpened)
371 ericApp().getObject("ViewManager").editorClosedEd.connect( 394 ericApp().getObject("ViewManager").editorClosedEd.connect(self.__editorClosed)
372 self.__editorClosed) 395
373
374 for editor in ericApp().getObject("ViewManager").getOpenEditors(): 396 for editor in ericApp().getObject("ViewManager").getOpenEditors():
375 self.__editorOpened(editor) 397 self.__editorOpened(editor)
376 398
377 error = "" 399 error = ""
378 return None, True 400 return None, True
379 401
380 def deactivate(self): 402 def deactivate(self):
381 """ 403 """
382 Public method to deactivate this plugin. 404 Public method to deactivate this plugin.
383 """ 405 """
384 ericApp().getObject("Project").showMenu.disconnect( 406 ericApp().getObject("Project").showMenu.disconnect(self.__projectShowMenu)
385 self.__projectShowMenu)
386 ericApp().getObject("ProjectBrowser").getProjectBrowser( 407 ericApp().getObject("ProjectBrowser").getProjectBrowser(
387 "sources").showMenu.disconnect(self.__projectBrowserShowMenu) 408 "sources"
409 ).showMenu.disconnect(self.__projectBrowserShowMenu)
388 ericApp().getObject("ViewManager").editorOpenedEd.disconnect( 410 ericApp().getObject("ViewManager").editorOpenedEd.disconnect(
389 self.__editorOpened) 411 self.__editorOpened
412 )
390 ericApp().getObject("ViewManager").editorClosedEd.disconnect( 413 ericApp().getObject("ViewManager").editorClosedEd.disconnect(
391 self.__editorClosed) 414 self.__editorClosed
392 415 )
416
393 menu = ericApp().getObject("Project").getMenu("Checks") 417 menu = ericApp().getObject("Project").getMenu("Checks")
394 if menu: 418 if menu:
395 if self.__projectAct: 419 if self.__projectAct:
396 menu.removeAction(self.__projectAct) 420 menu.removeAction(self.__projectAct)
397 ericApp().getObject("Project").removeEricActions( 421 ericApp().getObject("Project").removeEricActions([self.__projectAct])
398 [self.__projectAct])
399 if self.__projectShowAct: 422 if self.__projectShowAct:
400 menu.removeAction(self.__projectShowAct) 423 menu.removeAction(self.__projectShowAct)
401 ericApp().getObject("Project").removeEricActions( 424 ericApp().getObject("Project").removeEricActions(
402 [self.__projectShowAct]) 425 [self.__projectShowAct]
403 426 )
427
404 if self.__projectBrowserMenu: 428 if self.__projectBrowserMenu:
405 if self.__projectBrowserAct: 429 if self.__projectBrowserAct:
406 self.__projectBrowserMenu.removeAction( 430 self.__projectBrowserMenu.removeAction(self.__projectBrowserAct)
407 self.__projectBrowserAct)
408 if self.__projectBrowserShowAct: 431 if self.__projectBrowserShowAct:
409 self.__projectBrowserMenu.removeAction( 432 self.__projectBrowserMenu.removeAction(self.__projectBrowserShowAct)
410 self.__projectBrowserShowAct) 433
411
412 for editor in self.__editors: 434 for editor in self.__editors:
413 editor.showMenu.disconnect(self.__editorShowMenu) 435 editor.showMenu.disconnect(self.__editorShowMenu)
414 menu = editor.getMenu("Checks") 436 menu = editor.getMenu("Checks")
415 if menu is not None: 437 if menu is not None:
416 menu.removeAction(self.__editorAct) 438 menu.removeAction(self.__editorAct)
417 439
418 self.__initialize() 440 self.__initialize()
419 441
420 def __loadTranslator(self): 442 def __loadTranslator(self):
421 """ 443 """
422 Private method to load the translation file. 444 Private method to load the translation file.
423 """ 445 """
424 if self.__ui is not None: 446 if self.__ui is not None:
425 loc = self.__ui.getLocale() 447 loc = self.__ui.getLocale()
426 if loc and loc != "C": 448 if loc and loc != "C":
427 locale_dir = os.path.join(os.path.dirname(__file__), 449 locale_dir = os.path.join(
428 "PyLintInterface", "i18n") 450 os.path.dirname(__file__), "PyLintInterface", "i18n"
451 )
429 translation = "pylint_{0}".format(loc) 452 translation = "pylint_{0}".format(loc)
430 translator = QTranslator(None) 453 translator = QTranslator(None)
431 loaded = translator.load(translation, locale_dir) 454 loaded = translator.load(translation, locale_dir)
432 if loaded: 455 if loaded:
433 self.__translator = translator 456 self.__translator = translator
434 ericApp().installTranslator(self.__translator) 457 ericApp().installTranslator(self.__translator)
435 else: 458 else:
436 print("Warning: translation file '{0}' could not be" 459 print(
437 " loaded.".format(translation)) 460 "Warning: translation file '{0}' could not be"
461 " loaded.".format(translation)
462 )
438 print("Using default.") 463 print("Using default.")
439 464
440 def __projectShowMenu(self, menuName, menu): 465 def __projectShowMenu(self, menuName, menu):
441 """ 466 """
442 Private slot called, when the the project menu or a submenu is 467 Private slot called, when the the project menu or a submenu is
443 about to be shown. 468 about to be shown.
444 469
445 @param menuName name of the menu to be shown 470 @param menuName name of the menu to be shown
446 @type str 471 @type str
447 @param menu reference to the menu 472 @param menu reference to the menu
448 @type QMenu 473 @type QMenu
449 """ 474 """
452 if self.__projectAct is not None: 477 if self.__projectAct is not None:
453 self.__projectAct.setEnabled(lang.startswith("Python")) 478 self.__projectAct.setEnabled(lang.startswith("Python"))
454 if self.__projectShowAct is not None: 479 if self.__projectShowAct is not None:
455 self.__projectShowAct.setEnabled(lang.startswith("Python")) 480 self.__projectShowAct.setEnabled(lang.startswith("Python"))
456 self.__projectShowAct.setEnabled(self.__pylintPDialog is not None) 481 self.__projectShowAct.setEnabled(self.__pylintPDialog is not None)
457 482
458 def __projectBrowserShowMenu(self, menuName, menu): 483 def __projectBrowserShowMenu(self, menuName, menu):
459 """ 484 """
460 Private slot called, when the the project browser menu or a submenu is 485 Private slot called, when the the project browser menu or a submenu is
461 about to be shown. 486 about to be shown.
462 487
463 @param menuName name of the menu to be shown 488 @param menuName name of the menu to be shown
464 @type str 489 @type str
465 @param menu reference to the menu 490 @param menu reference to the menu
466 @type QMenu 491 @type QMenu
467 """ 492 """
468 if ( 493 if menuName == "Checks" and ericApp().getObject(
469 menuName == "Checks" and 494 "Project"
470 ericApp().getObject("Project").getProjectLanguage() 495 ).getProjectLanguage().startswith("Python"):
471 .startswith("Python")
472 ):
473 self.__projectBrowserMenu = menu 496 self.__projectBrowserMenu = menu
474 if self.__projectBrowserAct is None: 497 if self.__projectBrowserAct is None:
475 self.__projectBrowserAct = EricAction( 498 self.__projectBrowserAct = EricAction(
476 self.tr('Run PyLint'), 499 self.tr("Run PyLint"), self.tr("Run &PyLint..."), 0, 0, self, ""
477 self.tr('Run &PyLint...'), 0, 0, 500 )
478 self, '') 501 self.__projectBrowserAct.setWhatsThis(
479 self.__projectBrowserAct.setWhatsThis(self.tr( 502 self.tr(
480 """<b>Run PyLint...</b>""" 503 """<b>Run PyLint...</b>"""
481 """<p>This checks the project, packages or modules""" 504 """<p>This checks the project, packages or modules"""
482 """ using pylint.</p>""" 505 """ using pylint.</p>"""
483 )) 506 )
484 self.__projectBrowserAct.triggered.connect( 507 )
485 self.__projectBrowserPylint) 508 self.__projectBrowserAct.triggered.connect(self.__projectBrowserPylint)
486 509
487 if self.__projectBrowserShowAct is None: 510 if self.__projectBrowserShowAct is None:
488 self.__projectBrowserShowAct = EricAction( 511 self.__projectBrowserShowAct = EricAction(
489 self.tr('Show PyLint Dialog'), 512 self.tr("Show PyLint Dialog"),
490 self.tr('Show Py&Lint Dialog...'), 0, 0, 513 self.tr("Show Py&Lint Dialog..."),
491 self, '') 514 0,
492 self.__projectBrowserShowAct.setWhatsThis(self.tr( 515 0,
493 """<b>Show PyLint Dialog...</b>""" 516 self,
494 """<p>This shows the PyLint dialog with the results""" 517 "",
495 """ of the last run.</p>""" 518 )
496 )) 519 self.__projectBrowserShowAct.setWhatsThis(
520 self.tr(
521 """<b>Show PyLint Dialog...</b>"""
522 """<p>This shows the PyLint dialog with the results"""
523 """ of the last run.</p>"""
524 )
525 )
497 self.__projectBrowserShowAct.triggered.connect( 526 self.__projectBrowserShowAct.triggered.connect(
498 self.__projectBrowserPylintShow) 527 self.__projectBrowserPylintShow
499 528 )
529
500 if self.__projectBrowserAct not in menu.actions(): 530 if self.__projectBrowserAct not in menu.actions():
501 menu.addAction(self.__projectBrowserAct) 531 menu.addAction(self.__projectBrowserAct)
502 if self.__projectBrowserShowAct not in menu.actions(): 532 if self.__projectBrowserShowAct not in menu.actions():
503 menu.addAction(self.__projectBrowserShowAct) 533 menu.addAction(self.__projectBrowserShowAct)
504 534
505 enable = ( 535 enable = (
506 ericApp().getObject("ProjectBrowser") 536 ericApp()
537 .getObject("ProjectBrowser")
507 .getProjectBrowser("sources") 538 .getProjectBrowser("sources")
508 .getSelectedItemsCount([ProjectBrowserFileItem]) == 1) 539 .getSelectedItemsCount([ProjectBrowserFileItem])
540 == 1
541 )
509 self.__projectBrowserAct.setEnabled(enable) 542 self.__projectBrowserAct.setEnabled(enable)
510 self.__projectBrowserShowAct.setEnabled( 543 self.__projectBrowserShowAct.setEnabled(
511 enable and self.__pylintPsbDialog is not None) 544 enable and self.__pylintPsbDialog is not None
512 545 )
546
513 def __pyLint(self, project, mpName, forProject, forEditor=False): 547 def __pyLint(self, project, mpName, forProject, forEditor=False):
514 """ 548 """
515 Private method used to perform a PyLint run. 549 Private method used to perform a PyLint run.
516 550
517 @param project reference to the Project object 551 @param project reference to the Project object
518 @type Project 552 @type Project
519 @param mpName name of module or package to be checked 553 @param mpName name of module or package to be checked
520 @type str 554 @type str
521 @param forProject flag indicating a run for the project 555 @param forProject flag indicating a run for the project
526 if forEditor: 560 if forEditor:
527 parms = copy.deepcopy(self.__editorParms) 561 parms = copy.deepcopy(self.__editorParms)
528 editor = ericApp().getObject("ViewManager").getOpenEditor(mpName) 562 editor = ericApp().getObject("ViewManager").getOpenEditor(mpName)
529 majorVersionStr = editor.getLanguage() 563 majorVersionStr = editor.getLanguage()
530 else: 564 else:
531 parms = project.getData('CHECKERSPARMS', "PYLINT") 565 parms = project.getData("CHECKERSPARMS", "PYLINT")
532 majorVersionStr = project.getProjectLanguage() 566 majorVersionStr = project.getProjectLanguage()
533 exe, version = {"Python3": exePy3}.get(majorVersionStr) 567 exe, version = {"Python3": exePy3}.get(majorVersionStr)
534 if exe == '': 568 if exe == "":
535 EricMessageBox.critical( 569 EricMessageBox.critical(
536 None, 570 None,
537 self.tr("pylint"), 571 self.tr("pylint"),
538 self.tr("""The pylint executable could not be found.""")) 572 self.tr("""The pylint executable could not be found."""),
573 )
539 return 574 return
540 575
541 from PyLintInterface.PyLintConfigDialog import PyLintConfigDialog 576 from PyLintInterface.PyLintConfigDialog import PyLintConfigDialog
577
542 dlg = PyLintConfigDialog(project.getProjectPath(), exe, parms, version) 578 dlg = PyLintConfigDialog(project.getProjectPath(), exe, parms, version)
543 if dlg.exec() == QDialog.DialogCode.Accepted: 579 if dlg.exec() == QDialog.DialogCode.Accepted:
544 args, parms = dlg.generateParameters() 580 args, parms = dlg.generateParameters()
545 self.__editorParms = copy.deepcopy(parms) 581 self.__editorParms = copy.deepcopy(parms)
546 if not forEditor: 582 if not forEditor:
547 project.setData('CHECKERSPARMS', "PYLINT", parms) 583 project.setData("CHECKERSPARMS", "PYLINT", parms)
548 584
549 # now do the call 585 # now do the call
550 from PyLintInterface.PyLintExecDialog import PyLintExecDialog 586 from PyLintInterface.PyLintExecDialog import PyLintExecDialog
587
551 dlg2 = PyLintExecDialog() 588 dlg2 = PyLintExecDialog()
552 reportFile = parms.get('reportFile', None) 589 reportFile = parms.get("reportFile", None)
553 res = dlg2.start(args, mpName, reportFile, 590 res = dlg2.start(args, mpName, reportFile, project.getProjectPath())
554 project.getProjectPath())
555 if res: 591 if res:
556 dlg2.show() 592 dlg2.show()
557 if forProject: 593 if forProject:
558 self.__pylintPDialog = dlg2 594 self.__pylintPDialog = dlg2
559 elif forEditor: 595 elif forEditor:
560 self.__editorPylintDialog = dlg2 596 self.__editorPylintDialog = dlg2
561 else: 597 else:
562 self.__pylintPsbDialog = dlg2 598 self.__pylintPsbDialog = dlg2
563 599
564 def __projectPylint(self): 600 def __projectPylint(self):
565 """ 601 """
566 Private slot used to check the project files with Pylint. 602 Private slot used to check the project files with Pylint.
567 """ 603 """
568 project = ericApp().getObject("Project") 604 project = ericApp().getObject("Project")
569 project.saveAllScripts() 605 project.saveAllScripts()
570 self.__pyLint(project, project.getProjectPath(), True) 606 self.__pyLint(project, project.getProjectPath(), True)
571 607
572 def __projectPylintShow(self): 608 def __projectPylintShow(self):
573 """ 609 """
574 Private slot to show the PyLint dialog with the results of the last 610 Private slot to show the PyLint dialog with the results of the last
575 run. 611 run.
576 """ 612 """
577 if self.__pylintPDialog is not None: 613 if self.__pylintPDialog is not None:
578 self.__pylintPDialog.show() 614 self.__pylintPDialog.show()
579 615
580 def __projectBrowserPylint(self): 616 def __projectBrowserPylint(self):
581 """ 617 """
582 Private method to handle the Pylint context menu action of the project 618 Private method to handle the Pylint context menu action of the project
583 sources browser. 619 sources browser.
584 """ 620 """
585 project = ericApp().getObject("Project") 621 project = ericApp().getObject("Project")
586 browser = ( 622 browser = ericApp().getObject("ProjectBrowser").getProjectBrowser("sources")
587 ericApp().getObject("ProjectBrowser").getProjectBrowser("sources")
588 )
589 itm = browser.model().item(browser.currentIndex()) 623 itm = browser.model().item(browser.currentIndex())
590 try: 624 try:
591 fn = itm.fileName() 625 fn = itm.fileName()
592 except AttributeError: 626 except AttributeError:
593 fn = itm.dirName() 627 fn = itm.dirName()
594 self.__pyLint(project, fn, False) 628 self.__pyLint(project, fn, False)
595 629
596 def __projectBrowserPylintShow(self): 630 def __projectBrowserPylintShow(self):
597 """ 631 """
598 Private slot to show the PyLint dialog with the results of the last 632 Private slot to show the PyLint dialog with the results of the last
599 run. 633 run.
600 """ 634 """
601 if self.__pylintPsbDialog is not None: 635 if self.__pylintPsbDialog is not None:
602 self.__pylintPsbDialog.show() 636 self.__pylintPsbDialog.show()
603 637
604 def __editorOpened(self, editor): 638 def __editorOpened(self, editor):
605 """ 639 """
606 Private slot called, when a new editor was opened. 640 Private slot called, when a new editor was opened.
607 641
608 @param editor reference to the new editor 642 @param editor reference to the new editor
609 @type Editor 643 @type Editor
610 """ 644 """
611 menu = editor.getMenu("Checks") 645 menu = editor.getMenu("Checks")
612 if menu is not None: 646 if menu is not None:
613 menu.addAction(self.__editorAct) 647 menu.addAction(self.__editorAct)
614 editor.showMenu.connect(self.__editorShowMenu) 648 editor.showMenu.connect(self.__editorShowMenu)
615 self.__editors.append(editor) 649 self.__editors.append(editor)
616 650
617 def __editorClosed(self, editor): 651 def __editorClosed(self, editor):
618 """ 652 """
619 Private slot called, when an editor was closed. 653 Private slot called, when an editor was closed.
620 654
621 @param editor reference to the editor 655 @param editor reference to the editor
622 @type Editor 656 @type Editor
623 """ 657 """
624 with contextlib.suppress(ValueError): 658 with contextlib.suppress(ValueError):
625 self.__editors.remove(editor) 659 self.__editors.remove(editor)
626 660
627 def __editorShowMenu(self, menuName, menu, editor): 661 def __editorShowMenu(self, menuName, menu, editor):
628 """ 662 """
629 Private slot called, when the the editor context menu or a submenu is 663 Private slot called, when the the editor context menu or a submenu is
630 about to be shown. 664 about to be shown.
631 665
632 @param menuName name of the menu to be shown 666 @param menuName name of the menu to be shown
633 @type str 667 @type str
634 @param menu reference to the menu 668 @param menu reference to the menu
635 @type QMenu 669 @type QMenu
636 @param editor reference to the editor 670 @param editor reference to the editor
638 """ 672 """
639 if menuName == "Checks": 673 if menuName == "Checks":
640 if self.__editorAct not in menu.actions(): 674 if self.__editorAct not in menu.actions():
641 menu.addAction(self.__editorAct) 675 menu.addAction(self.__editorAct)
642 self.__editorAct.setEnabled(editor.isPyFile()) 676 self.__editorAct.setEnabled(editor.isPyFile())
643 677
644 def __editorPylint(self): 678 def __editorPylint(self):
645 """ 679 """
646 Private slot to handle the Pylint context menu action of the editors. 680 Private slot to handle the Pylint context menu action of the editors.
647 """ 681 """
648 editor = ericApp().getObject("ViewManager").activeWindow() 682 editor = ericApp().getObject("ViewManager").activeWindow()
649 if ( 683 if editor is not None and not editor.checkDirty():
650 editor is not None and
651 not editor.checkDirty()
652 ):
653 return 684 return
654 685
655 fn = editor.getFileName() 686 fn = editor.getFileName()
656 project = ericApp().getObject("Project") 687 project = ericApp().getObject("Project")
657 self.__pyLint(project, fn, False, True) 688 self.__pyLint(project, fn, False, True)
658 689
659 690
660 def installDependencies(pipInstall): 691 def installDependencies(pipInstall):
661 """ 692 """
662 Function to install dependencies of this plug-in. 693 Function to install dependencies of this plug-in.
663 694
664 @param pipInstall function to be called with a list of package names. 695 @param pipInstall function to be called with a list of package names.
665 @type function 696 @type function
666 """ 697 """
667 try: 698 try:
668 import pylint # __IGNORE_WARNING__ 699 import pylint # __IGNORE_WARNING__
669 except ImportError: 700 except ImportError:
670 pipInstall(["pylint"]) 701 pipInstall(["pylint"])
671 702
703
672 # 704 #
673 # eflag: noqa = M801 705 # eflag: noqa = M801

eric ide

mercurial