Plugins/CheckerPlugins/CodeStyleChecker/pycodestyle.py

changeset 5509
d4c4763b46ee
parent 5435
44a6fc2828bc
child 6048
82ad8ec9548c
equal deleted inserted replaced
5498:6a5a3c2097cc 5509:d4c4763b46ee
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:

eric ide

mercurial