277 |
277 |
278 @param filename source filename |
278 @param filename source filename |
279 @type str |
279 @type str |
280 @param source string containing the code to check |
280 @param source string containing the code to check |
281 @type str |
281 @type str |
282 @return tuple containing the error dictionary with syntax error details |
282 @return tuple containing the error dictionary with syntax error details, |
283 and a statistics dictionary or a tuple containing two None |
283 a statistics dictionary and None or a tuple containing two None and |
284 @rtype tuple of (dict, dict) or tuple of (None, None) |
284 the generated AST tree |
|
285 @rtype tuple of (dict, dict, None) or tuple of (None, None, ast.Module) |
285 """ |
286 """ |
286 src = "".join(source) |
287 src = "".join(source) |
287 |
288 |
288 try: |
289 try: |
289 ast.parse(src, filename, 'exec') |
290 tree = ast.parse(src, filename, 'exec') |
290 return None, None |
291 return None, None, tree |
291 except (SyntaxError, TypeError): |
292 except (SyntaxError, TypeError): |
292 exc_type, exc = sys.exc_info()[:2] |
293 exc_type, exc = sys.exc_info()[:2] |
293 if len(exc.args) > 1: |
294 if len(exc.args) > 1: |
294 offset = exc.args[1] |
295 offset = exc.args[1] |
295 if len(offset) > 2: |
296 if len(offset) > 2: |
402 stats.update(docStyleChecker.counters) |
401 stats.update(docStyleChecker.counters) |
403 errors += docStyleChecker.errors |
402 errors += docStyleChecker.errors |
404 |
403 |
405 # miscellaneous additional checks |
404 # miscellaneous additional checks |
406 miscellaneousChecker = MiscellaneousChecker( |
405 miscellaneousChecker = MiscellaneousChecker( |
407 source, filename, select, ignore, [], repeatMessages, |
406 source, filename, tree, select, ignore, [], repeatMessages, |
408 miscellaneousArgs) |
407 miscellaneousArgs) |
409 miscellaneousChecker.run() |
408 miscellaneousChecker.run() |
410 stats.update(miscellaneousChecker.counters) |
409 stats.update(miscellaneousChecker.counters) |
411 errors += miscellaneousChecker.errors |
410 errors += miscellaneousChecker.errors |
412 |
411 |
413 # check code complexity |
412 # check code complexity |
414 complexityChecker = ComplexityChecker( |
413 complexityChecker = ComplexityChecker( |
415 source, filename, select, ignore, codeComplexityArgs) |
414 source, filename, tree, select, ignore, codeComplexityArgs) |
416 complexityChecker.run() |
415 complexityChecker.run() |
417 stats.update(complexityChecker.counters) |
416 stats.update(complexityChecker.counters) |
418 errors += complexityChecker.errors |
417 errors += complexityChecker.errors |
419 |
418 |
420 # check function annotations |
419 # check function annotations |
421 if sys.version_info >= (3, 5, 0): |
420 if sys.version_info >= (3, 5, 0): |
422 # annotations are supported from Python 3.5 on |
421 # annotations are supported from Python 3.5 on |
423 from Annotations.AnnotationsChecker import AnnotationsChecker |
422 from Annotations.AnnotationsChecker import AnnotationsChecker |
424 annotationsChecker = AnnotationsChecker( |
423 annotationsChecker = AnnotationsChecker( |
425 source, filename, select, ignore, [], repeatMessages, |
424 source, filename, tree, select, ignore, [], repeatMessages, |
426 annotationArgs) |
425 annotationArgs) |
427 annotationsChecker.run() |
426 annotationsChecker.run() |
428 stats.update(annotationsChecker.counters) |
427 stats.update(annotationsChecker.counters) |
429 errors += annotationsChecker.errors |
428 errors += annotationsChecker.errors |
430 |
429 |
431 # check for security issues |
430 # check for security issues |
432 securityChecker = SecurityChecker( |
431 securityChecker = SecurityChecker( |
433 source, filename, select, ignore, [], repeatMessages, |
432 source, filename, tree, select, ignore, [], repeatMessages, |
434 securityArgs) |
433 securityArgs) |
435 securityChecker.run() |
434 securityChecker.run() |
436 stats.update(securityChecker.counters) |
435 stats.update(securityChecker.counters) |
437 errors += securityChecker.errors |
436 errors += securityChecker.errors |
438 |
437 |
439 # check for pathlib usage |
438 # check for pathlib usage |
440 pathlibChecker = PathlibChecker( |
439 pathlibChecker = PathlibChecker( |
441 source, filename, select, ignore, [], repeatMessages) |
440 source, filename, tree, select, ignore, [], repeatMessages) |
442 pathlibChecker.run() |
441 pathlibChecker.run() |
443 stats.update(pathlibChecker.counters) |
442 stats.update(pathlibChecker.counters) |
444 errors += pathlibChecker.errors |
443 errors += pathlibChecker.errors |
445 |
444 |
446 # check for code simplifications |
445 # check for code simplifications |
447 simplifyChecker = SimplifyChecker( |
446 simplifyChecker = SimplifyChecker( |
448 source, filename, select, ignore, [], repeatMessages) |
447 source, filename, tree, select, ignore, [], repeatMessages) |
449 simplifyChecker.run() |
448 simplifyChecker.run() |
450 stats.update(simplifyChecker.counters) |
449 stats.update(simplifyChecker.counters) |
451 errors += simplifyChecker.errors |
450 errors += simplifyChecker.errors |
|
451 |
|
452 elif syntaxError: |
|
453 errors = [syntaxError] |
|
454 stats.update(syntaxStats) |
452 |
455 |
453 errorsDict = {} |
456 errorsDict = {} |
454 for error in errors: |
457 for error in errors: |
455 if error["line"] > len(source): |
458 if error["line"] > len(source): |
456 error["line"] = len(source) |
459 error["line"] = len(source) |