--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/pycodestyle.py Thu Dec 08 14:46:06 2022 +0100 +++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/pycodestyle.py Thu Dec 08 15:10:49 2022 +0100 @@ -62,7 +62,9 @@ # import bisect +import configparser import inspect +import io import keyword import os import re @@ -75,12 +77,6 @@ from functools import lru_cache from optparse import OptionParser -try: - from configparser import RawConfigParser - from io import TextIOWrapper -except ImportError: - from ConfigParser import RawConfigParser # __IGNORE_WARNING__ - # this is a performance hack. see https://bugs.python.org/issue43014 if ( sys.version_info < (3, 10) and @@ -88,7 +84,7 @@ ): # pragma: no cover (<py310) tokenize._compile = lru_cache()(tokenize._compile) # type: ignore -__version__ = '2.9.1-eric' +__version__ = '2.10.0-eric' DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox' DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503,W504' @@ -534,6 +530,7 @@ Okay: [a, b] Okay: (3,) + Okay: a[3,] = 1 Okay: a[1:4] Okay: a[:4] Okay: a[1:] @@ -551,7 +548,7 @@ if char == ':' and before.count('[') > before.count(']') and \ before.rfind('{') < before.rfind('['): continue # Slice syntax, no space required - if char == ',' and next_char == ')': + if char == ',' and next_char in ')]': continue # Allow tuple with only one element: (3,) if char == ':' and next_char == '=' and sys.version_info >= (3, 8): continue # Allow assignment expression @@ -1521,14 +1518,19 @@ E741: I = 42 Variables can be bound in several other contexts, including class - and function definitions, 'global' and 'nonlocal' statements, - exception handlers, and 'with' and 'for' statements. + and function definitions, lambda functions, 'global' and 'nonlocal' + statements, exception handlers, and 'with' and 'for' statements. In addition, we have a special handling for function parameters. Okay: except AttributeError as o: Okay: with lock as L: Okay: foo(l=12) + Okay: foo(l=I) Okay: for a in foo(l=12): + Okay: lambda arg: arg * l + Okay: lambda a=l[I:5]: None + Okay: lambda x=a.I: None + Okay: if l >= 12: E741: except AttributeError as O: E741: with lock as l: E741: global I @@ -1537,32 +1539,39 @@ E741: def foo(l=12): E741: l = foo(l=12) E741: for l in range(10): + E741: [l for l in lines if l] + E741: lambda l: None + E741: lambda a=x[1:5], l: None + E741: lambda **l: + E741: def f(**l): E742: class I(object): E743: def l(x): """ - is_func_def = False # Set to true if 'def' is found - parameter_parentheses_level = 0 + func_depth = None # set to brace depth if 'def' or 'lambda' is found + seen_colon = False # set to true if we're done with function parameters + brace_depth = 0 idents_to_avoid = ('l', 'O', 'I') prev_type, prev_text, prev_start, prev_end, __ = tokens[0] - for token_type, text, start, end, line in tokens[1:]: + for index in range(1, len(tokens)): + token_type, text, start, end, line = tokens[index] ident = pos = None # find function definitions - if prev_text == 'def': - is_func_def = True + if prev_text in {'def', 'lambda'}: + func_depth = brace_depth + seen_colon = False + elif ( + func_depth is not None and + text == ':' and + brace_depth == func_depth + ): + seen_colon = True # update parameter parentheses level - if parameter_parentheses_level == 0 and \ - prev_type == tokenize.NAME and \ - token_type == tokenize.OP and text == '(': - parameter_parentheses_level = 1 - elif parameter_parentheses_level > 0 and \ - token_type == tokenize.OP: - if text == '(': - parameter_parentheses_level += 1 - elif text == ')': - parameter_parentheses_level -= 1 + if text in '([{': + brace_depth += 1 + elif text in ')]}': + brace_depth -= 1 # identifiers on the lhs of an assignment operator - if token_type == tokenize.OP and '=' in text and \ - parameter_parentheses_level == 0: + if text == ':=' or (text == '=' and brace_depth == 0): if prev_text in idents_to_avoid: ident = prev_text pos = prev_start @@ -1572,11 +1581,16 @@ if text in idents_to_avoid: ident = text pos = start - # function parameter definitions - if is_func_def: - if text in idents_to_avoid: - ident = text - pos = start + # function / lambda parameter definitions + if ( + func_depth is not None and + not seen_colon and + index < len(tokens) - 1 and tokens[index + 1][1] in ':,=)' and + prev_text in {'lambda', ',', '*', '**', '('} and + text in idents_to_avoid + ): + ident = text + pos = start if prev_text == 'class': if text in idents_to_avoid: yield start, "E742 ambiguous class definition '%s'", text @@ -1585,7 +1599,6 @@ yield start, "E743 ambiguous function definition '%s'", text if ident: yield pos, "E741 ambiguous variable name '%s'", ident - prev_type = token_type prev_text = text prev_start = start @@ -1839,7 +1852,7 @@ def stdin_get_value(): """Read the value from stdin.""" - return TextIOWrapper(sys.stdin.buffer, errors='ignore').read() + return io.TextIOWrapper(sys.stdin.buffer, errors='ignore').read() noqa = lru_cache(512)(re.compile(r'# no(?:qa|pep8)\b', re.I).search) @@ -2669,7 +2682,7 @@ merged together (in that order) using the read method of ConfigParser. """ - config = RawConfigParser() + config = configparser.RawConfigParser() cli_conf = options.config