--- a/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsFunctionVisitor.py Tue Nov 16 18:00:40 2021 +0100 +++ b/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsFunctionVisitor.py Thu Nov 18 19:37:14 2021 +0100 @@ -8,11 +8,12 @@ """ # -# The visitor and associated classes are adapted from flake8-annotations v2.6.2 +# The visitor and associated classes are adapted from flake8-annotations v2.7.0 # import ast import itertools +import sys from .AnnotationsEnums import AnnotationType, ClassDecoratorType, FunctionType @@ -273,10 +274,12 @@ # Store raw decorator list for use by property methods kwargs["decoratorList"] = node.decorator_list + # Instantiate empty args list here since it has no default + kwargs["args"] = [] + newFunction = cls(node.name, node.lineno, node.col_offset, **kwargs) # Iterate over arguments by type & add - newFunction.args = [] for argType in AST_ARG_TYPES: args = node.args.__getattribute__(argType) if args: @@ -332,7 +335,27 @@ return Function._singleLineColonSeeker( node, lines[node.lineno - 1]) - defEndLineno = node.body[0].lineno - 1 + # With Python < 3.8, the function node includes the docstring and the + # body does not, so we have to rewind through any docstrings, if + # present, before looking for the def colon. We should end up with + # lines[defEndLineno - 1] having the colon. + defEndLineno = node.body[0].lineno + if sys.version_info < (3, 8, 0): + # If the docstring is on one line then no rewinding is necessary. + nTripleQuotes = lines[defEndLineno - 1].count('"""') + if nTripleQuotes == 1: + # Docstring closure, rewind until the opening is found and take + # the line prior. + while True: + defEndLineno -= 1 + if '"""' in lines[defEndLineno - 1]: + # Docstring has closed + break + + # Once we've gotten here, we've found the line where the docstring + # begins, so we have to step up one more line to get to the close of + # the def. + defEndLineno -= 1 # Use str.rfind() to account for annotations on the same line, # definition closure should be the last : on the line @@ -509,6 +532,8 @@ """ Class implementing a node visitor to check function annotations. """ + AstFuncTypes = (ast.FunctionDef, ast.AsyncFunctionDef) + def __init__(self, lines): """ Constructor @@ -532,7 +557,7 @@ @param node reference to the function definition node to be analyzed @type ast.AsyncFunctionDef or ast.FunctionDef """ - if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): + if isinstance(node, FunctionVisitor.AstFuncTypes): # Check for non-empty context first to prevent IndexErrors for # non-nested nodes if self.__context: @@ -543,8 +568,7 @@ Function.fromNode(node, self.lines, isClassMethod=True) ) elif isinstance( - self.__context[-1], - (ast.FunctionDef, ast.AsyncFunctionDef) + self.__context[-1], FunctionVisitor.AstFuncTypes ): # Check for nested function & pass the appropriate flag self.functionDefinitions.append(