Plugins/CheckerPlugins/Pep8/pep8.py

branch
Py2 comp.
changeset 2911
ce77f0b1ee67
parent 2847
1843ef6e2656
parent 2866
c77e08c38a5c
child 3056
9986ec0e559a
equal deleted inserted replaced
2847:1843ef6e2656 2911:ce77f0b1ee67
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 2
3 # 3 #
4 # pep8.py - Check Python source code formatting, according to PEP 8 4 # pep8.py - Check Python source code formatting, according to PEP 8
5 # Copyright (C) 2006 Johann C. Rocholl <johann@rocholl.net> 5 # Copyright (C) 2006-2009 Johann C. Rocholl <johann@rocholl.net>
6 # Copyright (C) 2009-2013 Florent Xicluna <florent.xicluna@gmail.com>
6 # 7 #
7 # Permission is hereby granted, free of charge, to any person 8 # Permission is hereby granted, free of charge, to any person
8 # obtaining a copy of this software and associated documentation files 9 # obtaining a copy of this software and associated documentation files
9 # (the "Software"), to deal in the Software without restriction, 10 # (the "Software"), to deal in the Software without restriction,
10 # including without limitation the rights to use, copy, modify, merge, 11 # including without limitation the rights to use, copy, modify, merge,
42 300 blank lines 43 300 blank lines
43 400 imports 44 400 imports
44 500 line length 45 500 line length
45 600 deprecation 46 600 deprecation
46 700 statements 47 700 statements
47 900 processing errors 48 900 syntax error
48
49 You can add checks to this program by writing plugins. Each plugin is
50 a simple function that is called for each line of source code, either
51 physical or logical.
52
53 Physical line:
54 - Raw line of text from the input file.
55
56 Logical line:
57 - Multi-line statements converted to a single line.
58 - Stripped left and right.
59 - Contents of strings replaced with 'xxx' of same length.
60 - Comments removed.
61
62 The check function requests physical or logical lines by the name of
63 the first argument:
64
65 def maximum_line_length(physical_line)
66 def extraneous_whitespace(logical_line)
67 def blank_lines(logical_line, blank_lines, indent_level, line_number)
68
69 The last example above demonstrates how check plugins can request
70 additional information with extra arguments. All attributes of the
71 Checker object are available. Some examples:
72
73 lines: a list of the raw lines from the input file
74 tokens: the tokens that contribute to this logical line
75 line_number: line number in the input file
76 blank_lines: blank lines before this one
77 indent_char: first indentation character in this file (' ' or '\t')
78 indent_level: indentation (with tabs expanded to multiples of 8)
79 previous_indent_level: indentation on previous line
80 previous_logical: previous logical line
81
82 The docstring of each check function shall be the relevant part of
83 text from PEP 8. It is printed if the user enables --show-pep8.
84 Several docstrings contain examples directly from the PEP 8 document.
85
86 Okay: spam(ham[1], {eggs: 2})
87 E201: spam( ham[1], {eggs: 2})
88
89 These examples are verified automatically when pep8.py is run with the
90 --doctest option. You can add examples for your own check functions.
91 The format is simple: "Okay" or error/warning code followed by colon
92 and space, the rest of the line is example source code. If you put 'r'
93 before the docstring, you can use \n for newline, \t for tab and \s
94 for space.
95
96 """ 49 """
97 50
98 # 51 #
99 # This is a modified version to make the original tabnanny better suitable 52 # This is a modified version to make the original pep8.py better suitable
100 # for being called from within the eric5 IDE. The modifications are as 53 # for being called from within the eric5 IDE. The modifications are as
101 # follows: 54 # follows:
102 # 55 #
103 # - made messages translatable via Qt 56 # - made messages translatable via Qt
57 # - added code for eric5 integration
104 # 58 #
105 # Copyright (c) 2011 - 2013 Detlev Offenbach <detlev@die-offenbachs.de> 59 # Copyright (c) 2011 - 2013 Detlev Offenbach <detlev@die-offenbachs.de>
106 # 60 #
107 61
108 __version__ = '0.6.1' 62 __version__ = '1.4.6'
109 63
110 import os 64 import os
111 import sys 65 import sys
112 import re 66 import re
113 import time 67 import time
115 import keyword 69 import keyword
116 import tokenize 70 import tokenize
117 from optparse import OptionParser 71 from optparse import OptionParser
118 from fnmatch import fnmatch 72 from fnmatch import fnmatch
119 try: 73 try:
120 frozenset 74 from configparser import RawConfigParser
121 except NameError: 75 from io import TextIOWrapper
122 from sets import ImmutableSet as frozenset 76 except ImportError:
77 from ConfigParser import RawConfigParser # __IGNORE_WARNING__
123 78
124 from PyQt4.QtCore import QCoreApplication, QT_TRANSLATE_NOOP 79 from PyQt4.QtCore import QCoreApplication, QT_TRANSLATE_NOOP
125 80
126 DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git' 81 DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__'
127 DEFAULT_IGNORE = 'E24' 82 DEFAULT_IGNORE = 'E123,E226,E24'
83 if sys.platform == 'win32':
84 DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8')
85 else:
86 DEFAULT_CONFIG = os.path.join(os.getenv('XDG_CONFIG_HOME') or
87 os.path.expanduser('~/.config'), 'pep8')
88 PROJECT_CONFIG = ('setup.cfg', 'tox.ini', '.pep8')
89 TESTSUITE_PATH = os.path.join(os.path.dirname(__file__), 'testsuite')
128 MAX_LINE_LENGTH = 79 90 MAX_LINE_LENGTH = 79
91 REPORT_FORMAT = {
92 'default': '%(path)s:%(row)d:%(col)d: %(code)s %(text)s',
93 'pylint': '%(path)s:%(row)d: [%(code)s] %(text)s',
94 }
95
96 PyCF_ONLY_AST = 1024
97 SINGLETONS = frozenset(['False', 'None', 'True'])
98 KEYWORDS = frozenset(keyword.kwlist + ['print']) - SINGLETONS
99 UNARY_OPERATORS = frozenset(['>>', '**', '*', '+', '-'])
100 ARITHMETIC_OP = frozenset(['**', '*', '/', '//', '+', '-'])
101 WS_OPTIONAL_OPERATORS = ARITHMETIC_OP.union(['^', '&', '|', '<<', '>>', '%'])
102 WS_NEEDED_OPERATORS = frozenset([
103 '**=', '*=', '/=', '//=', '+=', '-=', '!=', '<>', '<', '>',
104 '%=', '^=', '&=', '|=', '==', '<=', '>=', '<<=', '>>=', '='])
105 WHITESPACE = frozenset(' \t')
106 SKIP_TOKENS = frozenset([tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE,
107 tokenize.INDENT, tokenize.DEDENT])
108 BENCHMARK_KEYS = ['directories', 'files', 'logical lines', 'physical lines']
129 109
130 INDENT_REGEX = re.compile(r'([ \t]*)') 110 INDENT_REGEX = re.compile(r'([ \t]*)')
131 RAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*(,)') 111 RAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*,')
132 SELFTEST_REGEX = re.compile(r'(Okay|[EW]\d{3}):\s(.*)') 112 RERAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*,\s*\w+\s*,\s*\w+')
133 ERRORCODE_REGEX = re.compile(r'[EW]\d{3}') 113 ERRORCODE_REGEX = re.compile(r'\b[A-Z]\d{3}\b')
134 DOCSTRING_REGEX = re.compile(r'u?r?["\']') 114 DOCSTRING_REGEX = re.compile(r'u?r?["\']')
135 WHITESPACE_AROUND_OPERATOR_REGEX = \
136 re.compile('([^\w\s]*)\s*(\t| )\s*([^\w\s]*)')
137 EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[[({] | []}),;:]') 115 EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[[({] | []}),;:]')
138 WHITESPACE_AROUND_NAMED_PARAMETER_REGEX = \ 116 WHITESPACE_AFTER_COMMA_REGEX = re.compile(r'[,;:]\s*(?: |\t)')
139 re.compile(r'[()]|\s=[^=]|[^=!<>]=\s') 117 COMPARE_SINGLETON_REGEX = re.compile(r'([=!]=)\s*(None|False|True)')
140 118 COMPARE_TYPE_REGEX = re.compile(r'(?:[=!]=|is(?:\s+not)?)\s*type(?:s.\w+Type'
141 119 r'|\s*\(\s*([^)]*[^ )])\s*\))')
142 WHITESPACE = ' \t' 120 KEYWORD_REGEX = re.compile(r'(\s*)\b(?:%s)\b(\s*)' % r'|'.join(KEYWORDS))
143 121 OPERATOR_REGEX = re.compile(r'(?:[^,\s])(\s*)(?:[-+*/|!<=>%&^]+)(\s*)')
144 BINARY_OPERATORS = frozenset(['**=', '*=', '+=', '-=', '!=', '<>', 122 LAMBDA_REGEX = re.compile(r'\blambda\b')
145 '%=', '^=', '&=', '|=', '==', '/=', '//=', '<=', '>=', '<<=', '>>=', 123 HUNK_REGEX = re.compile(r'^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@.*$')
146 '%', '^', '&', '|', '=', '/', '//', '<', '>', '<<']) 124
147 UNARY_OPERATORS = frozenset(['>>', '**', '*', '+', '-']) 125 # Work around Python < 2.6 behaviour, which does not generate NL after
148 OPERATORS = BINARY_OPERATORS | UNARY_OPERATORS 126 # a comment which is on a line by itself.
149 SKIP_TOKENS = frozenset([tokenize.COMMENT, tokenize.NL, tokenize.INDENT, 127 COMMENT_WITH_NL = tokenize.generate_tokens(['#\n'].pop).send(None)[1] == '#\n'
150 tokenize.DEDENT, tokenize.NEWLINE])
151 E225NOT_KEYWORDS = (frozenset(keyword.kwlist + ['print']) -
152 frozenset(['False', 'None', 'True']))
153 BENCHMARK_KEYS = ('directories', 'files', 'logical lines', 'physical lines')
154
155 options = None
156 args = None
157 128
158 129
159 ############################################################################## 130 ##############################################################################
160 # Helper functions for translated and formatted messages 131 # Helper functions for translated and formatted messages
161 ############################################################################## 132 ##############################################################################
168 "indentation is not a multiple of four"), 139 "indentation is not a multiple of four"),
169 "E112": QT_TRANSLATE_NOOP("pep8", 140 "E112": QT_TRANSLATE_NOOP("pep8",
170 "expected an indented block"), 141 "expected an indented block"),
171 "E113": QT_TRANSLATE_NOOP("pep8", 142 "E113": QT_TRANSLATE_NOOP("pep8",
172 "unexpected indentation"), 143 "unexpected indentation"),
144 "E121": QT_TRANSLATE_NOOP("pep8",
145 "continuation line indentation is not a multiple of four"),
146 "E122": QT_TRANSLATE_NOOP("pep8",
147 "continuation line missing indentation or outdented"),
148 "E123": QT_TRANSLATE_NOOP("pep8",
149 "closing bracket does not match indentation of opening bracket's line"),
150 "E124": QT_TRANSLATE_NOOP("pep8",
151 "closing bracket does not match visual indentation"),
152 "E125": QT_TRANSLATE_NOOP("pep8",
153 "continuation line does not distinguish itself from next logical line"),
154 "E126": QT_TRANSLATE_NOOP("pep8",
155 "continuation line over-indented for hanging indent"),
156 "E127": QT_TRANSLATE_NOOP("pep8",
157 "continuation line over-indented for visual indent"),
158 "E128": QT_TRANSLATE_NOOP("pep8",
159 "continuation line under-indented for visual indent"),
160 "E133": QT_TRANSLATE_NOOP("pep8",
161 "closing bracket is missing indentation"),
173 "W191": QT_TRANSLATE_NOOP("pep8", 162 "W191": QT_TRANSLATE_NOOP("pep8",
174 "indentation contains tabs"), 163 "indentation contains tabs"),
175 "E201": QT_TRANSLATE_NOOP("pep8", 164 "E201": QT_TRANSLATE_NOOP("pep8",
176 "whitespace after '{0}'"), 165 "whitespace after '{0}'"),
177 "E202": QT_TRANSLATE_NOOP("pep8", 166 "E202": QT_TRANSLATE_NOOP("pep8",
188 "tab before operator"), 177 "tab before operator"),
189 "E224": QT_TRANSLATE_NOOP("pep8", 178 "E224": QT_TRANSLATE_NOOP("pep8",
190 "tab after operator"), 179 "tab after operator"),
191 "E225": QT_TRANSLATE_NOOP("pep8", 180 "E225": QT_TRANSLATE_NOOP("pep8",
192 "missing whitespace around operator"), 181 "missing whitespace around operator"),
182 "E226": QT_TRANSLATE_NOOP("pep8",
183 "missing whitespace around arithmetic operator"),
184 "E227": QT_TRANSLATE_NOOP("pep8",
185 "missing whitespace around bitwise or shift operator"),
186 "E228": QT_TRANSLATE_NOOP("pep8",
187 "missing whitespace around modulo operator"),
193 "E231": QT_TRANSLATE_NOOP("pep8", 188 "E231": QT_TRANSLATE_NOOP("pep8",
194 "missing whitespace after '{0}'"), 189 "missing whitespace after '{0}'"),
195 "E241": QT_TRANSLATE_NOOP("pep8", 190 "E241": QT_TRANSLATE_NOOP("pep8",
196 "multiple spaces after '{0}'"), 191 "multiple spaces after '{0}'"),
197 "E242": QT_TRANSLATE_NOOP("pep8", 192 "E242": QT_TRANSLATE_NOOP("pep8",
198 "tab after '{0}'"), 193 "tab after '{0}'"),
199 "E251": QT_TRANSLATE_NOOP("pep8", 194 "E251": QT_TRANSLATE_NOOP("pep8",
200 "no spaces around keyword / parameter equals"), 195 "unexpected spaces around keyword / parameter equals"),
201 "E261": QT_TRANSLATE_NOOP("pep8", 196 "E261": QT_TRANSLATE_NOOP("pep8",
202 "at least two spaces before inline comment"), 197 "at least two spaces before inline comment"),
203 "E262": QT_TRANSLATE_NOOP("pep8", 198 "E262": QT_TRANSLATE_NOOP("pep8",
204 "inline comment should start with '# '"), 199 "inline comment should start with '# '"),
200 "E271": QT_TRANSLATE_NOOP("pep8",
201 "multiple spaces after keyword"),
202 "E272": QT_TRANSLATE_NOOP("pep8",
203 "multiple spaces before keyword"),
204 "E273": QT_TRANSLATE_NOOP("pep8",
205 "tab after keyword"),
206 "E274": QT_TRANSLATE_NOOP("pep8",
207 "tab before keyword"),
205 "W291": QT_TRANSLATE_NOOP("pep8", 208 "W291": QT_TRANSLATE_NOOP("pep8",
206 "trailing whitespace"), 209 "trailing whitespace"),
207 "W292": QT_TRANSLATE_NOOP("pep8", 210 "W292": QT_TRANSLATE_NOOP("pep8",
208 "no newline at end of file"), 211 "no newline at end of file"),
209 "W293": QT_TRANSLATE_NOOP("pep8", 212 "W293": QT_TRANSLATE_NOOP("pep8",
219 "W391": QT_TRANSLATE_NOOP("pep8", 222 "W391": QT_TRANSLATE_NOOP("pep8",
220 "blank line at end of file"), 223 "blank line at end of file"),
221 "E401": QT_TRANSLATE_NOOP("pep8", 224 "E401": QT_TRANSLATE_NOOP("pep8",
222 "multiple imports on one line"), 225 "multiple imports on one line"),
223 "E501": QT_TRANSLATE_NOOP("pep8", 226 "E501": QT_TRANSLATE_NOOP("pep8",
224 "line too long ({0} characters)"), 227 "line too long ({0} > {1} characters)"),
228 "E502": QT_TRANSLATE_NOOP("pep8",
229 "the backslash is redundant between brackets"),
225 "W601": QT_TRANSLATE_NOOP("pep8", 230 "W601": QT_TRANSLATE_NOOP("pep8",
226 ".has_key() is deprecated, use 'in'"), 231 ".has_key() is deprecated, use 'in'"),
227 "W602": QT_TRANSLATE_NOOP("pep8", 232 "W602": QT_TRANSLATE_NOOP("pep8",
228 "deprecated form of raising exception"), 233 "deprecated form of raising exception"),
229 "W603": QT_TRANSLATE_NOOP("pep8", 234 "W603": QT_TRANSLATE_NOOP("pep8",
232 "backticks are deprecated, use 'repr()'"), 237 "backticks are deprecated, use 'repr()'"),
233 "E701": QT_TRANSLATE_NOOP("pep8", 238 "E701": QT_TRANSLATE_NOOP("pep8",
234 "multiple statements on one line (colon)"), 239 "multiple statements on one line (colon)"),
235 "E702": QT_TRANSLATE_NOOP("pep8", 240 "E702": QT_TRANSLATE_NOOP("pep8",
236 "multiple statements on one line (semicolon)"), 241 "multiple statements on one line (semicolon)"),
242 "E703": QT_TRANSLATE_NOOP("pep8",
243 "statement ends with a semicolon"),
244 "E711": QT_TRANSLATE_NOOP("pep8",
245 "comparison to {0} should be {1}"),
246 "E712": QT_TRANSLATE_NOOP("pep8",
247 "comparison to {0} should be {1}"),
248 "E721": QT_TRANSLATE_NOOP("pep8",
249 "do not compare types, use 'isinstance()'"),
237 "E901": QT_TRANSLATE_NOOP("pep8", 250 "E901": QT_TRANSLATE_NOOP("pep8",
238 "Token Error: {0}"), 251 "{0}: {1}"),
239 } 252 }
240 253
241 pep8_messages_sample_args = { 254 pep8_messages_sample_args = {
242 "E201": ["([{"], 255 "E201": ["([{"],
243 "E202": ["}])"], 256 "E202": ["}])"],
246 "E231": [",;:"], 259 "E231": [",;:"],
247 "E241": [",;:"], 260 "E241": [",;:"],
248 "E242": [",;:"], 261 "E242": [",;:"],
249 "E302": [1], 262 "E302": [1],
250 "E303": [3], 263 "E303": [3],
251 "E501": [85], 264 "E501": [85, 79],
265 "E711": ["None", "'if cond is None:'"],
266 "E712": ["True", "'if cond is True:' or 'if cond:'"],
267 "E901": ["SyntaxError", "Invalid Syntax"],
252 } 268 }
253 269
254 270
255 def getMessage(code, *args): 271 def getMessage(code, *args):
256 """ 272 """
299 315
300 Okay: if True:\n return 316 Okay: if True:\n return
301 W191: if True:\n\treturn 317 W191: if True:\n\treturn
302 """ 318 """
303 indent = INDENT_REGEX.match(physical_line).group(1) 319 indent = INDENT_REGEX.match(physical_line).group(1)
304 if indent.count('\t'): 320 if '\t' in indent:
305 return indent.index('\t'), "W191" 321 return indent.index('\t'), "W191"
306 322
307 323
308 def trailing_whitespace(physical_line): 324 def trailing_whitespace(physical_line):
309 r""" 325 r"""
318 [1] http://docs.python.org/reference/lexical_analysis.html#blank-lines 334 [1] http://docs.python.org/reference/lexical_analysis.html#blank-lines
319 335
320 The warning returned varies on whether the line itself is blank, for easier 336 The warning returned varies on whether the line itself is blank, for easier
321 filtering for those who want to indent their blank lines. 337 filtering for those who want to indent their blank lines.
322 338
323 Okay: spam(1) 339 Okay: spam(1)\n#
324 W291: spam(1)\s 340 W291: spam(1) \n#
325 W293: class Foo(object):\n \n bang = 12 341 W293: class Foo(object):\n \n bang = 12
326 """ 342 """
327 physical_line = physical_line.rstrip('\n') # chr(10), newline 343 physical_line = physical_line.rstrip('\n') # chr(10), newline
328 physical_line = physical_line.rstrip('\r') # chr(13), carriage return 344 physical_line = physical_line.rstrip('\r') # chr(13), carriage return
329 physical_line = physical_line.rstrip('\x0c') # chr(12), form feed, ^L 345 physical_line = physical_line.rstrip('\x0c') # chr(12), form feed, ^L
330 stripped = physical_line.rstrip() 346 stripped = physical_line.rstrip(' \t\v')
331 if physical_line != stripped: 347 if physical_line != stripped:
332 if stripped: 348 if stripped:
333 return len(stripped), "W291" 349 return len(stripped), "W291"
334 else: 350 else:
335 return 0, "W293" 351 return 0, "W293"
340 JCR: Trailing blank lines are superfluous. 356 JCR: Trailing blank lines are superfluous.
341 357
342 Okay: spam(1) 358 Okay: spam(1)
343 W391: spam(1)\n 359 W391: spam(1)\n
344 """ 360 """
345 if physical_line.strip() == '' and line_number == len(lines): 361 if not physical_line.rstrip() and line_number == len(lines):
346 return 0, "W391" 362 return 0, "W391"
347 363
348 364
349 def missing_newline(physical_line): 365 def missing_newline(physical_line):
350 """ 366 """
351 JCR: The last line should have a newline. 367 JCR: The last line should have a newline.
368
369 Reports warning W292.
352 """ 370 """
353 if physical_line.rstrip() == physical_line: 371 if physical_line.rstrip() == physical_line:
354 return len(physical_line), "W292" 372 return len(physical_line), "W292"
355 373
356 374
357 def maximum_line_length(physical_line): 375 def maximum_line_length(physical_line, max_line_length):
358 """ 376 """
359 Limit all lines to a maximum of 79 characters. 377 Limit all lines to a maximum of 79 characters.
360 378
361 There are still many devices around that are limited to 80 character 379 There are still many devices around that are limited to 80 character
362 lines; plus, limiting windows to 80 characters makes it possible to have 380 lines; plus, limiting windows to 80 characters makes it possible to have
363 several windows side-by-side. The default wrapping on such devices looks 381 several windows side-by-side. The default wrapping on such devices looks
364 ugly. Therefore, please limit all lines to a maximum of 79 characters. 382 ugly. Therefore, please limit all lines to a maximum of 79 characters.
365 For flowing long blocks of text (docstrings or comments), limiting the 383 For flowing long blocks of text (docstrings or comments), limiting the
366 length to 72 characters is recommended. 384 length to 72 characters is recommended.
385
386 Reports error E501.
367 """ 387 """
368 line = physical_line.rstrip() 388 line = physical_line.rstrip()
369 length = len(line) 389 length = len(line)
370 try: 390 if length > max_line_length and not noqa(line):
391 if hasattr(line, 'decode'): # Python 2
371 # The line could contain multi-byte characters 392 # The line could contain multi-byte characters
372 if hasattr(line, 'decode'): # Python 2 only 393 try:
373 length = len(line.decode('utf-8')) 394 length = len(line.decode('utf-8'))
374 except (UnicodeDecodeError, UnicodeEncodeError): 395 except (UnicodeDecodeError, UnicodeEncodeError):
375 pass 396 pass
376 if length > MAX_LINE_LENGTH: 397 if length > max_line_length:
377 return MAX_LINE_LENGTH, "E501", length 398 return max_line_length, "E501", length, max_line_length
378 399
379 400
380 ############################################################################## 401 ##############################################################################
381 # Plugins (check functions) for logical lines 402 # Plugins (check functions) for logical lines
382 ############################################################################## 403 ##############################################################################
383 404
384 405
385 def blank_lines(logical_line, blank_lines, indent_level, line_number, 406 def blank_lines(logical_line, blank_lines, indent_level, line_number,
386 previous_logical, previous_indent_level, 407 previous_logical, previous_indent_level):
387 blank_lines_before_comment):
388 r""" 408 r"""
389 Separate top-level function and class definitions with two blank lines. 409 Separate top-level function and class definitions with two blank lines.
390 410
391 Method definitions inside a class are separated by a single blank line. 411 Method definitions inside a class are separated by a single blank line.
392 412
403 E302: def a():\n pass\n\ndef b(n):\n pass 423 E302: def a():\n pass\n\ndef b(n):\n pass
404 E303: def a():\n pass\n\n\n\ndef b(n):\n pass 424 E303: def a():\n pass\n\n\n\ndef b(n):\n pass
405 E303: def a():\n\n\n\n pass 425 E303: def a():\n\n\n\n pass
406 E304: @decorator\n\ndef a():\n pass 426 E304: @decorator\n\ndef a():\n pass
407 """ 427 """
408 if line_number == 1: 428 if line_number < 3 and not previous_logical:
409 return # Don't expect blank lines before the first line 429 return # Don't expect blank lines before the first line
410 max_blank_lines = max(blank_lines, blank_lines_before_comment)
411 if previous_logical.startswith('@'): 430 if previous_logical.startswith('@'):
412 if max_blank_lines: 431 if blank_lines:
413 return 0, "E304" 432 yield 0, "E304"
414 elif (logical_line.startswith('def ') or 433 elif blank_lines > 2 or (indent_level and blank_lines == 2):
415 logical_line.startswith('class ') or 434 yield 0, "E303", blank_lines
416 logical_line.startswith('@')): 435 elif logical_line.startswith(('def ', 'class ', '@')):
417 if indent_level: 436 if indent_level:
418 if not (max_blank_lines or previous_indent_level < indent_level or 437 if not (blank_lines or previous_indent_level < indent_level or
419 DOCSTRING_REGEX.match(previous_logical)): 438 DOCSTRING_REGEX.match(previous_logical)):
420 return 0, "E301" 439 yield 0, "E301"
421 elif max_blank_lines != 2: 440 elif blank_lines != 2:
422 return 0, "E302", max_blank_lines 441 yield 0, "E302", blank_lines
423 elif max_blank_lines > 2 or (indent_level and max_blank_lines == 2):
424 return 0, "E303", max_blank_lines
425 442
426 443
427 def extraneous_whitespace(logical_line): 444 def extraneous_whitespace(logical_line):
428 """ 445 """
429 Avoid extraneous whitespace in the following situations: 446 Avoid extraneous whitespace in the following situations:
447 line = logical_line 464 line = logical_line
448 for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line): 465 for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line):
449 text = match.group() 466 text = match.group()
450 char = text.strip() 467 char = text.strip()
451 found = match.start() 468 found = match.start()
452 if text == char + ' ' and char in '([{': 469 if text == char + ' ':
453 return found + 1, "E201", char 470 # assert char in '([{'
454 if text == ' ' + char and line[found - 1] != ',': 471 yield found + 1, "E201", char
455 if char in '}])': 472 elif line[found - 1] != ',':
456 return found, "E202", char 473 code = ('E202' if char in '}])' else 'E203') # if char in ',;:'
457 if char in ',;:': 474 yield found, code, char
458 return found, "E203", char 475
476
477 def whitespace_around_keywords(logical_line):
478 r"""
479 Avoid extraneous whitespace around keywords.
480
481 Okay: True and False
482 E271: True and False
483 E272: True and False
484 E273: True and\tFalse
485 E274: True\tand False
486 """
487 for match in KEYWORD_REGEX.finditer(logical_line):
488 before, after = match.groups()
489
490 if '\t' in before:
491 yield match.start(1), "E274"
492 elif len(before) > 1:
493 yield match.start(1), "E272"
494
495 if '\t' in after:
496 yield match.start(2), "E273"
497 elif len(after) > 1:
498 yield match.start(2), "E271"
459 499
460 500
461 def missing_whitespace(logical_line): 501 def missing_whitespace(logical_line):
462 """ 502 """
463 JCR: Each comma, semicolon or colon should be followed by whitespace. 503 JCR: Each comma, semicolon or colon should be followed by whitespace.
468 Okay: a[:4] 508 Okay: a[:4]
469 Okay: a[1:] 509 Okay: a[1:]
470 Okay: a[1:4:2] 510 Okay: a[1:4:2]
471 E231: ['a','b'] 511 E231: ['a','b']
472 E231: foo(bar,baz) 512 E231: foo(bar,baz)
513 E231: [{'a':'b'}]
473 """ 514 """
474 line = logical_line 515 line = logical_line
475 for index in range(len(line) - 1): 516 for index in range(len(line) - 1):
476 char = line[index] 517 char = line[index]
477 if char in ',;:' and line[index + 1] not in WHITESPACE: 518 if char in ',;:' and line[index + 1] not in WHITESPACE:
478 before = line[:index] 519 before = line[:index]
479 if char == ':' and before.count('[') > before.count(']'): 520 if char == ':' and before.count('[') > before.count(']') and \
521 before.rfind('{') < before.rfind('['):
480 continue # Slice syntax, no space required 522 continue # Slice syntax, no space required
481 if char == ',' and line[index + 1] == ')': 523 if char == ',' and line[index + 1] == ')':
482 continue # Allow tuple with only one element: (3,) 524 continue # Allow tuple with only one element: (3,)
483 return index, "E231", char 525 yield index, "E231", char
484 526
485 527
486 def indentation(logical_line, previous_logical, indent_char, 528 def indentation(logical_line, previous_logical, indent_char,
487 indent_level, previous_indent_level): 529 indent_level, previous_indent_level):
488 r""" 530 r"""
500 542
501 Okay: a = 1\nb = 2 543 Okay: a = 1\nb = 2
502 E113: a = 1\n b = 2 544 E113: a = 1\n b = 2
503 """ 545 """
504 if indent_char == ' ' and indent_level % 4: 546 if indent_char == ' ' and indent_level % 4:
505 return 0, "E111" 547 yield 0, "E111"
506 indent_expect = previous_logical.endswith(':') 548 indent_expect = previous_logical.endswith(':')
507 if indent_expect and indent_level <= previous_indent_level: 549 if indent_expect and indent_level <= previous_indent_level:
508 return 0, "E112" 550 yield 0, "E112"
509 if indent_level > previous_indent_level and not indent_expect: 551 if indent_level > previous_indent_level and not indent_expect:
510 return 0, "E113" 552 yield 0, "E113"
553
554
555 def continued_indentation(logical_line, tokens, indent_level, hang_closing,
556 noqa, verbose):
557 r"""
558 Continuation lines should align wrapped elements either vertically using
559 Python's implicit line joining inside parentheses, brackets and braces, or
560 using a hanging indent.
561
562 When using a hanging indent the following considerations should be applied:
563
564 - there should be no arguments on the first line, and
565
566 - further indentation should be used to clearly distinguish itself as a
567 continuation line.
568
569 Okay: a = (\n)
570 E123: a = (\n )
571
572 Okay: a = (\n 42)
573 E121: a = (\n 42)
574 E122: a = (\n42)
575 E123: a = (\n 42\n )
576 E124: a = (24,\n 42\n)
577 E125: if (a or\n b):\n pass
578 E126: a = (\n 42)
579 E127: a = (24,\n 42)
580 E128: a = (24,\n 42)
581 """
582 first_row = tokens[0][2][0]
583 nrows = 1 + tokens[-1][2][0] - first_row
584 if noqa or nrows == 1:
585 return
586
587 # indent_next tells us whether the next block is indented; assuming
588 # that it is indented by 4 spaces, then we should not allow 4-space
589 # indents on the final continuation line; in turn, some other
590 # indents are allowed to have an extra 4 spaces.
591 indent_next = logical_line.endswith(':')
592
593 row = depth = 0
594 # remember how many brackets were opened on each line
595 parens = [0] * nrows
596 # relative indents of physical lines
597 rel_indent = [0] * nrows
598 # visual indents
599 indent_chances = {}
600 last_indent = tokens[0][2]
601 indent = [last_indent[1]]
602 if verbose >= 3:
603 print(">>> " + tokens[0][4].rstrip())
604
605 for token_type, text, start, end, line in tokens:
606
607 last_token_multiline = (start[0] != end[0])
608 newline = row < start[0] - first_row
609 if newline:
610 row = start[0] - first_row
611 newline = (not last_token_multiline and
612 token_type not in (tokenize.NL, tokenize.NEWLINE))
613
614 if newline:
615 # this is the beginning of a continuation line.
616 last_indent = start
617 if verbose >= 3:
618 print("... " + line.rstrip())
619
620 # record the initial indent.
621 rel_indent[row] = expand_indent(line) - indent_level
622
623 if depth:
624 # a bracket expression in a continuation line.
625 # find the line that it was opened on
626 for open_row in range(row - 1, -1, -1):
627 if parens[open_row]:
628 break
629 else:
630 # an unbracketed continuation line (ie, backslash)
631 open_row = 0
632 hang = rel_indent[row] - rel_indent[open_row]
633 close_bracket = (token_type == tokenize.OP and text in ']})')
634 visual_indent = (not close_bracket and hang > 0 and
635 indent_chances.get(start[1]))
636
637 if close_bracket and indent[depth]:
638 # closing bracket for visual indent
639 if start[1] != indent[depth]:
640 yield start, "E124"
641 elif close_bracket and not hang:
642 # closing bracket matches indentation of opening bracket's line
643 if hang_closing:
644 yield start, "E133"
645 elif visual_indent is True:
646 # visual indent is verified
647 if not indent[depth]:
648 indent[depth] = start[1]
649 elif visual_indent in (text, str):
650 # ignore token lined up with matching one from a previous line
651 pass
652 elif indent[depth] and start[1] < indent[depth]:
653 # visual indent is broken
654 yield start, "E128"
655 elif hang == 4 or (indent_next and rel_indent[row] == 8):
656 # hanging indent is verified
657 if close_bracket and not hang_closing:
658 yield (start, "E123")
659 else:
660 # indent is broken
661 if hang <= 0:
662 error = "E122"
663 elif indent[depth]:
664 error = "E127"
665 elif hang % 4:
666 error = "E121"
667 else:
668 error = "E126"
669 yield start, error
670
671 # look for visual indenting
672 if (parens[row] and token_type not in (tokenize.NL, tokenize.COMMENT)
673 and not indent[depth]):
674 indent[depth] = start[1]
675 indent_chances[start[1]] = True
676 if verbose >= 4:
677 print("bracket depth %s indent to %s" % (depth, start[1]))
678 # deal with implicit string concatenation
679 elif (token_type in (tokenize.STRING, tokenize.COMMENT) or
680 text in ('u', 'ur', 'b', 'br')):
681 indent_chances[start[1]] = str
682 # special case for the "if" statement because len("if (") == 4
683 elif not indent_chances and not row and not depth and text == 'if':
684 indent_chances[end[1] + 1] = True
685
686 # keep track of bracket depth
687 if token_type == tokenize.OP:
688 if text in '([{':
689 depth += 1
690 indent.append(0)
691 parens[row] += 1
692 if verbose >= 4:
693 print("bracket depth %s seen, col %s, visual min = %s" %
694 (depth, start[1], indent[depth]))
695 elif text in ')]}' and depth > 0:
696 # parent indents should not be more than this one
697 prev_indent = indent.pop() or last_indent[1]
698 for d in range(depth):
699 if indent[d] > prev_indent:
700 indent[d] = 0
701 for ind in list(indent_chances):
702 if ind >= prev_indent:
703 del indent_chances[ind]
704 depth -= 1
705 if depth:
706 indent_chances[indent[depth]] = True
707 for idx in range(row, -1, -1):
708 if parens[idx]:
709 parens[idx] -= 1
710 rel_indent[row] = rel_indent[idx]
711 break
712 assert len(indent) == depth + 1
713 if start[1] not in indent_chances:
714 # allow to line up tokens
715 indent_chances[start[1]] = text
716
717 if indent_next and expand_indent(line) == indent_level + 4:
718 yield last_indent, "E125"
511 719
512 720
513 def whitespace_before_parameters(logical_line, tokens): 721 def whitespace_before_parameters(logical_line, tokens):
514 """ 722 """
515 Avoid extraneous whitespace in the following situations: 723 Avoid extraneous whitespace in the following situations:
525 733
526 Okay: dict['key'] = list[index] 734 Okay: dict['key'] = list[index]
527 E211: dict ['key'] = list[index] 735 E211: dict ['key'] = list[index]
528 E211: dict['key'] = list [index] 736 E211: dict['key'] = list [index]
529 """ 737 """
530 prev_type = tokens[0][0] 738 prev_type, prev_text, __, prev_end, __ = tokens[0]
531 prev_text = tokens[0][1]
532 prev_end = tokens[0][3]
533 for index in range(1, len(tokens)): 739 for index in range(1, len(tokens)):
534 token_type, text, start, end, line = tokens[index] 740 token_type, text, start, end, __ = tokens[index]
535 if (token_type == tokenize.OP and 741 if (token_type == tokenize.OP and
536 text in '([' and 742 text in '([' and
537 start != prev_end and 743 start != prev_end and
538 (prev_type == tokenize.NAME or prev_text in '}])') and 744 (prev_type == tokenize.NAME or prev_text in '}])') and
539 # Syntax "class A (B):" is allowed, but avoid it 745 # Syntax "class A (B):" is allowed, but avoid it
540 (index < 2 or tokens[index - 2][1] != 'class') and 746 (index < 2 or tokens[index - 2][1] != 'class') and
541 # Allow "return (a.foo for a in range(5))" 747 # Allow "return (a.foo for a in range(5))"
542 (not keyword.iskeyword(prev_text))): 748 not keyword.iskeyword(prev_text)):
543 return prev_end, "E211", text 749 yield prev_end, "E211", text
544 prev_type = token_type 750 prev_type = token_type
545 prev_text = text 751 prev_text = text
546 prev_end = end 752 prev_end = end
547 753
548 754
557 E221: a = 4 + 5 763 E221: a = 4 + 5
558 E222: a = 4 + 5 764 E222: a = 4 + 5
559 E223: a = 4\t+ 5 765 E223: a = 4\t+ 5
560 E224: a = 4 +\t5 766 E224: a = 4 +\t5
561 """ 767 """
562 for match in WHITESPACE_AROUND_OPERATOR_REGEX.finditer(logical_line): 768 for match in OPERATOR_REGEX.finditer(logical_line):
563 before, whitespace, after = match.groups() 769 before, after = match.groups()
564 tab = whitespace == '\t' 770
565 offset = match.start(2) 771 if '\t' in before:
566 if before in OPERATORS: 772 yield match.start(1), "E223"
567 return offset, (tab and "E224" or "E222") 773 elif len(before) > 1:
568 elif after in OPERATORS: 774 yield match.start(1), "E221"
569 return offset, (tab and "E223" or "E221") 775
570 776 if '\t' in after:
777 yield match.start(2), "E224"
778 elif len(after) > 1:
779 yield match.start(2), "E222"
571 780
572 def missing_whitespace_around_operator(logical_line, tokens): 781 def missing_whitespace_around_operator(logical_line, tokens):
573 r""" 782 r"""
574 - Always surround these binary operators with a single space on 783 - Always surround these binary operators with a single space on
575 either side: assignment (=), augmented assignment (+=, -= etc.), 784 either side: assignment (=), augmented assignment (+=, -= etc.),
582 Okay: submitted += 1 791 Okay: submitted += 1
583 Okay: x = x * 2 - 1 792 Okay: x = x * 2 - 1
584 Okay: hypot2 = x * x + y * y 793 Okay: hypot2 = x * x + y * y
585 Okay: c = (a + b) * (a - b) 794 Okay: c = (a + b) * (a - b)
586 Okay: foo(bar, key='word', *args, **kwargs) 795 Okay: foo(bar, key='word', *args, **kwargs)
587 Okay: baz(**kwargs)
588 Okay: negative = -1
589 Okay: spam(-1)
590 Okay: alpha[:-i] 796 Okay: alpha[:-i]
591 Okay: if not -5 < x < +5:\n pass
592 Okay: lambda *args, **kw: (args, kw)
593 797
594 E225: i=i+1 798 E225: i=i+1
595 E225: submitted +=1 799 E225: submitted +=1
596 E225: x = x*2 - 1 800 E225: x = x /2 - 1
597 E225: hypot2 = x*x + y*y
598 E225: c = (a+b) * (a-b)
599 E225: c = alpha -4
600 E225: z = x **y 801 E225: z = x **y
802 E226: c = (a+b) * (a-b)
803 E226: hypot2 = x*x + y*y
804 E227: c = a|b
805 E228: msg = fmt%(errno, errmsg)
601 """ 806 """
602 parens = 0 807 parens = 0
603 need_space = False 808 need_space = False
604 prev_type = tokenize.OP 809 prev_type = tokenize.OP
605 prev_text = prev_end = None 810 prev_text = prev_end = None
606 for token_type, text, start, end, line in tokens: 811 for token_type, text, start, end, line in tokens:
607 if token_type in (tokenize.NL, tokenize.NEWLINE, tokenize.ERRORTOKEN): 812 if token_type in (tokenize.NL, tokenize.NEWLINE, tokenize.ERRORTOKEN):
608 # ERRORTOKEN is triggered by backticks in Python 3000 813 # ERRORTOKEN is triggered by backticks in Python 3
609 continue 814 continue
610 if text in ('(', 'lambda'): 815 if text in ('(', 'lambda'):
611 parens += 1 816 parens += 1
612 elif text == ')': 817 elif text == ')':
613 parens -= 1 818 parens -= 1
614 if need_space: 819 if need_space:
615 if start != prev_end: 820 if start != prev_end:
821 # Found a (probably) needed space
822 if need_space is not True and not need_space[1]:
823 yield need_space[0], "E225"
616 need_space = False 824 need_space = False
617 elif text == '>' and prev_text == '<': 825 elif text == '>' and prev_text in ('<', '-'):
618 # Tolerate the "<>" operator, even if running Python 3 826 # Tolerate the "<>" operator, even if running Python 3
827 # Deal with Python 3's annotated return value "->"
619 pass 828 pass
620 else: 829 else:
621 return prev_end, "E225" 830 if need_space is True or need_space[1]:
831 # A needed trailing space was not found
832 yield prev_end, "E225"
833 else:
834 code = 'E226'
835 if prev_text == '%':
836 code = 'E228'
837 elif prev_text not in ARITHMETIC_OP:
838 code = 'E227'
839 yield need_space[0], code
840 need_space = False
622 elif token_type == tokenize.OP and prev_end is not None: 841 elif token_type == tokenize.OP and prev_end is not None:
623 if text == '=' and parens: 842 if text == '=' and parens:
624 # Allow keyword args or defaults: foo(bar=None). 843 # Allow keyword args or defaults: foo(bar=None).
625 pass 844 pass
626 elif text in BINARY_OPERATORS: 845 elif text in WS_NEEDED_OPERATORS:
627 need_space = True 846 need_space = True
628 elif text in UNARY_OPERATORS: 847 elif text in UNARY_OPERATORS:
848 # Check if the operator is being used as a binary operator
629 # Allow unary operators: -123, -x, +1. 849 # Allow unary operators: -123, -x, +1.
630 # Allow argument unpacking: foo(*args, **kwargs). 850 # Allow argument unpacking: foo(*args, **kwargs).
631 if prev_type == tokenize.OP: 851 if prev_type == tokenize.OP:
632 if prev_text in '}])': 852 binary_usage = (prev_text in '}])')
633 need_space = True
634 elif prev_type == tokenize.NAME: 853 elif prev_type == tokenize.NAME:
635 if prev_text not in E225NOT_KEYWORDS: 854 binary_usage = (prev_text not in KEYWORDS)
636 need_space = True
637 else: 855 else:
638 need_space = True 856 binary_usage = (prev_type not in SKIP_TOKENS)
639 if need_space and start == prev_end: 857
640 return prev_end, "E225" 858 if binary_usage:
859 need_space = None
860 elif text in WS_OPTIONAL_OPERATORS:
861 need_space = None
862
863 if need_space is None:
864 # Surrounding space is optional, but ensure that
865 # trailing space matches opening space
866 need_space = (prev_end, start != prev_end)
867 elif need_space and start == prev_end:
868 # A needed opening space was not found
869 yield prev_end, "E225"
870 need_space = False
641 prev_type = token_type 871 prev_type = token_type
642 prev_text = text 872 prev_text = text
643 prev_end = end 873 prev_end = end
644 874
645 875
656 Okay: a = (1, 2) 886 Okay: a = (1, 2)
657 E241: a = (1, 2) 887 E241: a = (1, 2)
658 E242: a = (1,\t2) 888 E242: a = (1,\t2)
659 """ 889 """
660 line = logical_line 890 line = logical_line
661 for separator in ',;:': 891 for m in WHITESPACE_AFTER_COMMA_REGEX.finditer(line):
662 found = line.find(separator + ' ') 892 found = m.start() + 1
663 if found > -1: 893 if '\t' in m.group():
664 return found + 1, "E241", separator 894 yield found, "E242", m.group()[0]
665 found = line.find(separator + '\t') 895 else:
666 if found > -1: 896 yield found, "E241", m.group()[0]
667 return found + 1, "E242", separator 897
668 898
669 899 def whitespace_around_named_parameter_equals(logical_line, tokens):
670 def whitespace_around_named_parameter_equals(logical_line):
671 """ 900 """
672 Don't use spaces around the '=' sign when used to indicate a 901 Don't use spaces around the '=' sign when used to indicate a
673 keyword argument or a default parameter value. 902 keyword argument or a default parameter value.
674 903
675 Okay: def complex(real, imag=0.0): 904 Okay: def complex(real, imag=0.0):
681 910
682 E251: def complex(real, imag = 0.0): 911 E251: def complex(real, imag = 0.0):
683 E251: return magic(r = real, i = imag) 912 E251: return magic(r = real, i = imag)
684 """ 913 """
685 parens = 0 914 parens = 0
686 for match in WHITESPACE_AROUND_NAMED_PARAMETER_REGEX.finditer( 915 no_space = False
687 logical_line): 916 prev_end = None
688 text = match.group() 917 message = "E251"
689 if parens and len(text) == 3: 918 for token_type, text, start, end, line in tokens:
690 issue = "E251" 919 if no_space:
691 return match.start(), issue 920 no_space = False
692 if text == '(': 921 if start != prev_end:
693 parens += 1 922 yield prev_end, message
694 elif text == ')': 923 elif token_type == tokenize.OP:
695 parens -= 1 924 if text == '(':
925 parens += 1
926 elif text == ')':
927 parens -= 1
928 elif parens and text == '=':
929 no_space = True
930 if start != prev_end:
931 yield prev_end, message
932 prev_end = end
696 933
697 934
698 def whitespace_before_inline_comment(logical_line, tokens): 935 def whitespace_before_inline_comment(logical_line, tokens):
699 """ 936 """
700 Separate inline comments by at least two spaces. 937 Separate inline comments by at least two spaces.
709 E262: x = x + 1 #Increment x 946 E262: x = x + 1 #Increment x
710 E262: x = x + 1 # Increment x 947 E262: x = x + 1 # Increment x
711 """ 948 """
712 prev_end = (0, 0) 949 prev_end = (0, 0)
713 for token_type, text, start, end, line in tokens: 950 for token_type, text, start, end, line in tokens:
714 if token_type == tokenize.NL:
715 continue
716 if token_type == tokenize.COMMENT: 951 if token_type == tokenize.COMMENT:
717 if not line[:start[1]].strip(): 952 if not line[:start[1]].strip():
718 continue 953 continue
719 if prev_end[0] == start[0] and start[1] < prev_end[1] + 2: 954 if prev_end[0] == start[0] and start[1] < prev_end[1] + 2:
720 return (prev_end, "E261") 955 yield prev_end, "E261"
721 if (len(text) > 1 and text.startswith('# ') 956 symbol, sp, comment = text.partition(' ')
722 or not text.startswith('# ')): 957 if symbol not in ('#', '#:') or comment[:1].isspace():
723 return start, "E262" 958 yield start, "E262"
724 else: 959 elif token_type != tokenize.NL:
725 prev_end = end 960 prev_end = end
726 961
727 962
728 def imports_on_separate_lines(logical_line): 963 def imports_on_separate_lines(logical_line):
729 r""" 964 r"""
739 Okay: import foo.bar.yourclass 974 Okay: import foo.bar.yourclass
740 """ 975 """
741 line = logical_line 976 line = logical_line
742 if line.startswith('import '): 977 if line.startswith('import '):
743 found = line.find(',') 978 found = line.find(',')
744 if found > -1: 979 if -1 < found and ';' not in line[:found]:
745 return found, "E401" 980 yield found, "E401"
746 981
747 982
748 def compound_statements(logical_line): 983 def compound_statements(logical_line):
749 r""" 984 r"""
750 Compound statements (multiple statements on the same line) are 985 Compound statements (multiple statements on the same line) are
767 E701: try: something() 1002 E701: try: something()
768 E701: finally: cleanup() 1003 E701: finally: cleanup()
769 E701: if foo == 'blah': one(); two(); three() 1004 E701: if foo == 'blah': one(); two(); three()
770 1005
771 E702: do_one(); do_two(); do_three() 1006 E702: do_one(); do_two(); do_three()
1007 E703: do_four(); # useless semicolon
772 """ 1008 """
773 line = logical_line 1009 line = logical_line
1010 last_char = len(line) - 1
774 found = line.find(':') 1011 found = line.find(':')
775 if -1 < found < len(line) - 1: 1012 while -1 < found < last_char:
776 before = line[:found] 1013 before = line[:found]
777 if (before.count('{') <= before.count('}') and # {'a': 1} (dict) 1014 if (before.count('{') <= before.count('}') and # {'a': 1} (dict)
778 before.count('[') <= before.count(']') and # [1:2] (slice) 1015 before.count('[') <= before.count(']') and # [1:2] (slice)
779 not re.search(r'\blambda\b', before)): # lambda x: x 1016 before.count('(') <= before.count(')') and # (Python 3 annotation)
780 return found, "E701" 1017 not LAMBDA_REGEX.search(before)): # lambda x: x
1018 yield found, "E701"
1019 found = line.find(':', found + 1)
781 found = line.find(';') 1020 found = line.find(';')
782 if -1 < found: 1021 while -1 < found:
783 return found, "E702" 1022 if found < last_char:
1023 yield found, "E702"
1024 else:
1025 yield found, "E703"
1026 found = line.find(';', found + 1)
1027
1028
1029 def explicit_line_join(logical_line, tokens):
1030 r"""
1031 Avoid explicit line join between brackets.
1032
1033 The preferred way of wrapping long lines is by using Python's implied line
1034 continuation inside parentheses, brackets and braces. Long lines can be
1035 broken over multiple lines by wrapping expressions in parentheses. These
1036 should be used in preference to using a backslash for line continuation.
1037
1038 E502: aaa = [123, \\n 123]
1039 E502: aaa = ("bbb " \\n "ccc")
1040
1041 Okay: aaa = [123,\n 123]
1042 Okay: aaa = ("bbb "\n "ccc")
1043 Okay: aaa = "bbb " \\n "ccc"
1044 """
1045 prev_start = prev_end = parens = 0
1046 backslash = None
1047 for token_type, text, start, end, line in tokens:
1048 if start[0] != prev_start and parens and backslash:
1049 yield backslash, "E502"
1050 if end[0] != prev_end:
1051 if line.rstrip('\r\n').endswith('\\'):
1052 backslash = (end[0], len(line.splitlines()[-1]) - 1)
1053 else:
1054 backslash = None
1055 prev_start = prev_end = end[0]
1056 else:
1057 prev_start = start[0]
1058 if token_type == tokenize.OP:
1059 if text in '([{':
1060 parens += 1
1061 elif text in ')]}':
1062 parens -= 1
1063
1064
1065 def comparison_to_singleton(logical_line, noqa):
1066 """
1067 Comparisons to singletons like None should always be done
1068 with "is" or "is not", never the equality operators.
1069
1070 Okay: if arg is not None:
1071 E711: if arg != None:
1072 E712: if arg == True:
1073
1074 Also, beware of writing if x when you really mean if x is not None --
1075 e.g. when testing whether a variable or argument that defaults to None was
1076 set to some other value. The other value might have a type (such as a
1077 container) that could be false in a boolean context!
1078 """
1079 match = not noqa and COMPARE_SINGLETON_REGEX.search(logical_line)
1080 if match:
1081 same = (match.group(1) == '==')
1082 singleton = match.group(2)
1083 msg = "'if cond is %s:'" % (('' if same else 'not ') + singleton)
1084 if singleton in ('None',):
1085 code = 'E711'
1086 else:
1087 code = 'E712'
1088 nonzero = ((singleton == 'True' and same) or
1089 (singleton == 'False' and not same))
1090 msg += " or 'if %scond:'" % ('' if nonzero else 'not ')
1091 yield match.start(1), code, singleton, msg
1092
1093
1094 def comparison_type(logical_line):
1095 """
1096 Object type comparisons should always use isinstance() instead of
1097 comparing types directly.
1098
1099 Okay: if isinstance(obj, int):
1100 E721: if type(obj) is type(1):
1101
1102 When checking if an object is a string, keep in mind that it might be a
1103 unicode string too! In Python 2.3, str and unicode have a common base
1104 class, basestring, so you can do:
1105
1106 Okay: if isinstance(obj, basestring):
1107 Okay: if type(a1) is type(b1):
1108 """
1109 match = COMPARE_TYPE_REGEX.search(logical_line)
1110 if match:
1111 inst = match.group(1)
1112 if inst and isidentifier(inst) and inst not in SINGLETONS:
1113 return # Allow comparison for types which are not obvious
1114 yield match.start(), "E721"
784 1115
785 1116
786 def python_3000_has_key(logical_line): 1117 def python_3000_has_key(logical_line):
787 """ 1118 r"""
788 The {}.has_key() method will be removed in the future version of 1119 The {}.has_key() method is removed in the Python 3.
789 Python. Use the 'in' operation instead, like: 1120 Use the 'in' operation instead.
790 d = {"a": 1, "b": 2} 1121
791 if "b" in d: 1122 Okay: if "alph" in d:\n print d["alph"]
792 print d["b"] 1123 W601: assert d.has_key('alph')
793 """ 1124 """
794 pos = logical_line.find('.has_key(') 1125 pos = logical_line.find('.has_key(')
795 if pos > -1: 1126 if pos > -1:
796 return pos, "W601" 1127 yield pos, "W601"
797 1128
798 1129
799 def python_3000_raise_comma(logical_line): 1130 def python_3000_raise_comma(logical_line):
800 """ 1131 """
801 When raising an exception, use "raise ValueError('message')" 1132 When raising an exception, use "raise ValueError('message')"
802 instead of the older form "raise ValueError, 'message'". 1133 instead of the older form "raise ValueError, 'message'".
803 1134
804 The paren-using form is preferred because when the exception arguments 1135 The paren-using form is preferred because when the exception arguments
805 are long or include string formatting, you don't need to use line 1136 are long or include string formatting, you don't need to use line
806 continuation characters thanks to the containing parentheses. The older 1137 continuation characters thanks to the containing parentheses. The older
807 form will be removed in Python 3000. 1138 form is removed in Python 3.
1139
1140 Okay: raise DummyError("Message")
1141 W602: raise DummyError, "Message"
808 """ 1142 """
809 match = RAISE_COMMA_REGEX.match(logical_line) 1143 match = RAISE_COMMA_REGEX.match(logical_line)
810 if match: 1144 if match and not RERAISE_COMMA_REGEX.match(logical_line):
811 return match.start(1), "W602" 1145 yield match.end() - 1, "W602"
812 1146
813 1147
814 def python_3000_not_equal(logical_line): 1148 def python_3000_not_equal(logical_line):
815 """ 1149 """
816 != can also be written <>, but this is an obsolete usage kept for 1150 != can also be written <>, but this is an obsolete usage kept for
817 backwards compatibility only. New code should always use !=. 1151 backwards compatibility only. New code should always use !=.
818 The older syntax is removed in Python 3000. 1152 The older syntax is removed in Python 3.
1153
1154 Okay: if a != 'no':
1155 W603: if a <> 'no':
819 """ 1156 """
820 pos = logical_line.find('<>') 1157 pos = logical_line.find('<>')
821 if pos > -1: 1158 if pos > -1:
822 return pos, "W603" 1159 yield pos, "W603"
823 1160
824 1161
825 def python_3000_backticks(logical_line): 1162 def python_3000_backticks(logical_line):
826 """ 1163 """
827 Backticks are removed in Python 3000. 1164 Backticks are removed in Python 3.
828 Use repr() instead. 1165 Use repr() instead.
1166
1167 Okay: val = repr(1 + 2)
1168 W604: val = `1 + 2`
829 """ 1169 """
830 pos = logical_line.find('`') 1170 pos = logical_line.find('`')
831 if pos > -1: 1171 if pos > -1:
832 return pos, "W604" 1172 yield pos, "W604"
833 1173
834 1174
835 ############################################################################## 1175 ##############################################################################
836 # Helper functions 1176 # Helper functions
837 ############################################################################## 1177 ##############################################################################
838 1178
839 1179
840 if '' == ''.encode(): 1180 if '' == ''.encode():
841 # Python 2: implicit encoding. 1181 # Python 2: implicit encoding.
842 def readlines(filename): 1182 def readlines(filename):
843 return open(filename).readlines() 1183 f = open(filename)
1184 try:
1185 return f.readlines()
1186 finally:
1187 f.close()
1188 isidentifier = re.compile(r'[a-zA-Z_]\w*').match
1189 stdin_get_value = sys.stdin.read
844 else: 1190 else:
845 # Python 3: decode to latin-1. 1191 # Python 3
846 # This function is lazy, it does not read the encoding declaration. 1192 def readlines(filename): # __IGNORE_WARNING__
847 # XXX: use tokenize.detect_encoding() 1193 f = open(filename, 'rb')
848 def readlines(filename): # __IGNORE_WARNING__ 1194 try:
849 return open(filename, encoding='latin-1').readlines() 1195 coding, lines = tokenize.detect_encoding(f.readline)
1196 f = TextIOWrapper(f, coding, line_buffering=True)
1197 return [l.decode(coding) for l in lines] + f.readlines()
1198 except (LookupError, SyntaxError, UnicodeError):
1199 f.close()
1200 # Fall back if files are improperly declared
1201 f = open(filename, encoding='latin-1')
1202 return f.readlines()
1203 finally:
1204 f.close()
1205 isidentifier = str.isidentifier
1206
1207 def stdin_get_value():
1208 return TextIOWrapper(sys.stdin.buffer, errors='ignore').read()
1209 readlines.__doc__ = " Read the source code."
1210 noqa = re.compile(r'# no(?:qa|pep8)\b', re.I).search
850 1211
851 1212
852 def expand_indent(line): 1213 def expand_indent(line):
853 """ 1214 r"""
854 Return the amount of indentation. 1215 Return the amount of indentation.
855 Tabs are expanded to the next multiple of 8. 1216 Tabs are expanded to the next multiple of 8.
856 1217
857 >>> expand_indent(' ') 1218 >>> expand_indent(' ')
858 4 1219 4
859 >>> expand_indent('\\t') 1220 >>> expand_indent('\t')
860 8 1221 8
861 >>> expand_indent(' \\t') 1222 >>> expand_indent(' \t')
862 8 1223 8
863 >>> expand_indent(' \\t') 1224 >>> expand_indent(' \t')
864 8 1225 8
865 >>> expand_indent(' \\t') 1226 >>> expand_indent(' \t')
866 16 1227 16
867 """ 1228 """
1229 if '\t' not in line:
1230 return len(line) - len(line.lstrip())
868 result = 0 1231 result = 0
869 for char in line: 1232 for char in line:
870 if char == '\t': 1233 if char == '\t':
871 result = result // 8 * 8 + 8 1234 result = result // 8 * 8 + 8
872 elif char == ' ': 1235 elif char == ' ':
885 >>> mute_string("'''abc'''") 1248 >>> mute_string("'''abc'''")
886 "'''xxx'''" 1249 "'''xxx'''"
887 >>> mute_string("r'abc'") 1250 >>> mute_string("r'abc'")
888 "r'xxx'" 1251 "r'xxx'"
889 """ 1252 """
890 start = 1 1253 # String modifiers (e.g. u or r)
1254 start = text.index(text[-1]) + 1
891 end = len(text) - 1 1255 end = len(text) - 1
892 # String modifiers (e.g. u or r)
893 if text.endswith('"'):
894 start += text.index('"')
895 elif text.endswith("'"):
896 start += text.index("'")
897 # Triple quotes 1256 # Triple quotes
898 if text.endswith('"""') or text.endswith("'''"): 1257 if text[-3:] in ('"""', "'''"):
899 start += 2 1258 start += 2
900 end -= 2 1259 end -= 2
901 return text[:start] + 'x' * (end - start) + text[end:] 1260 return text[:start] + 'x' * (end - start) + text[end:]
902 1261
903 1262
904 def message(text): 1263 def parse_udiff(diff, patterns=None, parent='.'):
905 """Print a message.""" 1264 """Return a dictionary of matching lines."""
906 # print >> sys.stderr, options.prog + ': ' + text 1265 # For each file of the diff, the entry key is the filename,
907 # print >> sys.stderr, text 1266 # and the value is a set of row numbers to consider.
908 print(text) 1267 rv = {}
1268 path = nrows = None
1269 for line in diff.splitlines():
1270 if nrows:
1271 if line[:1] != '-':
1272 nrows -= 1
1273 continue
1274 if line[:3] == '@@ ':
1275 hunk_match = HUNK_REGEX.match(line)
1276 row, nrows = [int(g or '1') for g in hunk_match.groups()]
1277 rv[path].update(range(row, row + nrows))
1278 elif line[:3] == '+++':
1279 path = line[4:].split('\t', 1)[0]
1280 if path[:2] == 'b/':
1281 path = path[2:]
1282 rv[path] = set()
1283 return dict([(os.path.join(parent, path), rows)
1284 for (path, rows) in rv.items()
1285 if rows and filename_match(path, patterns)])
1286
1287
1288 def filename_match(filename, patterns, default=True):
1289 """
1290 Check if patterns contains a pattern that matches filename.
1291 If patterns is unspecified, this always returns True.
1292 """
1293 if not patterns:
1294 return default
1295 return any(fnmatch(filename, pattern) for pattern in patterns)
909 1296
910 1297
911 ############################################################################## 1298 ##############################################################################
912 # Framework to run all checks 1299 # Framework to run all checks
913 ############################################################################## 1300 ##############################################################################
914 1301
915 1302
916 def find_checks(argument_name): 1303 _checks = {'physical_line': {}, 'logical_line': {}, 'tree': {}}
917 """ 1304
918 Find all globally visible functions where the first argument name 1305
919 starts with argument_name. 1306 def register_check(check, codes=None):
920 """ 1307 """
921 checks = [] 1308 Register a new check object.
922 for name, function in globals().items(): 1309 """
923 if not inspect.isfunction(function): 1310 def _add_check(check, kind, codes, args):
924 continue 1311 if check in _checks[kind]:
925 args = inspect.getargspec(function)[0] 1312 _checks[kind][check][0].extend(codes or [])
926 if args and args[0].startswith(argument_name): 1313 else:
927 codes = ERRORCODE_REGEX.findall(inspect.getdoc(function) or '') 1314 _checks[kind][check] = (codes or [''], args)
928 for code in codes or ['']: 1315 if inspect.isfunction(check):
929 if not code or not ignore_code(code): 1316 args = inspect.getargspec(check)[0]
930 checks.append((name, function, args)) 1317 if args and args[0] in ('physical_line', 'logical_line'):
931 break 1318 if codes is None:
932 checks.sort() 1319 codes = ERRORCODE_REGEX.findall(check.__doc__ or '')
933 return checks 1320 _add_check(check, args[0], codes, args)
1321 elif inspect.isclass(check):
1322 if inspect.getargspec(check.__init__)[0][:2] == ['self', 'tree']:
1323 _add_check(check, 'tree', codes, None)
1324
1325
1326 def init_checks_registry():
1327 """
1328 Register all globally visible functions where the first argument name
1329 is 'physical_line' or 'logical_line'.
1330 """
1331 mod = inspect.getmodule(register_check)
1332 for (name, function) in inspect.getmembers(mod, inspect.isfunction):
1333 register_check(function)
1334 init_checks_registry()
934 1335
935 1336
936 class Checker(object): 1337 class Checker(object):
937 """ 1338 """
938 Load a Python source file, tokenize it, check coding style. 1339 Load a Python source file, tokenize it, check coding style.
939 """ 1340 """
940 1341
941 def __init__(self, filename, lines=None): 1342 def __init__(self, filename=None, lines=None,
1343 options=None, report=None, **kwargs):
1344 if options is None:
1345 options = StyleGuide(kwargs).options
1346 else:
1347 assert not kwargs
1348 self._io_error = None
1349 self._physical_checks = options.physical_checks
1350 self._logical_checks = options.logical_checks
1351 self._ast_checks = options.ast_checks
1352 self.max_line_length = options.max_line_length
1353 self.hang_closing = options.hang_closing
1354 self.verbose = options.verbose
942 self.filename = filename 1355 self.filename = filename
943 if filename is None: 1356 if filename is None:
944 self.filename = 'stdin' 1357 self.filename = 'stdin'
945 self.lines = lines or [] 1358 self.lines = lines or []
1359 elif filename == '-':
1360 self.filename = 'stdin'
1361 self.lines = stdin_get_value().splitlines(True)
946 elif lines is None: 1362 elif lines is None:
947 self.lines = readlines(filename) 1363 try:
1364 self.lines = readlines(filename)
1365 except IOError:
1366 exc_type, exc = sys.exc_info()[:2]
1367 self._io_error = '%s: %s' % (exc_type.__name__, exc)
1368 self.lines = []
948 else: 1369 else:
949 self.lines = lines 1370 self.lines = lines
950 options.counters['physical lines'] += len(self.lines) 1371 if self.lines:
1372 ord0 = ord(self.lines[0][0])
1373 if ord0 in (0xef, 0xfeff): # Strip the UTF-8 BOM
1374 if ord0 == 0xfeff:
1375 self.lines[0] = self.lines[0][1:]
1376 elif self.lines[0][:3] == '\xef\xbb\xbf':
1377 self.lines[0] = self.lines[0][3:]
1378 self.report = report or options.report
1379 self.report_error = self.report.error
1380 self.report_error_args = self.report.error_args
1381
1382 def report_invalid_syntax(self):
1383 exc_type, exc = sys.exc_info()[:2]
1384 if len(exc.args) > 1:
1385 offset = exc.args[1]
1386 if len(offset) > 2:
1387 offset = offset[1:3]
1388 else:
1389 offset = (1, 0)
1390 self.report_error_args(offset[0], offset[1] or 0,
1391 'E901', exc_type.__name__, exc.args[0],
1392 self.report_invalid_syntax)
1393 report_invalid_syntax.__doc__ = " Check if the syntax is valid."
951 1394
952 def readline(self): 1395 def readline(self):
953 """ 1396 """
954 Get the next line from the input buffer. 1397 Get the next line from the input buffer.
955 """ 1398 """
980 def check_physical(self, line): 1423 def check_physical(self, line):
981 """ 1424 """
982 Run all physical checks on a raw input line. 1425 Run all physical checks on a raw input line.
983 """ 1426 """
984 self.physical_line = line 1427 self.physical_line = line
985 if self.indent_char is None and len(line) and line[0] in ' \t': 1428 if self.indent_char is None and line[:1] in WHITESPACE:
986 self.indent_char = line[0] 1429 self.indent_char = line[0]
987 for name, check, argument_names in options.physical_checks: 1430 for name, check, argument_names in self._physical_checks:
988 result = self.run_check(check, argument_names) 1431 result = self.run_check(check, argument_names)
989 if result is not None: 1432 if result is not None:
990 offset, code = result[:2] 1433 offset, code = result[:2]
991 args = result[2:] 1434 args = result[2:]
992 self.report_error_args(self.line_number, offset, code, check, 1435 self.report_error_args(self.line_number, offset, code, check,
996 """ 1439 """
997 Build a logical line from tokens. 1440 Build a logical line from tokens.
998 """ 1441 """
999 self.mapping = [] 1442 self.mapping = []
1000 logical = [] 1443 logical = []
1444 comments = []
1001 length = 0 1445 length = 0
1002 previous = None 1446 previous = None
1003 for token in self.tokens: 1447 for token in self.tokens:
1004 token_type, text = token[0:2] 1448 token_type, text = token[0:2]
1449 if token_type == tokenize.COMMENT:
1450 comments.append(text)
1451 continue
1005 if token_type in SKIP_TOKENS: 1452 if token_type in SKIP_TOKENS:
1006 continue 1453 continue
1007 if token_type == tokenize.STRING: 1454 if token_type == tokenize.STRING:
1008 text = mute_string(text) 1455 text = mute_string(text)
1009 if previous: 1456 if previous:
1010 end_line, end = previous[3] 1457 end_row, end = previous[3]
1011 start_line, start = token[2] 1458 start_row, start = token[2]
1012 if end_line != start_line: # different row 1459 if end_row != start_row: # different row
1013 prev_text = self.lines[end_line - 1][end - 1] 1460 prev_text = self.lines[end_row - 1][end - 1]
1014 if prev_text == ',' or (prev_text not in '{[(' 1461 if prev_text == ',' or (prev_text not in '{[('
1015 and text not in '}])'): 1462 and text not in '}])'):
1016 logical.append(' ') 1463 logical.append(' ')
1017 length += 1 1464 length += 1
1018 elif end != start: # different column 1465 elif end != start: # different column
1019 fill = self.lines[end_line - 1][end:start] 1466 fill = self.lines[end_row - 1][end:start]
1020 logical.append(fill) 1467 logical.append(fill)
1021 length += len(fill) 1468 length += len(fill)
1022 self.mapping.append((length, token)) 1469 self.mapping.append((length, token))
1023 logical.append(text) 1470 logical.append(text)
1024 length += len(text) 1471 length += len(text)
1025 previous = token 1472 previous = token
1026 self.logical_line = ''.join(logical) 1473 self.logical_line = ''.join(logical)
1027 assert self.logical_line.lstrip() == self.logical_line 1474 self.noqa = comments and noqa(''.join(comments))
1028 assert self.logical_line.rstrip() == self.logical_line 1475 # With Python 2, if the line ends with '\r\r\n' the assertion fails
1476 # assert self.logical_line.strip() == self.logical_line
1029 1477
1030 def check_logical(self): 1478 def check_logical(self):
1031 """ 1479 """
1032 Build a line from tokens and run all logical checks on it. 1480 Build a line from tokens and run all logical checks on it.
1033 """ 1481 """
1034 options.counters['logical lines'] += 1
1035 self.build_tokens_line() 1482 self.build_tokens_line()
1483 self.report.increment_logical_line()
1036 first_line = self.lines[self.mapping[0][1][2][0] - 1] 1484 first_line = self.lines[self.mapping[0][1][2][0] - 1]
1037 indent = first_line[:self.mapping[0][1][2][1]] 1485 indent = first_line[:self.mapping[0][1][2][1]]
1038 self.previous_indent_level = self.indent_level 1486 self.previous_indent_level = self.indent_level
1039 self.indent_level = expand_indent(indent) 1487 self.indent_level = expand_indent(indent)
1040 if options.verbose >= 2: 1488 if self.verbose >= 2:
1041 print(self.logical_line[:80].rstrip()) 1489 print(self.logical_line[:80].rstrip())
1042 for name, check, argument_names in options.logical_checks: 1490 for name, check, argument_names in self._logical_checks:
1043 if options.verbose >= 4: 1491 if self.verbose >= 4:
1044 print(' ' + name) 1492 print(' ' + name)
1045 result = self.run_check(check, argument_names) 1493 for result in self.run_check(check, argument_names):
1046 if result is not None:
1047 offset, code = result[:2] 1494 offset, code = result[:2]
1048 args = result[2:] 1495 args = result[2:]
1049 if isinstance(offset, tuple): 1496 if isinstance(offset, tuple):
1050 original_number, original_offset = offset 1497 orig_number, orig_offset = offset
1051 else: 1498 else:
1052 for token_offset, token in self.mapping: 1499 for token_offset, token in self.mapping:
1053 if offset >= token_offset: 1500 if offset >= token_offset:
1054 original_number = token[2][0] 1501 orig_number = token[2][0]
1055 original_offset = (token[2][1] 1502 orig_offset = (token[2][1] + offset - token_offset)
1056 + offset - token_offset) 1503 self.report_error_args(orig_number, orig_offset, code, check,
1057 self.report_error_args(original_number, original_offset, 1504 *args)
1058 code, check, *args)
1059 self.previous_logical = self.logical_line 1505 self.previous_logical = self.logical_line
1060 1506
1507 def check_ast(self):
1508 try:
1509 tree = compile(''.join(self.lines), '', 'exec', PyCF_ONLY_AST)
1510 except (SyntaxError, TypeError):
1511 return self.report_invalid_syntax()
1512 for name, cls, _ in self._ast_checks:
1513 checker = cls(tree, self.filename)
1514 for args in checker.run():
1515 lineno = args.pop(0)
1516 if not noqa(self.lines[lineno - 1]):
1517 self.report_error_args(lineno, *args)
1518
1519 def generate_tokens(self):
1520 if self._io_error:
1521 self.report_error(1, 0, 'E902 %s' % self._io_error, readlines)
1522 tokengen = tokenize.generate_tokens(self.readline_check_physical)
1523 try:
1524 for token in tokengen:
1525 yield token
1526 except (SyntaxError, tokenize.TokenError):
1527 self.report_invalid_syntax()
1528
1061 def check_all(self, expected=None, line_offset=0): 1529 def check_all(self, expected=None, line_offset=0):
1062 """ 1530 """
1063 Run all checks on the input file. 1531 Run all checks on the input file.
1064 """ 1532 """
1065 self.expected = expected or () 1533 self.report.init_file(self.filename, self.lines, expected, line_offset)
1066 self.line_offset = line_offset 1534 if self._ast_checks:
1535 self.check_ast()
1067 self.line_number = 0 1536 self.line_number = 0
1068 self.file_errors = 0
1069 self.indent_char = None 1537 self.indent_char = None
1070 self.indent_level = 0 1538 self.indent_level = 0
1071 self.previous_logical = '' 1539 self.previous_logical = ''
1072 self.blank_lines = 0
1073 self.blank_lines_before_comment = 0
1074 self.tokens = [] 1540 self.tokens = []
1541 self.blank_lines = blank_lines_before_comment = 0
1075 parens = 0 1542 parens = 0
1076 try: 1543 for token in self.generate_tokens():
1077 for token in tokenize.generate_tokens(self.readline_check_physical): 1544 self.tokens.append(token)
1078 if options.verbose >= 3: 1545 token_type, text = token[0:2]
1079 if token[2][0] == token[3][0]: 1546 if self.verbose >= 3:
1080 pos = '[%s:%s]' % (token[2][1] or '', token[3][1]) 1547 if token[2][0] == token[3][0]:
1081 else: 1548 pos = '[%s:%s]' % (token[2][1] or '', token[3][1])
1082 pos = 'l.%s' % token[3][0] 1549 else:
1083 print('l.%s\t%s\t%s\t%r' % 1550 pos = 'l.%s' % token[3][0]
1084 (token[2][0], pos, tokenize.tok_name[token[0]], token[1])) 1551 print('l.%s\t%s\t%s\t%r' %
1085 self.tokens.append(token) 1552 (token[2][0], pos, tokenize.tok_name[token[0]], text))
1086 token_type, text = token[0:2] 1553 if token_type == tokenize.OP:
1087 if token_type == tokenize.OP and text in '([{': 1554 if text in '([{':
1088 parens += 1 1555 parens += 1
1089 if token_type == tokenize.OP and text in '}])': 1556 elif text in '}])':
1090 parens -= 1 1557 parens -= 1
1091 if token_type == tokenize.NEWLINE and not parens: 1558 elif not parens:
1559 if token_type == tokenize.NEWLINE:
1560 if self.blank_lines < blank_lines_before_comment:
1561 self.blank_lines = blank_lines_before_comment
1092 self.check_logical() 1562 self.check_logical()
1093 self.blank_lines = 0
1094 self.blank_lines_before_comment = 0
1095 self.tokens = [] 1563 self.tokens = []
1096 if token_type == tokenize.NL and not parens: 1564 self.blank_lines = blank_lines_before_comment = 0
1097 if len(self.tokens) <= 1: 1565 elif token_type == tokenize.NL:
1566 if len(self.tokens) == 1:
1098 # The physical line contains only this token. 1567 # The physical line contains only this token.
1099 self.blank_lines += 1 1568 self.blank_lines += 1
1100 self.tokens = [] 1569 self.tokens = []
1101 if token_type == tokenize.COMMENT: 1570 elif token_type == tokenize.COMMENT and len(self.tokens) == 1:
1102 source_line = token[4] 1571 if blank_lines_before_comment < self.blank_lines:
1103 token_start = token[2][1] 1572 blank_lines_before_comment = self.blank_lines
1104 if source_line[:token_start].strip() == '': 1573 self.blank_lines = 0
1105 self.blank_lines_before_comment = max(self.blank_lines, 1574 if COMMENT_WITH_NL:
1106 self.blank_lines_before_comment) 1575 # The comment also ends a physical line
1107 self.blank_lines = 0
1108 if text.endswith('\n') and not parens:
1109 # The comment also ends a physical line. This works around
1110 # Python < 2.6 behaviour, which does not generate NL after
1111 # a comment which is on a line by itself.
1112 self.tokens = [] 1576 self.tokens = []
1113 except tokenize.TokenError as err: 1577 return self.report.get_file_results()
1114 msg, (lnum, pos) = err.args 1578
1115 self.report_error_args(lnum, pos, "E901", "TokenError", msg) 1579
1580 class BaseReport(object):
1581 """Collect the results of the checks."""
1582 print_filename = False
1583
1584 def __init__(self, options):
1585 self._benchmark_keys = options.benchmark_keys
1586 self._ignore_code = options.ignore_code
1587 # Results
1588 self.elapsed = 0
1589 self.total_errors = 0
1590 self.counters = dict.fromkeys(self._benchmark_keys, 0)
1591 self.messages = {}
1592
1593 def start(self):
1594 """Start the timer."""
1595 self._start_time = time.time()
1596
1597 def stop(self):
1598 """Stop the timer."""
1599 self.elapsed = time.time() - self._start_time
1600
1601 def init_file(self, filename, lines, expected, line_offset):
1602 """Signal a new file."""
1603 self.filename = filename
1604 self.lines = lines
1605 self.expected = expected or ()
1606 self.line_offset = line_offset
1607 self.file_errors = 0
1608 self.counters['files'] += 1
1609 self.counters['physical lines'] += len(lines)
1610
1611 def increment_logical_line(self):
1612 """Signal a new logical line."""
1613 self.counters['logical lines'] += 1
1614
1615 def error(self, line_number, offset, text, check):
1616 """Report an error, according to options."""
1617 code = text[:4]
1618 if self._ignore_code(code):
1619 return
1620 if code in self.counters:
1621 self.counters[code] += 1
1622 else:
1623 self.counters[code] = 1
1624 self.messages[code] = text[5:]
1625 # Don't care about expected errors or warnings
1626 if code in self.expected:
1627 return
1628 if self.print_filename and not self.file_errors:
1629 print(self.filename)
1630 self.file_errors += 1
1631 self.total_errors += 1
1632 return code
1633
1634 def error_args(self, line_number, offset, code, check, *args):
1635 """Report an error, according to options."""
1636 if self._ignore_code(code):
1637 return
1638 text = getMessage(code, *args)
1639 if code in self.counters:
1640 self.counters[code] += 1
1641 else:
1642 self.counters[code] = 1
1643 self.messages[code] = text[5:]
1644 # Don't care about expected errors or warnings
1645 if code in self.expected:
1646 return
1647 if self.print_filename and not self.file_errors:
1648 print(self.filename)
1649 self.file_errors += 1
1650 self.total_errors += 1
1651 return code
1652
1653 def get_file_results(self):
1654 """Return the count of errors and warnings for this file."""
1116 return self.file_errors 1655 return self.file_errors
1117 1656
1118 def report_error(self, line_number, offset, text, check): 1657 def get_count(self, prefix=''):
1119 """ 1658 """Return the total count of errors and warnings."""
1120 Report an error, according to options. 1659 return sum([self.counters[key]
1121 """ 1660 for key in self.messages if key.startswith(prefix)])
1122 code = text[:4] 1661
1123 if ignore_code(code): 1662 def get_statistics(self, prefix=''):
1663 """
1664 Get statistics for message codes that start with the prefix.
1665
1666 prefix='' matches all errors and warnings
1667 prefix='E' matches all errors
1668 prefix='W' matches all warnings
1669 prefix='E4' matches all errors that have to do with imports
1670 """
1671 return ['%-7s %s %s' % (self.counters[key], key, self.messages[key])
1672 for key in sorted(self.messages) if key.startswith(prefix)]
1673
1674 def print_statistics(self, prefix=''):
1675 """Print overall statistics (number of errors and warnings)."""
1676 for line in self.get_statistics(prefix):
1677 print(line)
1678
1679 def print_benchmark(self):
1680 """Print benchmark numbers."""
1681 print('%-7.2f %s' % (self.elapsed, 'seconds elapsed'))
1682 if self.elapsed:
1683 for key in self._benchmark_keys:
1684 print('%-7d %s per second (%d total)' %
1685 (self.counters[key] / self.elapsed, key,
1686 self.counters[key]))
1687
1688
1689 class FileReport(BaseReport):
1690 """Collect the results of the checks and print only the filenames."""
1691 print_filename = True
1692
1693
1694 class StandardReport(BaseReport):
1695 """Collect and print the results of the checks."""
1696
1697 def __init__(self, options):
1698 super(StandardReport, self).__init__(options)
1699 self._fmt = REPORT_FORMAT.get(options.format.lower(),
1700 options.format)
1701 self._repeat = options.repeat
1702 self._show_source = options.show_source
1703 self._show_pep8 = options.show_pep8
1704
1705 def init_file(self, filename, lines, expected, line_offset):
1706 """Signal a new file."""
1707 self._deferred_print = []
1708 return super(StandardReport, self).init_file(
1709 filename, lines, expected, line_offset)
1710
1711 def error(self, line_number, offset, text, check):
1712 """Report an error, according to options."""
1713 code = super(StandardReport, self).error(line_number, offset,
1714 text, check)
1715 if code and (self.counters[code] == 1 or self._repeat):
1716 self._deferred_print.append(
1717 (line_number, offset, code, text[5:], check.__doc__))
1718 return code
1719
1720 def error_args(self, line_number, offset, code, check, *args):
1721 """Report an error, according to options."""
1722 code = super(StandardReport, self).error_args(line_number, offset,
1723 code, check, *args)
1724 if code and (self.counters[code] == 1 or self._repeat):
1725 text = getMessage(code, *args)
1726 self._deferred_print.append(
1727 (line_number, offset, code, text[5:], check.__doc__))
1728 return code
1729
1730 def get_file_results(self):
1731 """Print the result and return the overall count for this file."""
1732 self._deferred_print.sort()
1733 for line_number, offset, code, text, doc in self._deferred_print:
1734 print(self._fmt % {
1735 'path': self.filename,
1736 'row': self.line_offset + line_number, 'col': offset + 1,
1737 'code': code, 'text': text,
1738 })
1739 if self._show_source:
1740 if line_number > len(self.lines):
1741 line = ''
1742 else:
1743 line = self.lines[line_number - 1]
1744 print(line.rstrip())
1745 print(' ' * offset + '^')
1746 if self._show_pep8 and doc:
1747 print(doc.lstrip('\n').rstrip())
1748 return self.file_errors
1749
1750
1751 class DiffReport(StandardReport):
1752 """Collect and print the results for the changed lines only."""
1753
1754 def __init__(self, options):
1755 super(DiffReport, self).__init__(options)
1756 self._selected = options.selected_lines
1757
1758 def error(self, line_number, offset, text, check):
1759 if line_number not in self._selected[self.filename]:
1124 return 1760 return
1125 if options.quiet == 1 and not self.file_errors: 1761 return super(DiffReport, self).error(line_number, offset, text, check)
1126 message(self.filename) 1762
1127 if code in options.counters: 1763
1128 options.counters[code] += 1 1764 class StyleGuide(object):
1765 """Initialize a PEP-8 instance with few options."""
1766
1767 def __init__(self, *args, **kwargs):
1768 # build options from the command line
1769 self.checker_class = kwargs.pop('checker_class', Checker)
1770 parse_argv = kwargs.pop('parse_argv', False)
1771 config_file = kwargs.pop('config_file', None)
1772 parser = kwargs.pop('parser', None)
1773 options, self.paths = process_options(
1774 parse_argv=parse_argv, config_file=config_file, parser=parser)
1775 if args or kwargs:
1776 # build options from dict
1777 options_dict = dict(*args, **kwargs)
1778 options.__dict__.update(options_dict)
1779 if 'paths' in options_dict:
1780 self.paths = options_dict['paths']
1781
1782 self.runner = self.input_file
1783 self.options = options
1784
1785 if not options.reporter:
1786 options.reporter = BaseReport if options.quiet else StandardReport
1787
1788 for index, value in enumerate(options.exclude):
1789 options.exclude[index] = value.rstrip('/')
1790 options.select = tuple(options.select or ())
1791 if not (options.select or options.ignore or
1792 options.testsuite or options.doctest) and DEFAULT_IGNORE:
1793 # The default choice: ignore controversial checks
1794 options.ignore = tuple(DEFAULT_IGNORE.split(','))
1129 else: 1795 else:
1130 options.counters[code] = 1 1796 # Ignore all checks which are not explicitly selected
1131 options.messages[code] = text[5:] 1797 options.ignore = ('',) if options.select else tuple(options.ignore)
1132 if options.quiet or code in self.expected: 1798 options.benchmark_keys = BENCHMARK_KEYS[:]
1133 # Don't care about expected errors or warnings 1799 options.ignore_code = self.ignore_code
1134 return 1800 options.physical_checks = self.get_checks('physical_line')
1135 self.file_errors += 1 1801 options.logical_checks = self.get_checks('logical_line')
1136 if options.counters[code] == 1 or options.repeat: 1802 options.ast_checks = self.get_checks('tree')
1137 message("%s:%s:%d: %s" % 1803 self.init_report()
1138 (self.filename, self.line_offset + line_number, 1804
1139 offset + 1, text)) 1805 def init_report(self, reporter=None):
1140 if options.show_source: 1806 """Initialize the report instance."""
1141 line = self.lines[line_number - 1] 1807 self.options.report = (reporter or self.options.reporter)(self.options)
1142 message(line.rstrip()) 1808 return self.options.report
1143 message(' ' * offset + '^') 1809
1144 if options.show_pep8: 1810 def check_files(self, paths=None):
1145 message(check.__doc__.lstrip('\n').rstrip()) 1811 """Run all checks on the paths."""
1146 1812 if paths is None:
1147 1813 paths = self.paths
1148 def input_file(filename): 1814 report = self.options.report
1149 """ 1815 runner = self.runner
1150 Run all checks on a Python source file. 1816 report.start()
1151 """ 1817 try:
1152 if options.verbose: 1818 for path in paths:
1153 message('checking ' + filename) 1819 if os.path.isdir(path):
1154 Checker(filename).check_all() 1820 self.input_dir(path)
1155 1821 elif not self.excluded(path):
1156 1822 runner(path)
1157 def input_dir(dirname, runner=None): 1823 except KeyboardInterrupt:
1158 """ 1824 print('... stopped')
1159 Check all Python source files in this directory and all subdirectories. 1825 report.stop()
1160 """ 1826 return report
1161 dirname = dirname.rstrip('/') 1827
1162 if excluded(dirname): 1828 def input_file(self, filename, lines=None, expected=None, line_offset=0):
1163 return 1829 """Run all checks on a Python source file."""
1164 if runner is None: 1830 if self.options.verbose:
1165 runner = input_file 1831 print('checking %s' % filename)
1166 for root, dirs, files in os.walk(dirname): 1832 fchecker = self.checker_class(
1167 if options.verbose: 1833 filename, lines=lines, options=self.options)
1168 message('directory ' + root) 1834 return fchecker.check_all(expected=expected, line_offset=line_offset)
1169 options.counters['directories'] += 1 1835
1170 dirs.sort() 1836 def input_dir(self, dirname):
1171 for subdir in dirs: 1837 """Check all files in this directory and all subdirectories."""
1172 if excluded(subdir): 1838 dirname = dirname.rstrip('/')
1173 dirs.remove(subdir) 1839 if self.excluded(dirname):
1174 files.sort() 1840 return 0
1175 for filename in files: 1841 counters = self.options.report.counters
1176 if filename_match(filename) and not excluded(filename): 1842 verbose = self.options.verbose
1177 options.counters['files'] += 1 1843 filepatterns = self.options.filename
1178 runner(os.path.join(root, filename)) 1844 runner = self.runner
1179 1845 for root, dirs, files in os.walk(dirname):
1180 1846 if verbose:
1181 def excluded(filename): 1847 print('directory ' + root)
1182 """ 1848 counters['directories'] += 1
1183 Check if options.exclude contains a pattern that matches filename. 1849 for subdir in sorted(dirs):
1184 """ 1850 if self.excluded(subdir, root):
1185 basename = os.path.basename(filename) 1851 dirs.remove(subdir)
1186 for pattern in options.exclude: 1852 for filename in sorted(files):
1187 if fnmatch(basename, pattern): 1853 # contain a pattern that matches?
1188 # print basename, 'excluded because it matches', pattern 1854 if ((filename_match(filename, filepatterns) and
1855 not self.excluded(filename, root))):
1856 runner(os.path.join(root, filename))
1857
1858 def excluded(self, filename, parent=None):
1859 """
1860 Check if options.exclude contains a pattern that matches filename.
1861 """
1862 if not self.options.exclude:
1863 return False
1864 basename = os.path.basename(filename)
1865 if filename_match(basename, self.options.exclude):
1189 return True 1866 return True
1190 1867 if parent:
1191 1868 filename = os.path.join(parent, filename)
1192 def filename_match(filename): 1869 return filename_match(filename, self.options.exclude)
1193 """ 1870
1194 Check if options.filename contains a pattern that matches filename. 1871 def ignore_code(self, code):
1195 If options.filename is unspecified, this always returns True. 1872 """
1196 """ 1873 Check if the error code should be ignored.
1197 if not options.filename: 1874
1198 return True 1875 If 'options.select' contains a prefix of the error code,
1199 for pattern in options.filename: 1876 return False. Else, if 'options.ignore' contains a prefix of
1200 if fnmatch(filename, pattern): 1877 the error code, return True.
1201 return True 1878 """
1202 1879 return (code.startswith(self.options.ignore) and
1203 1880 not code.startswith(self.options.select))
1204 def ignore_code(code): 1881
1205 """ 1882 def get_checks(self, argument_name):
1206 Check if options.ignore contains a prefix of the error code. 1883 """
1207 If options.select contains a prefix of the error code, do not ignore it. 1884 Find all globally visible functions where the first argument name
1208 """ 1885 starts with argument_name and which contain selected tests.
1209 for select in options.select: 1886 """
1210 if code.startswith(select): 1887 checks = []
1211 return False 1888 for check, attrs in _checks[argument_name].items():
1212 for ignore in options.ignore: 1889 (codes, args) = attrs
1213 if code.startswith(ignore): 1890 if any(not (code and self.ignore_code(code)) for code in codes):
1214 return True 1891 checks.append((check.__name__, check, args))
1215 1892 return sorted(checks)
1216 1893
1217 def reset_counters(): 1894
1218 for key in list(options.counters.keys()): 1895 def get_parser(prog='pep8', version=__version__):
1219 if key not in BENCHMARK_KEYS: 1896 parser = OptionParser(prog=prog, version=version,
1220 del options.counters[key]
1221 options.messages = {}
1222
1223
1224 def get_error_statistics():
1225 """Get error statistics."""
1226 return get_statistics("E")
1227
1228
1229 def get_warning_statistics():
1230 """Get warning statistics."""
1231 return get_statistics("W")
1232
1233
1234 def get_statistics(prefix=''):
1235 """
1236 Get statistics for message codes that start with the prefix.
1237
1238 prefix='' matches all errors and warnings
1239 prefix='E' matches all errors
1240 prefix='W' matches all warnings
1241 prefix='E4' matches all errors that have to do with imports
1242 """
1243 stats = []
1244 keys = list(options.messages.keys())
1245 keys.sort()
1246 for key in keys:
1247 if key.startswith(prefix):
1248 stats.append('%-7s %s %s' %
1249 (options.counters[key], key, options.messages[key]))
1250 return stats
1251
1252
1253 def get_count(prefix=''):
1254 """Return the total count of errors and warnings."""
1255 keys = list(options.messages.keys())
1256 count = 0
1257 for key in keys:
1258 if key.startswith(prefix):
1259 count += options.counters[key]
1260 return count
1261
1262
1263 def print_statistics(prefix=''):
1264 """Print overall statistics (number of errors and warnings)."""
1265 for line in get_statistics(prefix):
1266 print(line)
1267
1268
1269 def print_benchmark(elapsed):
1270 """
1271 Print benchmark numbers.
1272 """
1273 print('%-7.2f %s' % (elapsed, 'seconds elapsed'))
1274 for key in BENCHMARK_KEYS:
1275 print('%-7d %s per second (%d total)' % (
1276 options.counters[key] / elapsed, key,
1277 options.counters[key]))
1278
1279
1280 def run_tests(filename):
1281 """
1282 Run all the tests from a file.
1283
1284 A test file can provide many tests. Each test starts with a declaration.
1285 This declaration is a single line starting with '#:'.
1286 It declares codes of expected failures, separated by spaces or 'Okay'
1287 if no failure is expected.
1288 If the file does not contain such declaration, it should pass all tests.
1289 If the declaration is empty, following lines are not checked, until next
1290 declaration.
1291
1292 Examples:
1293
1294 * Only E224 and W701 are expected: #: E224 W701
1295 * Following example is conform: #: Okay
1296 * Don't check these lines: #:
1297 """
1298 lines = readlines(filename) + ['#:\n']
1299 line_offset = 0
1300 codes = ['Okay']
1301 testcase = []
1302 for index, line in enumerate(lines):
1303 if not line.startswith('#:'):
1304 if codes:
1305 # Collect the lines of the test case
1306 testcase.append(line)
1307 continue
1308 if codes and index > 0:
1309 label = '%s:%s:1' % (filename, line_offset + 1)
1310 codes = [c for c in codes if c != 'Okay']
1311 # Run the checker
1312 errors = Checker(filename, testcase).check_all(codes, line_offset)
1313 # Check if the expected errors were found
1314 for code in codes:
1315 if not options.counters.get(code):
1316 errors += 1
1317 message('%s: error %s not found' % (label, code))
1318 if options.verbose and not errors:
1319 message('%s: passed (%s)' % (label, ' '.join(codes)))
1320 # Keep showing errors for multiple tests
1321 reset_counters()
1322 # output the real line numbers
1323 line_offset = index
1324 # configure the expected errors
1325 codes = line.split()[1:]
1326 # empty the test case buffer
1327 del testcase[:]
1328
1329
1330 def selftest():
1331 """
1332 Test all check functions with test cases in docstrings.
1333 """
1334 count_passed = 0
1335 count_failed = 0
1336 checks = options.physical_checks + options.logical_checks
1337 for name, check, argument_names in checks:
1338 for line in check.__doc__.splitlines():
1339 line = line.lstrip()
1340 match = SELFTEST_REGEX.match(line)
1341 if match is None:
1342 continue
1343 code, source = match.groups()
1344 checker = Checker(None)
1345 for part in source.split(r'\n'):
1346 part = part.replace(r'\t', '\t')
1347 part = part.replace(r'\s', ' ')
1348 checker.lines.append(part + '\n')
1349 options.quiet = 2
1350 checker.check_all()
1351 error = None
1352 if code == 'Okay':
1353 if len(options.counters) > len(BENCHMARK_KEYS):
1354 codes = [key for key in options.counters.keys()
1355 if key not in BENCHMARK_KEYS]
1356 error = "incorrectly found %s" % ', '.join(codes)
1357 elif not options.counters.get(code):
1358 error = "failed to find %s" % code
1359 # Reset the counters
1360 reset_counters()
1361 if not error:
1362 count_passed += 1
1363 else:
1364 count_failed += 1
1365 if len(checker.lines) == 1:
1366 print("pep8.py: %s: %s" %
1367 (error, checker.lines[0].rstrip()))
1368 else:
1369 print("pep8.py: %s:" % error)
1370 for line in checker.lines:
1371 print(line.rstrip())
1372 if options.verbose:
1373 print("%d passed and %d failed." % (count_passed, count_failed))
1374 if count_failed:
1375 print("Test failed.")
1376 else:
1377 print("Test passed.")
1378
1379
1380 def process_options(arglist=None):
1381 """
1382 Process options passed either via arglist or via command line args.
1383 """
1384 global options, args
1385 parser = OptionParser(version=__version__,
1386 usage="%prog [options] input ...") 1897 usage="%prog [options] input ...")
1898 parser.config_options = [
1899 'exclude', 'filename', 'select', 'ignore', 'max-line-length',
1900 'hang-closing', 'count', 'format', 'quiet', 'show-pep8',
1901 'show-source', 'statistics', 'verbose']
1387 parser.add_option('-v', '--verbose', default=0, action='count', 1902 parser.add_option('-v', '--verbose', default=0, action='count',
1388 help="print status messages, or debug with -vv") 1903 help="print status messages, or debug with -vv")
1389 parser.add_option('-q', '--quiet', default=0, action='count', 1904 parser.add_option('-q', '--quiet', default=0, action='count',
1390 help="report only file names, or nothing with -qq") 1905 help="report only file names, or nothing with -qq")
1391 parser.add_option('-r', '--repeat', action='store_true', 1906 parser.add_option('-r', '--repeat', default=True, action='store_true',
1392 help="show all occurrences of the same error") 1907 help="(obsolete) show all occurrences of the same error")
1908 parser.add_option('--first', action='store_false', dest='repeat',
1909 help="show first occurrence of each error")
1393 parser.add_option('--exclude', metavar='patterns', default=DEFAULT_EXCLUDE, 1910 parser.add_option('--exclude', metavar='patterns', default=DEFAULT_EXCLUDE,
1394 help="exclude files or directories which match these " 1911 help="exclude files or directories which match these "
1395 "comma separated patterns (default: %s)" % 1912 "comma separated patterns (default: %default)")
1396 DEFAULT_EXCLUDE)
1397 parser.add_option('--filename', metavar='patterns', default='*.py', 1913 parser.add_option('--filename', metavar='patterns', default='*.py',
1398 help="when parsing directories, only check filenames " 1914 help="when parsing directories, only check filenames "
1399 "matching these comma separated patterns (default: " 1915 "matching these comma separated patterns "
1400 "*.py)") 1916 "(default: %default)")
1401 parser.add_option('--select', metavar='errors', default='', 1917 parser.add_option('--select', metavar='errors', default='',
1402 help="select errors and warnings (e.g. E,W6)") 1918 help="select errors and warnings (e.g. E,W6)")
1403 parser.add_option('--ignore', metavar='errors', default='', 1919 parser.add_option('--ignore', metavar='errors', default='',
1404 help="skip errors and warnings (e.g. E4,W)") 1920 help="skip errors and warnings (e.g. E4,W)")
1405 parser.add_option('--show-source', action='store_true', 1921 parser.add_option('--show-source', action='store_true',
1406 help="show source code for each error") 1922 help="show source code for each error")
1407 parser.add_option('--show-pep8', action='store_true', 1923 parser.add_option('--show-pep8', action='store_true',
1408 help="show text of PEP 8 for each error") 1924 help="show text of PEP 8 for each error "
1925 "(implies --first)")
1409 parser.add_option('--statistics', action='store_true', 1926 parser.add_option('--statistics', action='store_true',
1410 help="count errors and warnings") 1927 help="count errors and warnings")
1411 parser.add_option('--count', action='store_true', 1928 parser.add_option('--count', action='store_true',
1412 help="print total number of errors and warnings " 1929 help="print total number of errors and warnings "
1413 "to standard error and set exit code to 1 if " 1930 "to standard error and set exit code to 1 if "
1414 "total is not null") 1931 "total is not null")
1415 parser.add_option('--benchmark', action='store_true', 1932 parser.add_option('--max-line-length', type='int', metavar='n',
1416 help="measure processing speed") 1933 default=MAX_LINE_LENGTH,
1417 parser.add_option('--testsuite', metavar='dir', 1934 help="set maximum allowed line length "
1418 help="run regression tests from dir") 1935 "(default: %default)")
1419 parser.add_option('--doctest', action='store_true', 1936 parser.add_option('--hang-closing', action='store_true',
1420 help="run doctest on myself") 1937 help="hang closing bracket instead of matching "
1938 "indentation of opening bracket's line")
1939 parser.add_option('--format', metavar='format', default='default',
1940 help="set the error format [default|pylint|<custom>]")
1941 parser.add_option('--diff', action='store_true',
1942 help="report only lines changed according to the "
1943 "unified diff received on STDIN")
1944 group = parser.add_option_group("Testing Options")
1945 if os.path.exists(TESTSUITE_PATH):
1946 group.add_option('--testsuite', metavar='dir',
1947 help="run regression tests from dir")
1948 group.add_option('--doctest', action='store_true',
1949 help="run doctest on myself")
1950 group.add_option('--benchmark', action='store_true',
1951 help="measure processing speed")
1952 return parser
1953
1954
1955 def read_config(options, args, arglist, parser):
1956 """Read both user configuration and local configuration."""
1957 config = RawConfigParser()
1958
1959 user_conf = options.config
1960 if user_conf and os.path.isfile(user_conf):
1961 if options.verbose:
1962 print('user configuration: %s' % user_conf)
1963 config.read(user_conf)
1964
1965 parent = tail = args and os.path.abspath(os.path.commonprefix(args))
1966 while tail:
1967 if config.read([os.path.join(parent, fn) for fn in PROJECT_CONFIG]):
1968 if options.verbose:
1969 print('local configuration: in %s' % parent)
1970 break
1971 parent, tail = os.path.split(parent)
1972
1973 pep8_section = parser.prog
1974 if config.has_section(pep8_section):
1975 option_list = dict([(o.dest, o.type or o.action)
1976 for o in parser.option_list])
1977
1978 # First, read the default values
1979 new_options, _ = parser.parse_args([])
1980
1981 # Second, parse the configuration
1982 for opt in config.options(pep8_section):
1983 if options.verbose > 1:
1984 print(" %s = %s" % (opt, config.get(pep8_section, opt)))
1985 if opt.replace('_', '-') not in parser.config_options:
1986 print("Unknown option: '%s'\n not in [%s]" %
1987 (opt, ' '.join(parser.config_options)))
1988 sys.exit(1)
1989 normalized_opt = opt.replace('-', '_')
1990 opt_type = option_list[normalized_opt]
1991 if opt_type in ('int', 'count'):
1992 value = config.getint(pep8_section, opt)
1993 elif opt_type == 'string':
1994 value = config.get(pep8_section, opt)
1995 else:
1996 assert opt_type in ('store_true', 'store_false')
1997 value = config.getboolean(pep8_section, opt)
1998 setattr(new_options, normalized_opt, value)
1999
2000 # Third, overwrite with the command-line options
2001 options, _ = parser.parse_args(arglist, values=new_options)
2002 options.doctest = options.testsuite = False
2003 return options
2004
2005
2006 def process_options(arglist=None, parse_argv=False, config_file=None,
2007 parser=None):
2008 """Process options passed either via arglist or via command line args."""
2009 if not arglist and not parse_argv:
2010 # Don't read the command line if the module is used as a library.
2011 arglist = []
2012 if not parser:
2013 parser = get_parser()
2014 if not parser.has_option('--config'):
2015 if config_file is True:
2016 config_file = DEFAULT_CONFIG
2017 group = parser.add_option_group("Configuration", description=(
2018 "The project options are read from the [%s] section of the "
2019 "tox.ini file or the setup.cfg file located in any parent folder "
2020 "of the path(s) being processed. Allowed options are: %s." %
2021 (parser.prog, ', '.join(parser.config_options))))
2022 group.add_option('--config', metavar='path', default=config_file,
2023 help="user config file location (default: %default)")
1421 options, args = parser.parse_args(arglist) 2024 options, args = parser.parse_args(arglist)
1422 if options.testsuite: 2025 options.reporter = None
2026
2027 if options.ensure_value('testsuite', False):
1423 args.append(options.testsuite) 2028 args.append(options.testsuite)
1424 if not args and not options.doctest: 2029 elif not options.ensure_value('doctest', False):
1425 parser.error('input not specified') 2030 if parse_argv and not args:
1426 options.prog = os.path.basename(sys.argv[0]) 2031 if options.diff or any(os.path.exists(name)
2032 for name in PROJECT_CONFIG):
2033 args = ['.']
2034 else:
2035 parser.error('input not specified')
2036 options = read_config(options, args, arglist, parser)
2037 options.reporter = parse_argv and options.quiet == 1 and FileReport
2038
2039 options.filename = options.filename and options.filename.split(',')
1427 options.exclude = options.exclude.split(',') 2040 options.exclude = options.exclude.split(',')
1428 for index in range(len(options.exclude)): 2041 options.select = options.select and options.select.split(',')
1429 options.exclude[index] = options.exclude[index].rstrip('/') 2042 options.ignore = options.ignore and options.ignore.split(',')
1430 if options.filename: 2043
1431 options.filename = options.filename.split(',') 2044 if options.diff:
1432 if options.select: 2045 options.reporter = DiffReport
1433 options.select = options.select.split(',') 2046 stdin = stdin_get_value()
2047 options.selected_lines = parse_udiff(stdin, options.filename, args[0])
2048 args = sorted(options.selected_lines)
2049
2050 return options, args
2051
2052
2053 def _main():
2054 """Parse options and run checks on Python source."""
2055 pep8style = StyleGuide(parse_argv=True, config_file=True)
2056 options = pep8style.options
2057 if options.doctest or options.testsuite:
2058 from testsuite.support import run_tests
2059 report = run_tests(pep8style)
1434 else: 2060 else:
1435 options.select = [] 2061 report = pep8style.check_files()
1436 if options.ignore:
1437 options.ignore = options.ignore.split(',')
1438 elif options.select:
1439 # Ignore all checks which are not explicitly selected
1440 options.ignore = ['']
1441 elif options.testsuite or options.doctest:
1442 # For doctest and testsuite, all checks are required
1443 options.ignore = []
1444 else:
1445 # The default choice: ignore controversial checks
1446 options.ignore = DEFAULT_IGNORE.split(',')
1447 options.physical_checks = find_checks('physical_line')
1448 options.logical_checks = find_checks('logical_line')
1449 options.counters = dict.fromkeys(BENCHMARK_KEYS, 0)
1450 options.messages = {}
1451 return options, args
1452
1453
1454 def _main():
1455 """
1456 Parse options and run checks on Python source.
1457 """
1458 options, args = process_options()
1459 if options.doctest:
1460 import doctest
1461 doctest.testmod(verbose=options.verbose)
1462 selftest()
1463 if options.testsuite:
1464 runner = run_tests
1465 else:
1466 runner = input_file
1467 start_time = time.time()
1468 for path in args:
1469 if os.path.isdir(path):
1470 input_dir(path, runner=runner)
1471 elif not excluded(path):
1472 options.counters['files'] += 1
1473 runner(path)
1474 elapsed = time.time() - start_time
1475 if options.statistics: 2062 if options.statistics:
1476 print_statistics() 2063 report.print_statistics()
1477 if options.benchmark: 2064 if options.benchmark:
1478 print_benchmark(elapsed) 2065 report.print_benchmark()
1479 count = get_count() 2066 if options.testsuite and not options.quiet:
1480 if count: 2067 report.print_results()
2068 if report.total_errors:
1481 if options.count: 2069 if options.count:
1482 sys.stderr.write(str(count) + '\n') 2070 sys.stderr.write(str(report.total_errors) + '\n')
1483 sys.exit(1) 2071 sys.exit(1)
1484
1485 2072
1486 if __name__ == '__main__': 2073 if __name__ == '__main__':
1487 _main() 2074 _main()

eric ide

mercurial