src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsFunctionVisitor.py

branch
eric7
changeset 9276
e6748a5e24b9
parent 9221
bf71ee032bb4
child 9500
5771348ded12
equal deleted inserted replaced
9275:1a7d545d3ef2 9276:e6748a5e24b9
6 """ 6 """
7 Module implementing a node visitor for function type annotations. 7 Module implementing a node visitor for function type annotations.
8 """ 8 """
9 9
10 # 10 #
11 # The visitor and associated classes are adapted from flake8-annotations v2.7.0 11 # The visitor and associated classes are adapted from flake8-annotations v2.9.0
12 # 12 #
13 13
14 import ast 14 import ast
15 import itertools 15 import itertools
16 import sys 16 import sys
33 col_offset, 33 col_offset,
34 annotationType, 34 annotationType,
35 hasTypeAnnotation=False, 35 hasTypeAnnotation=False,
36 has3107Annotation=False, 36 has3107Annotation=False,
37 hasTypeComment=False, 37 hasTypeComment=False,
38 isDynamicallyTyped=False,
38 ): 39 ):
39 """ 40 """
40 Constructor 41 Constructor
41 42
42 @param argname name of the argument 43 @param argname name of the argument
54 annotation (defaults to False) 55 annotation (defaults to False)
55 @type bool (optional) 56 @type bool (optional)
56 @param hasTypeComment flag indicating the presence of a type comment 57 @param hasTypeComment flag indicating the presence of a type comment
57 (defaults to False) 58 (defaults to False)
58 @type bool (optional) 59 @type bool (optional)
60 @param isDynamicallyTyped flag indicating dynamic typing (defaults to False)
61 @type bool (optional)
59 """ 62 """
60 self.argname = argname 63 self.argname = argname
61 self.lineno = lineno 64 self.lineno = lineno
62 self.col_offset = col_offset 65 self.col_offset = col_offset
63 self.annotationType = annotationType 66 self.annotationType = annotationType
64 self.hasTypeAnnotation = hasTypeAnnotation 67 self.hasTypeAnnotation = hasTypeAnnotation
65 self.has3107Annotation = has3107Annotation 68 self.has3107Annotation = has3107Annotation
66 self.hasTypeComment = hasTypeComment 69 self.hasTypeComment = hasTypeComment
70 self.isDynamicallyTyped = isDynamicallyTyped
67 71
68 @classmethod 72 @classmethod
69 def fromNode(cls, node, annotationTypeName): 73 def fromNode(cls, node, annotationTypeName):
70 """ 74 """
71 Class method to create an Argument object based on the given node. 75 Class method to create an Argument object based on the given node.
87 91
88 if node.type_comment: 92 if node.type_comment:
89 newArg.hasTypeAnnotation = True 93 newArg.hasTypeAnnotation = True
90 newArg.hasTypeComment = True 94 newArg.hasTypeComment = True
91 95
96 if cls._isAnnotatedAny(node.type_comment):
97 newArg.isDynamicallyTyped = True
98
92 return newArg 99 return newArg
100
101 @staticmethod
102 def _isAnnotatedAny(argExpr):
103 """
104 Static method to check if the provided expression node is annotated with
105 'typing.Any'.
106
107 Support is provided for the following patterns:
108 * 'from typing import Any; foo: Any'
109 * 'import typing; foo: typing.Any'
110 * 'import typing as <alias>; foo: <alias>.Any'
111
112 Type comments are also supported. Inline type comments are assumed to be
113 passed here as 'str', and function-level type comments are assumed to be
114 passed as 'ast.expr'.
115
116 @param argExpr DESCRIPTION
117 @type ast.expr or str
118 @return flag indicating an annotation with 'typing.Any'
119 @rtype bool
120 """
121 if isinstance(argExpr, ast.Name):
122 if argExpr.id == "Any":
123 return True
124 elif isinstance(argExpr, ast.Attribute):
125 if argExpr.attr == "Any":
126 return True
127 elif isinstance(argExpr, str): # __IGNORE_WARNING_Y102__
128 if argExpr.split(".", maxsplit=1)[-1] == "Any":
129 return True
130
131 return False
93 132
94 133
95 class Function: 134 class Function:
96 """ 135 """
97 Class representing a function. 136 Class representing a function.
316 ) 355 )
317 if node.returns: 356 if node.returns:
318 returnArg.hasTypeAnnotation = True 357 returnArg.hasTypeAnnotation = True
319 returnArg.has3107Annotation = True 358 returnArg.has3107Annotation = True
320 newFunction.isReturnAnnotated = True 359 newFunction.isReturnAnnotated = True
360
361 if Argument._isAnnotatedAny(node.returns):
362 returnArg.isDynamicallyTyped = True
321 363
322 newFunction.args.append(returnArg) 364 newFunction.args.append(returnArg)
323 365
324 # Type comments in-line with input arguments are handled by the 366 # Type comments in-line with input arguments are handled by the
325 # Argument class. If a function-level type comment is present, attempt 367 # Argument class. If a function-level type comment is present, attempt
424 466
425 if arg and hintComment: 467 if arg and hintComment:
426 arg.hasTypeAnnotation = True 468 arg.hasTypeAnnotation = True
427 arg.hasTypeComment = True 469 arg.hasTypeComment = True
428 470
471 if Argument._isAnnotatedAny(hintComment):
472 arg.isDynamicallyTyped = True
473
429 # Return arg is always last 474 # Return arg is always last
430 funcObj.args[-1].hasTypeAnnotation = True 475 funcObj.args[-1].hasTypeAnnotation = True
431 funcObj.args[-1].hasTypeComment = True 476 funcObj.args[-1].hasTypeComment = True
432 funcObj.isReturnAnnotated = True 477 funcObj.isReturnAnnotated = True
478 if Argument._isAnnotatedAny(hintTree.returns):
479 arg.isDynamicallyTyped = True
433 480
434 return funcObj 481 return funcObj
435 482
436 @staticmethod 483 @staticmethod
437 def _maybeInjectClassArgument(hintTree, funcObj): 484 def _maybeInjectClassArgument(hintTree, funcObj):
474 """ 521 """
475 if not funcObj.isClassMethod: 522 if not funcObj.isClassMethod:
476 # Short circuit 523 # Short circuit
477 return hintTree 524 return hintTree
478 525
479 if funcObj.classDecoratorType != ClassDecoratorType.STATICMETHOD and len( 526 if funcObj.classDecoratorType != ClassDecoratorType.STATICMETHOD and (
480 hintTree.argtypes 527 len(hintTree.argtypes) < (len(funcObj.args) - 1)
481 ) < (len(funcObj.args) - 1): 528 ):
482 # Subtract 1 to skip return arg 529 # Subtract 1 to skip return arg
483 hintTree.argtypes = [ast.Ellipsis()] + hintTree.argtypes 530 hintTree.argtypes = [ast.Ellipsis()] + hintTree.argtypes
484 531
485 return hintTree 532 return hintTree
486 533

eric ide

mercurial