10 ##################################################################################### |
10 ##################################################################################### |
11 ## The visitor and associated classes are adapted from flake8-annotations v3.0.1 |
11 ## The visitor and associated classes are adapted from flake8-annotations v3.0.1 |
12 ##################################################################################### |
12 ##################################################################################### |
13 |
13 |
14 import ast |
14 import ast |
15 import sys |
|
16 |
15 |
17 from .AnnotationsEnums import AnnotationType, ClassDecoratorType, FunctionType |
16 from .AnnotationsEnums import AnnotationType, ClassDecoratorType, FunctionType |
18 |
17 |
19 # The order of AST_ARG_TYPES must match Python's grammar |
18 # The order of AST_ARG_TYPES must match Python's grammar |
20 AST_ARG_TYPES = ("args", "vararg", "kwonlyargs", "kwarg") |
19 AST_ARG_TYPES = ("posonlyargs", "args", "vararg", "kwonlyargs", "kwarg") |
21 if sys.version_info >= (3, 8, 0): |
|
22 AST_ARG_TYPES = ("posonlyargs",) + AST_ARG_TYPES |
|
23 |
20 |
24 |
21 |
25 class Argument: |
22 class Argument: |
26 """ |
23 """ |
27 Class representing a function argument. |
24 Class representing a function argument. |
372 """ |
369 """ |
373 # Special case single line function definitions |
370 # Special case single line function definitions |
374 if node.lineno == node.body[0].lineno: |
371 if node.lineno == node.body[0].lineno: |
375 return Function._singleLineColonSeeker(node, lines[node.lineno - 1]) |
372 return Function._singleLineColonSeeker(node, lines[node.lineno - 1]) |
376 |
373 |
377 # With Python < 3.8, the function node includes the docstring and the |
374 defEndLineno = node.body[0].lineno - 1 |
378 # body does not, so we have to rewind through any docstrings, if |
|
379 # present, before looking for the def colon. We should end up with |
|
380 # lines[defEndLineno - 1] having the colon. |
|
381 defEndLineno = node.body[0].lineno |
|
382 if sys.version_info < (3, 8, 0): |
|
383 # If the docstring is on one line then no rewinding is necessary. |
|
384 nTripleQuotes = lines[defEndLineno - 1].count('"""') |
|
385 if nTripleQuotes == 1: |
|
386 # Docstring closure, rewind until the opening is found and take |
|
387 # the line prior. |
|
388 while True: |
|
389 defEndLineno -= 1 |
|
390 if '"""' in lines[defEndLineno - 1]: |
|
391 # Docstring has closed |
|
392 break |
|
393 |
|
394 # Once we've gotten here, we've found the line where the docstring |
|
395 # begins, so we have to step up one more line to get to the close of |
|
396 # the def. |
|
397 defEndLineno -= 1 |
|
398 |
375 |
399 # Use str.rfind() to account for annotations on the same line, |
376 # Use str.rfind() to account for annotations on the same line, |
400 # definition closure should be the last : on the line |
377 # definition closure should be the last : on the line |
401 defEndColOffset = lines[defEndLineno - 1].rfind(":") |
378 defEndColOffset = lines[defEndLineno - 1].rfind(":") |
402 |
379 |