Sat, 03 Apr 2021 16:02:33 +0200
Code Style Checker: changed code such, that the AST tree is built only once and passed to each checker module.
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsChecker.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsChecker.py Sat Apr 03 16:02:33 2021 +0200 @@ -7,7 +7,7 @@ Module implementing a checker for function type annotations. """ -import sys +import copy import ast import AstUtilities @@ -32,12 +32,9 @@ ## Annotation Complexity "A891", - - ## Syntax Error - "A999", ] - def __init__(self, source, filename, select, ignore, expected, repeat, + def __init__(self, source, filename, tree, select, ignore, expected, repeat, args): """ Constructor @@ -46,6 +43,8 @@ @type list of str @param filename name of the source file @type str + @param tree AST tree of the source code + @type ast.Module @param select list of selected codes @type list of str @param ignore list of codes to be ignored @@ -63,6 +62,7 @@ self.__repeat = repeat self.__filename = filename self.__source = source[:] + self.__tree = copy.deepcopy(tree) self.__args = args # statistics counters @@ -141,29 +141,6 @@ } ) - def __reportInvalidSyntax(self): - """ - Private method to report a syntax error. - """ - exc_type, exc = sys.exc_info()[:2] - if len(exc.args) > 1: - offset = exc.args[1] - if len(offset) > 2: - offset = offset[1:3] - else: - offset = (1, 0) - self.__error(offset[0] - 1, offset[1] or 0, - 'A999', exc_type.__name__, exc.args[0]) - - def __generateTree(self): - """ - Private method to generate an AST for our source. - - @return generated AST - @rtype ast.Module - """ - return ast.parse("".join(self.__source), self.__filename) - def run(self): """ Public method to check the given source against annotation issues. @@ -176,12 +153,6 @@ # don't do anything, if no codes were selected return - try: - self.__tree = self.__generateTree() - except (SyntaxError, TypeError): - self.__reportInvalidSyntax() - return - for check in self.__checkers: check()
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/translations.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/translations.py Sat Apr 03 16:02:33 2021 +0200 @@ -53,10 +53,6 @@ "A891": QCoreApplication.translate( "AnnotationsChecker", "type annotation is too complex ({0} > {1})"), - - "A999": QCoreApplication.translate( - "AnnotationsChecker", - "{0}: {1}"), } _annotationsMessagesSampleArgs = { @@ -65,5 +61,4 @@ "A003": ["kwargs"], "A881": [60], "A891": [5, 3], - "A999": ["SyntaxError", "Invalid Syntax"], }
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleChecker.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleChecker.py Sat Apr 03 16:02:33 2021 +0200 @@ -279,15 +279,16 @@ @type str @param source string containing the code to check @type str - @return tuple containing the error dictionary with syntax error details - and a statistics dictionary or a tuple containing two None - @rtype tuple of (dict, dict) or tuple of (None, None) + @return tuple containing the error dictionary with syntax error details, + a statistics dictionary and None or a tuple containing two None and + the generated AST tree + @rtype tuple of (dict, dict, None) or tuple of (None, None, ast.Module) """ src = "".join(source) try: - ast.parse(src, filename, 'exec') - return None, None + tree = ast.parse(src, filename, 'exec') + return None, None, tree except (SyntaxError, TypeError): exc_type, exc = sys.exc_info()[:2] if len(exc.args) > 1: @@ -304,7 +305,8 @@ "args": [exc_type.__name__, exc.args[0]], }, { "E901": 1, - }) + }, + None) def __checkCodeStyle(filename, source, args): @@ -367,13 +369,10 @@ else: ignore = [] - syntaxError, syntaxStats = __checkSyntax(filename, source) - if syntaxError: - errors = [syntaxError] - stats.update(syntaxStats) + syntaxError, syntaxStats, tree = __checkSyntax(filename, source) - # perform the checks only, if syntax is ok - else: + # perform the checks only, if syntax is ok and AST tree was generated + if tree: # check coding style pycodestyle.BLANK_LINES_CONFIG = { # Top level class and function. @@ -404,7 +403,7 @@ # miscellaneous additional checks miscellaneousChecker = MiscellaneousChecker( - source, filename, select, ignore, [], repeatMessages, + source, filename, tree, select, ignore, [], repeatMessages, miscellaneousArgs) miscellaneousChecker.run() stats.update(miscellaneousChecker.counters) @@ -412,7 +411,7 @@ # check code complexity complexityChecker = ComplexityChecker( - source, filename, select, ignore, codeComplexityArgs) + source, filename, tree, select, ignore, codeComplexityArgs) complexityChecker.run() stats.update(complexityChecker.counters) errors += complexityChecker.errors @@ -422,7 +421,7 @@ # annotations are supported from Python 3.5 on from Annotations.AnnotationsChecker import AnnotationsChecker annotationsChecker = AnnotationsChecker( - source, filename, select, ignore, [], repeatMessages, + source, filename, tree, select, ignore, [], repeatMessages, annotationArgs) annotationsChecker.run() stats.update(annotationsChecker.counters) @@ -430,7 +429,7 @@ # check for security issues securityChecker = SecurityChecker( - source, filename, select, ignore, [], repeatMessages, + source, filename, tree, select, ignore, [], repeatMessages, securityArgs) securityChecker.run() stats.update(securityChecker.counters) @@ -438,17 +437,21 @@ # check for pathlib usage pathlibChecker = PathlibChecker( - source, filename, select, ignore, [], repeatMessages) + source, filename, tree, select, ignore, [], repeatMessages) pathlibChecker.run() stats.update(pathlibChecker.counters) errors += pathlibChecker.errors # check for code simplifications simplifyChecker = SimplifyChecker( - source, filename, select, ignore, [], repeatMessages) + source, filename, tree, select, ignore, [], repeatMessages) simplifyChecker.run() stats.update(simplifyChecker.counters) errors += simplifyChecker.errors + + elif syntaxError: + errors = [syntaxError] + stats.update(syntaxStats) errorsDict = {} for error in errors:
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Complexity/ComplexityChecker.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Complexity/ComplexityChecker.py Sat Apr 03 16:02:33 2021 +0200 @@ -7,7 +7,7 @@ Module implementing a checker for code complexity. """ -import sys +import copy import ast from .mccabe import PathGraphingAstVisitor @@ -20,11 +20,9 @@ Codes = [ "C101", "C111", "C112", - - "C901", ] - def __init__(self, source, filename, select, ignore, args): + def __init__(self, source, filename, tree, select, ignore, args): """ Constructor @@ -32,6 +30,8 @@ @type list of str @param filename name of the source file @type str + @param tree AST tree of the source code + @type ast.Module @param select list of selected codes @type list of str @param ignore list of codes to be ignored @@ -41,6 +41,7 @@ """ self.__filename = filename self.__source = source[:] + self.__tree = copy.deepcopy(tree) self.__select = tuple(select) self.__ignore = ('',) if select else tuple(ignore) self.__args = args @@ -113,20 +114,6 @@ } ) - def __reportInvalidSyntax(self): - """ - Private method to report a syntax error. - """ - exc_type, exc = sys.exc_info()[:2] - if len(exc.args) > 1: - offset = exc.args[1] - if len(offset) > 2: - offset = offset[1:3] - else: - offset = (1, 0) - self.__error(offset[0] - 1, offset[1] or 0, - 'C901', exc_type.__name__, exc.args[0]) - def run(self): """ Public method to check the given source for code complexity. @@ -139,12 +126,6 @@ # don't do anything, if no codes were selected return - try: - self.__tree = ast.parse("".join(self.__source), self.__filename) - except (SyntaxError, TypeError): - self.__reportInvalidSyntax() - return - for check in self.__checkers: check()
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Complexity/translations.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Complexity/translations.py Sat Apr 03 16:02:33 2021 +0200 @@ -19,13 +19,10 @@ "C112": QCoreApplication.translate( "ComplexityChecker", "overall source code line complexity is too high ({0})"), - "C901": QCoreApplication.translate( - "ComplexityChecker", "{0}: {1}"), } _complexityMessagesSampleArgs = { "C101": ["foo.bar", "42"], "C111": [42], "C112": [12.0], - "C901": ["SyntaxError", "Invalid Syntax"], }
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/DocStyle/DocStyleChecker.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/DocStyle/DocStyleChecker.py Sat Apr 03 16:02:33 2021 +0200 @@ -14,7 +14,6 @@ import tokenize import ast -import sys from io import StringIO try: @@ -135,8 +134,6 @@ "D242", "D243", "D244", "D245", "D246", "D247", "D250", "D251", "D252", "D253", "D260", "D261", "D262", "D263", - - "D901", ] def __init__(self, source, filename, select, ignore, expected, repeat, @@ -307,20 +304,6 @@ } ) - def __reportInvalidSyntax(self): - """ - Private method to report a syntax error. - """ - exc_type, exc = sys.exc_info()[:2] - if len(exc.args) > 1: - offset = exc.args[1] - if len(offset) > 2: - offset = offset[1:3] - else: - offset = (1, 0) - self.__error(offset[0] - 1, offset[1] or 0, - 'D901', exc_type.__name__, exc.args[0]) - def __resetReadline(self): """ Private method to reset the internal readline function. @@ -351,12 +334,6 @@ # don't do anything, if no codes were selected return - try: - ast.parse("".join(self.__source), self.__filename) - except (SyntaxError, TypeError): - self.__reportInvalidSyntax() - return - for keyword in self.__keywords: if keyword in self.__checkers: for check in self.__checkers[keyword]:
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/DocStyle/translations.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/DocStyle/translations.py Sat Apr 03 16:02:33 2021 +0200 @@ -157,9 +157,6 @@ "D263": QCoreApplication.translate( "DocStyleChecker", "documented signal '{0}' is not defined"), - - "D901": QCoreApplication.translate( - "DocStyleChecker", "{0}: {1}"), } _docStyleMessagesSampleArgs = { @@ -168,5 +165,4 @@ "D253": ["RuntimeError"], "D262": ["buttonClicked"], "D263": ["buttonClicked"], - "D901": ["SyntaxError", "Invalid Syntax"], }
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Miscellaneous/MiscellaneousChecker.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Miscellaneous/MiscellaneousChecker.py Sat Apr 03 16:02:33 2021 +0200 @@ -14,6 +14,7 @@ from string import Formatter from collections import defaultdict import tokenize +import copy import AstUtilities @@ -110,9 +111,6 @@ ## commented code "M891", - - ## syntax error - "M901", ] Formatter = Formatter() @@ -124,8 +122,8 @@ "credits", ] - def __init__(self, source, filename, select, ignore, expected, repeat, - args): + def __init__(self, source, filename, tree, select, ignore, expected, + repeat, args): """ Constructor @@ -133,6 +131,8 @@ @type list of str @param filename name of the source file @type str + @param tree AST tree of the source code + @type ast.Module @param select list of selected codes @type list of str @param ignore list of codes to be ignored @@ -150,6 +150,7 @@ self.__repeat = repeat self.__filename = filename self.__source = source[:] + self.__tree = copy.deepcopy(tree) self.__args = args self.__pep3101FormatRegex = re.compile( @@ -267,29 +268,6 @@ } ) - def __reportInvalidSyntax(self): - """ - Private method to report a syntax error. - """ - exc_type, exc = sys.exc_info()[:2] - if len(exc.args) > 1: - offset = exc.args[1] - if len(offset) > 2: - offset = offset[1:3] - else: - offset = (1, 0) - self.__error(offset[0] - 1, offset[1] or 0, - 'M901', exc_type.__name__, exc.args[0]) - - def __generateTree(self): - """ - Private method to generate an AST for our source. - - @return generated AST - @rtype ast.AST - """ - return ast.parse("".join(self.__source), self.__filename) - def run(self): """ Public method to check the given source against miscellaneous @@ -303,12 +281,6 @@ # don't do anything, if no codes were selected return - try: - self.__tree = self.__generateTree() - except (SyntaxError, TypeError): - self.__reportInvalidSyntax() - return - for check in self.__checkers: check() @@ -943,7 +915,7 @@ """ # step 1: generate an augmented node tree containing parent info # for each child node - tree = self.__generateTree() + tree = copy.deepcopy(self.__tree) for node in ast.walk(tree): for childNode in ast.iter_child_nodes(node): childNode._dtCheckerParent = node
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Miscellaneous/translations.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Miscellaneous/translations.py Sat Apr 03 16:02:33 2021 +0200 @@ -319,10 +319,6 @@ "M891": QCoreApplication.translate( "MiscellaneousChecker", "commented code lines should be removed"), - - "M901": QCoreApplication.translate( - "MiscellaneousChecker", - "{0}: {1}"), } _miscellaneousMessagesSampleArgs = { @@ -349,5 +345,4 @@ "M821": ["Dict"], "M822": ["Call"], "M823": ["dict"], - "M901": ["SyntaxError", "Invalid Syntax"], }
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/PathLib/PathlibChecker.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/PathLib/PathlibChecker.py Sat Apr 03 16:02:33 2021 +0200 @@ -9,7 +9,7 @@ """ import ast -import sys +import copy class PathlibChecker(object): @@ -65,7 +65,8 @@ "py.path.local": "P401", } - def __init__(self, source, filename, selected, ignored, expected, repeat): + def __init__(self, source, filename, tree, selected, ignored, expected, + repeat): """ Constructor @@ -73,6 +74,8 @@ @type list of str @param filename name of the source file @type str + @param tree AST tree of the source code + @type ast.Module @param selected list of selected codes @type list of str @param ignored list of codes to be ignored @@ -88,6 +91,7 @@ self.__repeat = repeat self.__filename = filename self.__source = source[:] + self.__tree = copy.deepcopy(tree) # statistics counters self.counters = {} @@ -147,29 +151,6 @@ } ) - def __reportInvalidSyntax(self): - """ - Private method to report a syntax error. - """ - exc_type, exc = sys.exc_info()[:2] - if len(exc.args) > 1: - offset = exc.args[1] - if len(offset) > 2: - offset = offset[1:3] - else: - offset = (1, 0) - self.__error(offset[0] - 1, offset[1] or 0, - 'M901', exc_type.__name__, exc.args[0]) - - def __generateTree(self): - """ - Private method to generate an AST for our source. - - @return generated AST - @rtype ast.AST - """ - return ast.parse("".join(self.__source), self.__filename) - def run(self): """ Public method to check the given source against functions @@ -183,12 +164,6 @@ # don't do anything, if no codes were selected return - try: - self.__tree = self.__generateTree() - except (SyntaxError, TypeError): - self.__reportInvalidSyntax() - return - visitor = PathlibVisitor(self.__checkForReplacement) visitor.visit(self.__tree)
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Security/SecurityChecker.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Security/SecurityChecker.py Sat Apr 03 16:02:33 2021 +0200 @@ -7,8 +7,7 @@ Module implementing the security checker. """ -import sys -import ast +import copy import collections from . import Checks @@ -94,13 +93,10 @@ # hardcoded AWS passwords "S801", "S802", - - # Syntax error - "S999", ] - def __init__(self, source, filename, select, ignore, expected, repeat, - args): + def __init__(self, source, filename, tree, select, ignore, expected, + repeat, args): """ Constructor @@ -108,6 +104,8 @@ @type list of str @param filename name of the source file @type str + @param tree AST tree of the source code + @type ast.Module @param select list of selected codes @type list of str @param ignore list of codes to be ignored @@ -125,6 +123,7 @@ self.__repeat = repeat self.__filename = filename self.__source = source[:] + self.__tree = copy.deepcopy(tree) self.__args = args # statistics counters @@ -198,33 +197,6 @@ "confidence": confidence, }) - def __reportInvalidSyntax(self): - """ - Private method to report a syntax error. - """ - exc_type, exc = sys.exc_info()[:2] - if len(exc.args) > 1: - offset = exc.args[1] - if len(offset) > 2: - offset = offset[1:3] - else: - offset = (1, 0) - self.reportError(offset[0] - 1, - offset[1] or 0, - 'S999', - "H", - "H", - exc_type.__name__, exc.args[0]) - - def __generateTree(self): - """ - Private method to generate an AST for our source. - - @return generated AST - @rtype ast.AST - """ - return ast.parse("".join(self.__source), self.__filename) - def getConfig(self): """ Public method to get the configuration dictionary. @@ -247,12 +219,6 @@ # don't do anything, if no codes were selected return - try: - self.__tree = self.__generateTree() - except (SyntaxError, TypeError): - self.__reportInvalidSyntax() - return - securityNodeVisitor = SecurityNodeVisitor( self, self.__checkers, self.__filename) securityNodeVisitor.generic_visit(self.__tree)
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Security/translations.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Security/translations.py Sat Apr 03 16:02:33 2021 +0200 @@ -368,11 +368,6 @@ "S802": QCoreApplication.translate( "Security", "Possible hardcoded AWS secret access key: {0}"), - - # Syntax error - "S999": QCoreApplication.translate( - "Security", - "{0}: {1}"), } _securityMessagesSampleArgs = { @@ -412,6 +407,4 @@ "S801": ["A1B2C3D4E5F6G7H8I9J0"], # secok "S802": ["aA1bB2cC3dD4/eE5fF6gG7+hH8iI9jJ0=kKlLM+="], # secok - - "S999": ["SyntaxError", "Invalid Syntax"], }
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyChecker.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyChecker.py Sat Apr 03 16:02:33 2021 +0200 @@ -8,7 +8,7 @@ """ import ast -import sys +import copy from .SimplifyNodeVisitor import SimplifyNodeVisitor @@ -32,7 +32,8 @@ "Y301", ] - def __init__(self, source, filename, selected, ignored, expected, repeat): + def __init__(self, source, filename, tree, selected, ignored, expected, + repeat): """ Constructor @@ -40,6 +41,8 @@ @type list of str @param filename name of the source file @type str + @param tree AST tree of the source code + @type ast.Module @param selected list of selected codes @type list of str @param ignored list of codes to be ignored @@ -55,6 +58,7 @@ self.__repeat = repeat self.__filename = filename self.__source = source[:] + self.__tree = copy.deepcopy(tree) # statistics counters self.counters = {} @@ -114,29 +118,6 @@ } ) - def __reportInvalidSyntax(self): - """ - Private method to report a syntax error. - """ - exc_type, exc = sys.exc_info()[:2] - if len(exc.args) > 1: - offset = exc.args[1] - if len(offset) > 2: - offset = offset[1:3] - else: - offset = (1, 0) - self.__error(offset[0] - 1, offset[1] or 0, - 'M901', exc_type.__name__, exc.args[0]) - - def __generateTree(self): - """ - Private method to generate an AST for our source. - - @return generated AST - @rtype ast.AST - """ - return ast.parse("".join(self.__source), self.__filename) - def run(self): """ Public method to check the given source against functions @@ -150,12 +131,6 @@ # don't do anything, if no codes were selected return - try: - self.__tree = self.__generateTree() - except (SyntaxError, TypeError): - self.__reportInvalidSyntax() - return - # Add parent information for node in ast.walk(self.__tree): for child in ast.iter_child_nodes(node):
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/translations.py Sat Apr 03 15:09:56 2021 +0200 +++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/translations.py Sat Apr 03 16:02:33 2021 +0200 @@ -259,7 +259,6 @@ "pycodestyle", "{0}"), } -# TODO: change all syntax error reports to report E901 ################################################################## ## pycodestyle warning messages