eric6/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleChecker.py

changeset 7619
ef2b5af23ce7
parent 7615
ca2949b1a29a
child 7635
0cdead130a81
equal deleted inserted replaced
7618:cba5c14bcd5e 7619:ef2b5af23ce7
10 try: # Only for Py2 10 try: # Only for Py2
11 import Queue as queue 11 import Queue as queue
12 except ImportError: 12 except ImportError:
13 import queue 13 import queue
14 14
15 import ast
15 import sys 16 import sys
16 import multiprocessing 17 import multiprocessing
17 18
18 import pycodestyle 19 import pycodestyle
19 from NamingStyleChecker import NamingStyleChecker 20 from NamingStyleChecker import NamingStyleChecker
268 @param outputQueue output queue (multiprocessing.Queue) 269 @param outputQueue output queue (multiprocessing.Queue)
269 """ 270 """
270 for filename, source, args in iter(inputQueue.get, 'STOP'): 271 for filename, source, args in iter(inputQueue.get, 'STOP'):
271 result = __checkCodeStyle(filename, source, args) 272 result = __checkCodeStyle(filename, source, args)
272 outputQueue.put((filename, result)) 273 outputQueue.put((filename, result))
274
275
276 def __checkSyntax(filename, source):
277 """
278 Private module function to perform a syntax check.
279
280 @param filename source filename
281 @type str
282 @param source string containing the code to check
283 @type str
284 @return tuple containing the error dictionary with syntax error details
285 and a statistics dictionary or a tuple containing two None
286 @rtype tuple of (dict, dict) or tuple of (None, None)
287 """
288 src = "".join(source)
289 # Check type for py2: if not str it's unicode
290 if sys.version_info[0] == 2:
291 try:
292 src = src.encode('utf-8')
293 except UnicodeError:
294 pass
295
296 try:
297 ast.parse(src, filename, 'exec')
298 return None, None
299 except (SyntaxError, TypeError):
300 exc_type, exc = sys.exc_info()[:2]
301 if len(exc.args) > 1:
302 offset = exc.args[1]
303 if len(offset) > 2:
304 offset = offset[1:3]
305 else:
306 offset = (1, 0)
307 return ({
308 "file": filename,
309 "line": offset[0],
310 "offset": offset[1],
311 "code": "E901",
312 "args": [exc_type.__name__, exc.args[0]],
313 }, {
314 "E901": 1,
315 })
273 316
274 317
275 def __checkCodeStyle(filename, source, args): 318 def __checkCodeStyle(filename, source, args):
276 """ 319 """
277 Private module function to perform the code style check and/or fix 320 Private module function to perform the code style check and/or fix
338 ignore = [i.strip() for i in 381 ignore = [i.strip() for i in
339 excludeMessages.split(',') if i.strip()] 382 excludeMessages.split(',') if i.strip()]
340 else: 383 else:
341 ignore = [] 384 ignore = []
342 385
343 # TODO: perform syntax check and report invalid syntax once for all 386 syntaxError, syntaxStats = __checkSyntax(filename, source)
344 387 if syntaxError:
345 # check coding style 388 errors = [syntaxError]
346 pycodestyle.BLANK_LINES_CONFIG = { 389 stats.update(syntaxStats)
347 # Top level class and function. 390
348 'top_level': blankLines[0], 391 # perform the checks only, if syntax is ok
349 # Methods and nested class and function. 392 else:
350 'method': blankLines[1], 393 # check coding style
351 } 394 pycodestyle.BLANK_LINES_CONFIG = {
352 styleGuide = pycodestyle.StyleGuide( 395 # Top level class and function.
353 reporter=CodeStyleCheckerReport, 396 'top_level': blankLines[0],
354 repeat=repeatMessages, 397 # Methods and nested class and function.
355 select=select, 398 'method': blankLines[1],
356 ignore=ignore, 399 }
357 max_line_length=maxLineLength, 400 styleGuide = pycodestyle.StyleGuide(
358 max_doc_length=maxDocLineLength, 401 reporter=CodeStyleCheckerReport,
359 hang_closing=hangClosing, 402 repeat=repeatMessages,
360 ) 403 select=select,
361 report = styleGuide.check_files([filename]) 404 ignore=ignore,
362 stats.update(report.counters) 405 max_line_length=maxLineLength,
363 errors = report.errors 406 max_doc_length=maxDocLineLength,
364 407 hang_closing=hangClosing,
365 # check documentation style 408 )
366 docStyleChecker = DocStyleChecker( 409 report = styleGuide.check_files([filename])
367 source, filename, select, ignore, [], repeatMessages, 410 stats.update(report.counters)
368 maxLineLength=maxDocLineLength, docType=docType) 411 errors = report.errors
369 docStyleChecker.run() 412
370 stats.update(docStyleChecker.counters) 413 # check documentation style
371 errors += docStyleChecker.errors 414 docStyleChecker = DocStyleChecker(
372
373 # miscellaneous additional checks
374 miscellaneousChecker = MiscellaneousChecker(
375 source, filename, select, ignore, [], repeatMessages,
376 miscellaneousArgs)
377 miscellaneousChecker.run()
378 stats.update(miscellaneousChecker.counters)
379 errors += miscellaneousChecker.errors
380
381 # check code complexity
382 complexityChecker = ComplexityChecker(
383 source, filename, select, ignore, codeComplexityArgs)
384 complexityChecker.run()
385 stats.update(complexityChecker.counters)
386 errors += complexityChecker.errors
387
388 # check function annotations
389 if sys.version_info >= (3, 5, 0):
390 # annotations are supported from Python 3.5 on
391 from AnnotationsChecker import AnnotationsChecker
392 annotationsChecker = AnnotationsChecker(
393 source, filename, select, ignore, [], repeatMessages, 415 source, filename, select, ignore, [], repeatMessages,
394 annotationArgs) 416 maxLineLength=maxDocLineLength, docType=docType)
395 annotationsChecker.run() 417 docStyleChecker.run()
396 stats.update(annotationsChecker.counters) 418 stats.update(docStyleChecker.counters)
397 errors += annotationsChecker.errors 419 errors += docStyleChecker.errors
398 420
399 securityChecker = SecurityChecker( 421 # miscellaneous additional checks
400 source, filename, select, ignore, [], repeatMessages, 422 miscellaneousChecker = MiscellaneousChecker(
401 securityArgs) 423 source, filename, select, ignore, [], repeatMessages,
402 securityChecker.run() 424 miscellaneousArgs)
403 stats.update(securityChecker.counters) 425 miscellaneousChecker.run()
404 errors += securityChecker.errors 426 stats.update(miscellaneousChecker.counters)
427 errors += miscellaneousChecker.errors
428
429 # check code complexity
430 complexityChecker = ComplexityChecker(
431 source, filename, select, ignore, codeComplexityArgs)
432 complexityChecker.run()
433 stats.update(complexityChecker.counters)
434 errors += complexityChecker.errors
435
436 # check function annotations
437 if sys.version_info >= (3, 5, 0):
438 # annotations are supported from Python 3.5 on
439 from AnnotationsChecker import AnnotationsChecker
440 annotationsChecker = AnnotationsChecker(
441 source, filename, select, ignore, [], repeatMessages,
442 annotationArgs)
443 annotationsChecker.run()
444 stats.update(annotationsChecker.counters)
445 errors += annotationsChecker.errors
446
447 securityChecker = SecurityChecker(
448 source, filename, select, ignore, [], repeatMessages,
449 securityArgs)
450 securityChecker.run()
451 stats.update(securityChecker.counters)
452 errors += securityChecker.errors
405 453
406 errorsDict = {} 454 errorsDict = {}
407 for error in errors: 455 for error in errors:
408 if error["line"] > len(source): 456 if error["line"] > len(source):
409 error["line"] = len(source) 457 error["line"] = len(source)

eric ide

mercurial