88 from configparser import RawConfigParser |
88 from configparser import RawConfigParser |
89 from io import TextIOWrapper |
89 from io import TextIOWrapper |
90 except ImportError: |
90 except ImportError: |
91 from ConfigParser import RawConfigParser # __IGNORE_WARNING__ |
91 from ConfigParser import RawConfigParser # __IGNORE_WARNING__ |
92 |
92 |
93 __version__ = '2.7.0-eric' |
93 # this is a performance hack. see https://bugs.python.org/issue43014 |
|
94 if ( |
|
95 sys.version_info < (3, 10) and |
|
96 callable(getattr(tokenize, '_compile', None)) |
|
97 ): # pragma: no cover (<py310) |
|
98 tokenize._compile = lru_cache()(tokenize._compile) # type: ignore |
|
99 |
|
100 __version__ = '2.8.0-eric' |
94 |
101 |
95 DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox' |
102 DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox' |
96 DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503,W504' |
103 DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503,W504' |
97 try: |
104 try: |
98 if sys.platform == 'win32': |
105 if sys.platform == 'win32': |
147 INDENT_REGEX = re.compile(r'([ \t]*)') |
154 INDENT_REGEX = re.compile(r'([ \t]*)') |
148 RAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*,') |
155 RAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*,') |
149 RERAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*,.*,\s*\w+\s*$') |
156 RERAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*,.*,\s*\w+\s*$') |
150 ERRORCODE_REGEX = re.compile(r'\b[A-Z]\d{3}\b') |
157 ERRORCODE_REGEX = re.compile(r'\b[A-Z]\d{3}\b') |
151 DOCSTRING_REGEX = re.compile(r'u?r?["\']') |
158 DOCSTRING_REGEX = re.compile(r'u?r?["\']') |
152 EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[\[({] | [\]}),;]| :(?!=)') |
159 EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[\[({][ \t]|[ \t][\]}),;:](?!=)') |
153 WHITESPACE_AFTER_COMMA_REGEX = re.compile(r'[,;:]\s*(?: |\t)') |
160 WHITESPACE_AFTER_COMMA_REGEX = re.compile(r'[,;:]\s*(?: |\t)') |
154 COMPARE_SINGLETON_REGEX = re.compile(r'(\bNone|\bFalse|\bTrue)?\s*([=!]=)' |
161 COMPARE_SINGLETON_REGEX = re.compile(r'(\bNone|\bFalse|\bTrue)?\s*([=!]=)' |
155 r'\s*(?(1)|(None|False|True))\b') |
162 r'\s*(?(1)|(None|False|True))\b') |
156 COMPARE_NEGATIVE_REGEX = re.compile(r'\b(?<!is\s)(not)\s+[^][)(}{ ]+\s+' |
163 COMPARE_NEGATIVE_REGEX = re.compile(r'\b(?<!is\s)(not)\s+[^][)(}{ ]+\s+' |
157 r'(in|is)\s') |
164 r'(in|is)\s') |
172 'with', 'async with', |
179 'with', 'async with', |
173 'class', |
180 'class', |
174 'while', |
181 'while', |
175 ))) |
182 ))) |
176 ) |
183 ) |
177 DUNDER_REGEX = re.compile(r'^__([^\s]+)__ = ') |
184 DUNDER_REGEX = re.compile(r"^__([^\s]+)__(?::\s*[a-zA-Z.0-9_\[\]\"]+)? = ") |
|
185 BLANK_EXCEPT_REGEX = re.compile(r"except\s*:") |
178 |
186 |
179 _checks = {'physical_line': {}, 'logical_line': {}, 'tree': {}} |
187 _checks = {'physical_line': {}, 'logical_line': {}, 'tree': {}} |
180 |
188 |
181 |
189 |
182 def _get_parameters(function): |
190 def _get_parameters(function): |
484 line = logical_line |
492 line = logical_line |
485 for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line): |
493 for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line): |
486 text = match.group() |
494 text = match.group() |
487 char = text.strip() |
495 char = text.strip() |
488 found = match.start() |
496 found = match.start() |
489 if text == char + ' ': |
497 if text[-1].isspace(): |
490 # assert char in '([{' |
498 # assert char in '([{' |
491 yield found + 1, "E201 whitespace after '%s'", char |
499 yield found + 1, "E201 whitespace after '%s'", char |
492 elif line[found - 1] != ',': |
500 elif line[found - 1] != ',': |
493 code = ('E202' if char in '}])' else 'E203') # if char in ',;:' |
501 code = ('E202' if char in '}])' else 'E203') # if char in ',;:' |
494 yield found, "%s whitespace before '%s'" % (code, char), char |
502 yield found, "%s whitespace before '%s'" % (code, char), char |
567 |
575 |
568 |
576 |
569 @register_check |
577 @register_check |
570 def indentation(logical_line, previous_logical, indent_char, |
578 def indentation(logical_line, previous_logical, indent_char, |
571 indent_level, previous_indent_level, |
579 indent_level, previous_indent_level, |
572 indent_size, indent_size_str): |
580 indent_size): |
573 r"""Use indent_size (PEP8 says 4) spaces per indentation level. |
581 r"""Use indent_size (PEP8 says 4) spaces per indentation level. |
574 |
582 |
575 For really old code that you don't want to mess up, you can continue |
583 For really old code that you don't want to mess up, you can continue |
576 to use 8-space tabs. |
584 to use 8-space tabs. |
577 |
585 |
591 c = 0 if logical_line else 3 |
599 c = 0 if logical_line else 3 |
592 tmpl = "E11%d %s" if logical_line else "E11%d %s (comment)" |
600 tmpl = "E11%d %s" if logical_line else "E11%d %s (comment)" |
593 if indent_level % indent_size: |
601 if indent_level % indent_size: |
594 yield 0, tmpl % ( |
602 yield 0, tmpl % ( |
595 1 + c, |
603 1 + c, |
596 "indentation is not a multiple of " + indent_size_str, |
604 "indentation is not a multiple of " + str(indent_size), |
597 ) |
605 ) |
598 indent_expect = previous_logical.endswith(':') |
606 indent_expect = previous_logical.endswith(':') |
599 if indent_expect and indent_level <= previous_indent_level: |
607 if indent_expect and indent_level <= previous_indent_level: |
600 yield 0, tmpl % (2 + c, "expected an indented block") |
608 yield 0, tmpl % (2 + c, "expected an indented block") |
601 elif not indent_expect and indent_level > previous_indent_level: |
609 elif not indent_expect and indent_level > previous_indent_level: |
608 yield 0, tmpl % (7, 'over-indented') |
616 yield 0, tmpl % (7, 'over-indented') |
609 |
617 |
610 |
618 |
611 @register_check |
619 @register_check |
612 def continued_indentation(logical_line, tokens, indent_level, hang_closing, |
620 def continued_indentation(logical_line, tokens, indent_level, hang_closing, |
613 indent_char, indent_size, indent_size_str, noqa, |
621 indent_char, indent_size, noqa, verbose): |
614 verbose): |
|
615 r"""Continuation lines indentation. |
622 r"""Continuation lines indentation. |
616 |
623 |
617 Continuation lines should align wrapped elements either vertically |
624 Continuation lines should align wrapped elements either vertically |
618 using Python's implicit line joining inside parentheses, brackets |
625 using Python's implicit line joining inside parentheses, brackets |
619 and braces, or using a hanging indent. |
626 and braces, or using a hanging indent. |
833 E211: dict['key'] = list [index] |
840 E211: dict['key'] = list [index] |
834 """ |
841 """ |
835 prev_type, prev_text, __, prev_end, __ = tokens[0] |
842 prev_type, prev_text, __, prev_end, __ = tokens[0] |
836 for index in range(1, len(tokens)): |
843 for index in range(1, len(tokens)): |
837 token_type, text, start, end, __ = tokens[index] |
844 token_type, text, start, end, __ = tokens[index] |
838 if (token_type == tokenize.OP and |
845 if ( |
|
846 token_type == tokenize.OP and |
839 text in '([' and |
847 text in '([' and |
840 start != prev_end and |
848 start != prev_end and |
841 (prev_type == tokenize.NAME or prev_text in '}])') and |
849 (prev_type == tokenize.NAME or prev_text in '}])') and |
842 # Syntax "class A (B):" is allowed, but avoid it |
850 # Syntax "class A (B):" is allowed, but avoid it |
843 (index < 2 or tokens[index - 2][1] != 'class') and |
851 (index < 2 or tokens[index - 2][1] != 'class') and |
844 # Allow "return (a.foo for a in range(5))" |
852 # Allow "return (a.foo for a in range(5))" |
845 not keyword.iskeyword(prev_text)): |
853 not keyword.iskeyword(prev_text) and |
|
854 # 'match' and 'case' are only soft keywords |
|
855 ( |
|
856 sys.version_info < (3, 9) or |
|
857 not keyword.issoftkeyword(prev_text) |
|
858 ) |
|
859 ): |
846 yield prev_end, "E211 whitespace before '%s'", text |
860 yield prev_end, "E211 whitespace before '%s'", text |
847 prev_type = token_type |
861 prev_type = token_type |
848 prev_text = text |
862 prev_text = text |
849 prev_end = end |
863 prev_end = end |
850 |
864 |
960 need_space = True |
976 need_space = True |
961 elif text in UNARY_OPERATORS: |
977 elif text in UNARY_OPERATORS: |
962 # Check if the operator is used as a binary operator |
978 # Check if the operator is used as a binary operator |
963 # Allow unary operators: -123, -x, +1. |
979 # Allow unary operators: -123, -x, +1. |
964 # Allow argument unpacking: foo(*args, **kwargs). |
980 # Allow argument unpacking: foo(*args, **kwargs). |
965 if (prev_text in '}])' if prev_type == tokenize.OP |
981 if prev_type == tokenize.OP and prev_text in '}])' or ( |
966 else prev_text not in KEYWORDS): |
982 prev_type != tokenize.OP and |
|
983 prev_text not in KEYWORDS and ( |
|
984 sys.version_info < (3, 9) or |
|
985 not keyword.issoftkeyword(prev_text) |
|
986 ) |
|
987 ): |
967 need_space = None |
988 need_space = None |
968 elif text in WS_OPTIONAL_OPERATORS: |
989 elif text in WS_OPTIONAL_OPERATORS: |
969 need_space = None |
990 need_space = None |
970 |
991 |
971 if need_space is None: |
992 if need_space is None: |
1415 Also, beware of writing if x when you really mean if x is not None |
1436 Also, beware of writing if x when you really mean if x is not None |
1416 -- e.g. when testing whether a variable or argument that defaults to |
1437 -- e.g. when testing whether a variable or argument that defaults to |
1417 None was set to some other value. The other value might have a type |
1438 None was set to some other value. The other value might have a type |
1418 (such as a container) that could be false in a boolean context! |
1439 (such as a container) that could be false in a boolean context! |
1419 """ |
1440 """ |
1420 match = not noqa and COMPARE_SINGLETON_REGEX.search(logical_line) |
1441 if noqa: |
1421 if match: |
1442 return |
|
1443 |
|
1444 for match in COMPARE_SINGLETON_REGEX.finditer(logical_line): |
1422 singleton = match.group(1) or match.group(3) |
1445 singleton = match.group(1) or match.group(3) |
1423 same = (match.group(2) == '==') |
1446 same = (match.group(2) == '==') |
1424 |
1447 |
1425 msg = "'if cond is %s:'" % (('' if same else 'not ') + singleton) |
1448 msg = "'if cond is %s:'" % (('' if same else 'not ') + singleton) |
1426 if singleton in ('None',): |
1449 if singleton in ('None',): |
1992 self.max_doc_length = options.max_doc_length |
2014 self.max_doc_length = options.max_doc_length |
1993 self.indent_size = options.indent_size |
2015 self.indent_size = options.indent_size |
1994 self.multiline = False # in a multiline string? |
2016 self.multiline = False # in a multiline string? |
1995 self.hang_closing = options.hang_closing |
2017 self.hang_closing = options.hang_closing |
1996 self.indent_size = options.indent_size |
2018 self.indent_size = options.indent_size |
1997 self.indent_size_str = ({2: 'two', 4: 'four', 8: 'eight'} |
|
1998 .get(self.indent_size, str(self.indent_size))) |
|
1999 self.verbose = options.verbose |
2019 self.verbose = options.verbose |
2000 self.filename = filename |
2020 self.filename = filename |
2001 # Dictionary where a checker can store its custom state. |
2021 # Dictionary where a checker can store its custom state. |
2002 self._checker_states = {} |
2022 self._checker_states = {} |
2003 if filename is None: |
2023 if filename is None: |