77 from configparser import RawConfigParser |
77 from configparser import RawConfigParser |
78 from io import TextIOWrapper |
78 from io import TextIOWrapper |
79 except ImportError: |
79 except ImportError: |
80 from ConfigParser import RawConfigParser # __IGNORE_WARNING__ |
80 from ConfigParser import RawConfigParser # __IGNORE_WARNING__ |
81 |
81 |
82 __version__ = '2.2.0-eric' |
82 __version__ = '2.3.1-eric' |
83 |
83 |
84 DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox' |
84 DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox' |
85 DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503' |
85 DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503' |
86 try: |
86 try: |
87 if sys.platform == 'win32': |
87 if sys.platform == 'win32': |
132 r'|\s*\(\s*([^)]*[^ )])\s*\))') |
132 r'|\s*\(\s*([^)]*[^ )])\s*\))') |
133 KEYWORD_REGEX = re.compile(r'(\s*)\b(?:%s)\b(\s*)' % r'|'.join(KEYWORDS)) |
133 KEYWORD_REGEX = re.compile(r'(\s*)\b(?:%s)\b(\s*)' % r'|'.join(KEYWORDS)) |
134 OPERATOR_REGEX = re.compile(r'(?:[^,\s])(\s*)(?:[-+*/|!<=>%&^]+)(\s*)') |
134 OPERATOR_REGEX = re.compile(r'(?:[^,\s])(\s*)(?:[-+*/|!<=>%&^]+)(\s*)') |
135 LAMBDA_REGEX = re.compile(r'\blambda\b') |
135 LAMBDA_REGEX = re.compile(r'\blambda\b') |
136 HUNK_REGEX = re.compile(r'^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@.*$') |
136 HUNK_REGEX = re.compile(r'^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@.*$') |
|
137 STARTSWITH_DEF_REGEX = re.compile(r'^(async\s+def|def)') |
|
138 STARTSWITH_TOP_LEVEL_REGEX = re.compile(r'^(async\s+def\s+|def\s+|class\s+|@)') |
|
139 STARTSWITH_INDENT_STATEMENT_REGEX = re.compile( |
|
140 r'^\s*({0})'.format('|'.join(s.replace(' ', '\s+') for s in ( |
|
141 'def', 'async def', |
|
142 'for', 'async for', |
|
143 'if', 'elif', 'else', |
|
144 'try', 'except', 'finally', |
|
145 'with', 'async with', |
|
146 'class', |
|
147 'while', |
|
148 ))) |
|
149 ) |
|
150 DUNDER_REGEX = re.compile(r'^__([^\s]+)__ = ') |
137 |
151 |
138 # Work around Python < 2.6 behaviour, which does not generate NL after |
152 # Work around Python < 2.6 behaviour, which does not generate NL after |
139 # a comment which is on a line by itself. |
153 # a comment which is on a line by itself. |
140 COMMENT_WITH_NL = tokenize.generate_tokens(['#\n'].pop).send(None)[1] == '#\n' |
154 COMMENT_WITH_NL = tokenize.generate_tokens(['#\n'].pop).send(None)[1] == '#\n' |
141 |
155 |
276 E302: def a():\n pass\n\nasync def b(n):\n pass |
290 E302: def a():\n pass\n\nasync def b(n):\n pass |
277 E303: def a():\n pass\n\n\n\ndef b(n):\n pass |
291 E303: def a():\n pass\n\n\n\ndef b(n):\n pass |
278 E303: def a():\n\n\n\n pass |
292 E303: def a():\n\n\n\n pass |
279 E304: @decorator\n\ndef a():\n pass |
293 E304: @decorator\n\ndef a():\n pass |
280 E305: def a():\n pass\na() |
294 E305: def a():\n pass\na() |
|
295 E306: def a():\n def b():\n pass\n def c():\n pass |
281 """ |
296 """ |
282 if line_number < 3 and not previous_logical: |
297 if line_number < 3 and not previous_logical: |
283 return # Don't expect blank lines before the first line |
298 return # Don't expect blank lines before the first line |
284 if previous_logical.startswith('@'): |
299 if previous_logical.startswith('@'): |
285 if blank_lines: |
300 if blank_lines: |
286 yield 0, "E304 blank lines found after function decorator" |
301 yield 0, "E304 blank lines found after function decorator" |
287 elif blank_lines > 2 or (indent_level and blank_lines == 2): |
302 elif blank_lines > 2 or (indent_level and blank_lines == 2): |
288 yield 0, "E303 too many blank lines (%d)", blank_lines |
303 yield 0, "E303 too many blank lines (%d)", blank_lines |
289 elif logical_line.startswith(('def ', 'async def ', 'class ', '@')): |
304 elif STARTSWITH_TOP_LEVEL_REGEX.match(logical_line): |
290 if indent_level: |
305 if indent_level: |
291 if not (blank_before or previous_indent_level < indent_level or |
306 if not (blank_before or previous_indent_level < indent_level or |
292 DOCSTRING_REGEX.match(previous_logical)): |
307 DOCSTRING_REGEX.match(previous_logical)): |
293 ancestor_level = indent_level |
308 ancestor_level = indent_level |
294 nested = False |
309 nested = False |
825 """ |
840 """ |
826 parens = 0 |
841 parens = 0 |
827 no_space = False |
842 no_space = False |
828 prev_end = None |
843 prev_end = None |
829 annotated_func_arg = False |
844 annotated_func_arg = False |
830 in_def = logical_line.startswith(('def', 'async def')) |
845 in_def = bool(STARTSWITH_DEF_REGEX.match(logical_line)) |
831 message = "E251 unexpected spaces around keyword / parameter equals" |
846 message = "E251 unexpected spaces around keyword / parameter equals" |
832 for token_type, text, start, end, line in tokens: |
847 for token_type, text, start, end, line in tokens: |
833 if token_type == tokenize.NL: |
848 if token_type == tokenize.NL: |
834 continue |
849 continue |
835 if no_space: |
850 if no_space: |
954 return |
969 return |
955 line = logical_line |
970 line = logical_line |
956 if line.startswith('import ') or line.startswith('from '): |
971 if line.startswith('import ') or line.startswith('from '): |
957 if checker_state.get('seen_non_imports', False): |
972 if checker_state.get('seen_non_imports', False): |
958 yield 0, "E402 module level import not at top of file" |
973 yield 0, "E402 module level import not at top of file" |
|
974 elif re.match(DUNDER_REGEX, line): |
|
975 return |
959 elif any(line.startswith(kw) for kw in allowed_try_keywords): |
976 elif any(line.startswith(kw) for kw in allowed_try_keywords): |
960 # Allow try, except, else, finally keywords intermixed with imports in |
977 # Allow try, except, else, finally keywords intermixed with imports in |
961 # order to support conditional importing |
978 # order to support conditional importing |
962 return |
979 return |
963 elif is_string_literal(line): |
980 elif is_string_literal(line): |
994 E701: finally: cleanup() |
1011 E701: finally: cleanup() |
995 E701: if foo == 'blah': one(); two(); three() |
1012 E701: if foo == 'blah': one(); two(); three() |
996 E702: do_one(); do_two(); do_three() |
1013 E702: do_one(); do_two(); do_three() |
997 E703: do_four(); # useless semicolon |
1014 E703: do_four(); # useless semicolon |
998 E704: def f(x): return 2*x |
1015 E704: def f(x): return 2*x |
999 E705: async def f(x): return 2*x |
|
1000 E731: f = lambda x: 2*x |
1016 E731: f = lambda x: 2*x |
1001 """ |
1017 """ |
1002 line = logical_line |
1018 line = logical_line |
1003 last_char = len(line) - 1 |
1019 last_char = len(line) - 1 |
1004 found = line.find(':') |
1020 found = line.find(':') |
1014 before = line[:lambda_kw.start()].rstrip() |
1030 before = line[:lambda_kw.start()].rstrip() |
1015 if before[-1:] == '=' and isidentifier(before[:-1].strip()): |
1031 if before[-1:] == '=' and isidentifier(before[:-1].strip()): |
1016 yield 0, ("E731 do not assign a lambda expression, use a " |
1032 yield 0, ("E731 do not assign a lambda expression, use a " |
1017 "def") |
1033 "def") |
1018 break |
1034 break |
1019 if line.startswith('def '): |
1035 if STARTSWITH_DEF_REGEX.match(line): |
1020 yield 0, "E704 multiple statements on one line (def)" |
1036 yield 0, "E704 multiple statements on one line (def)" |
1021 elif line.startswith('async def '): |
1037 elif STARTSWITH_INDENT_STATEMENT_REGEX.match(line): |
1022 yield 0, "E705 multiple statements on one line (async def)" |
|
1023 else: |
|
1024 yield found, "E701 multiple statements on one line (colon)" |
1038 yield found, "E701 multiple statements on one line (colon)" |
1025 prev_found = found |
1039 prev_found = found |
1026 found = line.find(':', found + 1) |
1040 found = line.find(':', found + 1) |
1027 found = line.find(';') |
1041 found = line.find(';') |
1028 while -1 < found: |
1042 while -1 < found: |