73 |
75 |
74 from fnmatch import fnmatch |
76 from fnmatch import fnmatch |
75 from functools import lru_cache |
77 from functools import lru_cache |
76 from optparse import OptionParser |
78 from optparse import OptionParser |
77 |
79 |
78 try: |
|
79 from configparser import RawConfigParser |
|
80 from io import TextIOWrapper |
|
81 except ImportError: |
|
82 from ConfigParser import RawConfigParser # __IGNORE_WARNING__ |
|
83 |
|
84 # this is a performance hack. see https://bugs.python.org/issue43014 |
80 # this is a performance hack. see https://bugs.python.org/issue43014 |
85 if ( |
81 if ( |
86 sys.version_info < (3, 10) and |
82 sys.version_info < (3, 10) and |
87 callable(getattr(tokenize, '_compile', None)) |
83 callable(getattr(tokenize, '_compile', None)) |
88 ): # pragma: no cover (<py310) |
84 ): # pragma: no cover (<py310) |
89 tokenize._compile = lru_cache()(tokenize._compile) # type: ignore |
85 tokenize._compile = lru_cache()(tokenize._compile) # type: ignore |
90 |
86 |
91 __version__ = '2.9.1-eric' |
87 __version__ = '2.10.0-eric' |
92 |
88 |
93 DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox' |
89 DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox' |
94 DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503,W504' |
90 DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503,W504' |
95 try: |
91 try: |
96 if sys.platform == 'win32': |
92 if sys.platform == 'win32': |
549 if char in ',;:' and next_char not in WHITESPACE: |
546 if char in ',;:' and next_char not in WHITESPACE: |
550 before = line[:index] |
547 before = line[:index] |
551 if char == ':' and before.count('[') > before.count(']') and \ |
548 if char == ':' and before.count('[') > before.count(']') and \ |
552 before.rfind('{') < before.rfind('['): |
549 before.rfind('{') < before.rfind('['): |
553 continue # Slice syntax, no space required |
550 continue # Slice syntax, no space required |
554 if char == ',' and next_char == ')': |
551 if char == ',' and next_char in ')]': |
555 continue # Allow tuple with only one element: (3,) |
552 continue # Allow tuple with only one element: (3,) |
556 if char == ':' and next_char == '=' and sys.version_info >= (3, 8): |
553 if char == ':' and next_char == '=' and sys.version_info >= (3, 8): |
557 continue # Allow assignment expression |
554 continue # Allow assignment expression |
558 yield index, "E231 missing whitespace after '%s'", char |
555 yield index, "E231 missing whitespace after '%s'", char |
559 |
556 |
1519 E741: l = 0 |
1516 E741: l = 0 |
1520 E741: O = 123 |
1517 E741: O = 123 |
1521 E741: I = 42 |
1518 E741: I = 42 |
1522 |
1519 |
1523 Variables can be bound in several other contexts, including class |
1520 Variables can be bound in several other contexts, including class |
1524 and function definitions, 'global' and 'nonlocal' statements, |
1521 and function definitions, lambda functions, 'global' and 'nonlocal' |
1525 exception handlers, and 'with' and 'for' statements. |
1522 statements, exception handlers, and 'with' and 'for' statements. |
1526 In addition, we have a special handling for function parameters. |
1523 In addition, we have a special handling for function parameters. |
1527 |
1524 |
1528 Okay: except AttributeError as o: |
1525 Okay: except AttributeError as o: |
1529 Okay: with lock as L: |
1526 Okay: with lock as L: |
1530 Okay: foo(l=12) |
1527 Okay: foo(l=12) |
|
1528 Okay: foo(l=I) |
1531 Okay: for a in foo(l=12): |
1529 Okay: for a in foo(l=12): |
|
1530 Okay: lambda arg: arg * l |
|
1531 Okay: lambda a=l[I:5]: None |
|
1532 Okay: lambda x=a.I: None |
|
1533 Okay: if l >= 12: |
1532 E741: except AttributeError as O: |
1534 E741: except AttributeError as O: |
1533 E741: with lock as l: |
1535 E741: with lock as l: |
1534 E741: global I |
1536 E741: global I |
1535 E741: nonlocal l |
1537 E741: nonlocal l |
1536 E741: def foo(l): |
1538 E741: def foo(l): |
1537 E741: def foo(l=12): |
1539 E741: def foo(l=12): |
1538 E741: l = foo(l=12) |
1540 E741: l = foo(l=12) |
1539 E741: for l in range(10): |
1541 E741: for l in range(10): |
|
1542 E741: [l for l in lines if l] |
|
1543 E741: lambda l: None |
|
1544 E741: lambda a=x[1:5], l: None |
|
1545 E741: lambda **l: |
|
1546 E741: def f(**l): |
1540 E742: class I(object): |
1547 E742: class I(object): |
1541 E743: def l(x): |
1548 E743: def l(x): |
1542 """ |
1549 """ |
1543 is_func_def = False # Set to true if 'def' is found |
1550 func_depth = None # set to brace depth if 'def' or 'lambda' is found |
1544 parameter_parentheses_level = 0 |
1551 seen_colon = False # set to true if we're done with function parameters |
|
1552 brace_depth = 0 |
1545 idents_to_avoid = ('l', 'O', 'I') |
1553 idents_to_avoid = ('l', 'O', 'I') |
1546 prev_type, prev_text, prev_start, prev_end, __ = tokens[0] |
1554 prev_type, prev_text, prev_start, prev_end, __ = tokens[0] |
1547 for token_type, text, start, end, line in tokens[1:]: |
1555 for index in range(1, len(tokens)): |
|
1556 token_type, text, start, end, line = tokens[index] |
1548 ident = pos = None |
1557 ident = pos = None |
1549 # find function definitions |
1558 # find function definitions |
1550 if prev_text == 'def': |
1559 if prev_text in {'def', 'lambda'}: |
1551 is_func_def = True |
1560 func_depth = brace_depth |
|
1561 seen_colon = False |
|
1562 elif ( |
|
1563 func_depth is not None and |
|
1564 text == ':' and |
|
1565 brace_depth == func_depth |
|
1566 ): |
|
1567 seen_colon = True |
1552 # update parameter parentheses level |
1568 # update parameter parentheses level |
1553 if parameter_parentheses_level == 0 and \ |
1569 if text in '([{': |
1554 prev_type == tokenize.NAME and \ |
1570 brace_depth += 1 |
1555 token_type == tokenize.OP and text == '(': |
1571 elif text in ')]}': |
1556 parameter_parentheses_level = 1 |
1572 brace_depth -= 1 |
1557 elif parameter_parentheses_level > 0 and \ |
|
1558 token_type == tokenize.OP: |
|
1559 if text == '(': |
|
1560 parameter_parentheses_level += 1 |
|
1561 elif text == ')': |
|
1562 parameter_parentheses_level -= 1 |
|
1563 # identifiers on the lhs of an assignment operator |
1573 # identifiers on the lhs of an assignment operator |
1564 if token_type == tokenize.OP and '=' in text and \ |
1574 if text == ':=' or (text == '=' and brace_depth == 0): |
1565 parameter_parentheses_level == 0: |
|
1566 if prev_text in idents_to_avoid: |
1575 if prev_text in idents_to_avoid: |
1567 ident = prev_text |
1576 ident = prev_text |
1568 pos = prev_start |
1577 pos = prev_start |
1569 # identifiers bound to values with 'as', 'for', |
1578 # identifiers bound to values with 'as', 'for', |
1570 # 'global', or 'nonlocal' |
1579 # 'global', or 'nonlocal' |
1571 if prev_text in ('as', 'for', 'global', 'nonlocal'): |
1580 if prev_text in ('as', 'for', 'global', 'nonlocal'): |
1572 if text in idents_to_avoid: |
1581 if text in idents_to_avoid: |
1573 ident = text |
1582 ident = text |
1574 pos = start |
1583 pos = start |
1575 # function parameter definitions |
1584 # function / lambda parameter definitions |
1576 if is_func_def: |
1585 if ( |
1577 if text in idents_to_avoid: |
1586 func_depth is not None and |
1578 ident = text |
1587 not seen_colon and |
1579 pos = start |
1588 index < len(tokens) - 1 and tokens[index + 1][1] in ':,=)' and |
|
1589 prev_text in {'lambda', ',', '*', '**', '('} and |
|
1590 text in idents_to_avoid |
|
1591 ): |
|
1592 ident = text |
|
1593 pos = start |
1580 if prev_text == 'class': |
1594 if prev_text == 'class': |
1581 if text in idents_to_avoid: |
1595 if text in idents_to_avoid: |
1582 yield start, "E742 ambiguous class definition '%s'", text |
1596 yield start, "E742 ambiguous class definition '%s'", text |
1583 if prev_text == 'def': |
1597 if prev_text == 'def': |
1584 if text in idents_to_avoid: |
1598 if text in idents_to_avoid: |
1585 yield start, "E743 ambiguous function definition '%s'", text |
1599 yield start, "E743 ambiguous function definition '%s'", text |
1586 if ident: |
1600 if ident: |
1587 yield pos, "E741 ambiguous variable name '%s'", ident |
1601 yield pos, "E741 ambiguous variable name '%s'", ident |
1588 prev_type = token_type |
|
1589 prev_text = text |
1602 prev_text = text |
1590 prev_start = start |
1603 prev_start = start |
1591 |
1604 |
1592 |
1605 |
1593 @register_check |
1606 @register_check |