2 # pep8.py - Check Python source code formatting, according to PEP 8
3 # Copyright (C) 2006-2009 Johann C. Rocholl <johann@rocholl.net>
4 # Copyright (C) 2009-2014 Florent Xicluna <florent.xicluna@gmail.com>
6 # Permission is hereby granted, free of charge, to any person
7 # obtaining a copy of this software and associated documentation files
8 # (the "Software"), to deal in the Software without restriction,
9 # including without limitation the rights to use, copy, modify, merge,
10 # publish, distribute, sublicense, and/or sell copies of the Software,
11 # and to permit persons to whom the Software is furnished to do so,
12 # subject to the following conditions:
14 # The above copyright notice and this permission notice shall be
15 # included in all copies or substantial portions of the Software.
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 Check Python source code formatting, according to PEP 8.
29 For usage and a list of options, try this:
32 This program and its regression test suite live here:
33 http://github.com/jcrocholl/pep8
35 Groups of errors and warnings:
47 from __future__ import with_statement
49 __version__ = '1.6.0a0'
58 from optparse import OptionParser
59 from fnmatch import fnmatch
61 from configparser import RawConfigParser
62 from io import TextIOWrapper
64 from ConfigParser import RawConfigParser
66 DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__'
67 DEFAULT_IGNORE = 'E123,E226,E24,E704'
68 if sys.platform == 'win32':
69 DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8')
71 DEFAULT_CONFIG = os.path.join(os.getenv('XDG_CONFIG_HOME') or
72 os.path.expanduser('~/.config'), 'pep8')
73 PROJECT_CONFIG = ('setup.cfg', 'tox.ini', '.pep8')
74 TESTSUITE_PATH = os.path.join(os.path.dirname(__file__), 'testsuite')
77 'default': '%(path)s:%(row)d:%(col)d: %(code)s %(text)s',
78 'pylint': '%(path)s:%(row)d: [%(code)s] %(text)s',
82 SINGLETONS = frozenset(['False', 'None', 'True'])
83 KEYWORDS = frozenset(keyword.kwlist + ['print']) - SINGLETONS
84 UNARY_OPERATORS = frozenset(['>>', '**', '*', '+', '-'])
85 ARITHMETIC_OP = frozenset(['**', '*', '/', '//', '+', '-'])
86 WS_OPTIONAL_OPERATORS = ARITHMETIC_OP.union(['^', '&', '|', '<<', '>>', '%'])
87 WS_NEEDED_OPERATORS = frozenset([
88 '**=', '*=', '/=', '//=', '+=', '-=', '!=', '<>', '<', '>',
89 '%=', '^=', '&=', '|=', '==', '<=', '>=', '<<=', '>>=', '='])
90 WHITESPACE = frozenset(' \t')
91 NEWLINE = frozenset([tokenize.NL, tokenize.NEWLINE])
92 SKIP_TOKENS = NEWLINE.union([tokenize.INDENT, tokenize.DEDENT])
93 # ERRORTOKEN is triggered by backticks in Python 3
94 SKIP_COMMENTS = SKIP_TOKENS.union([tokenize.COMMENT, tokenize.ERRORTOKEN])
95 BENCHMARK_KEYS = ['directories', 'files', 'logical lines', 'physical lines']
97 INDENT_REGEX = re.compile(r'([ \t]*)')
98 RAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*,')
99 RERAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*,.*,\s*\w+\s*$')
100 ERRORCODE_REGEX = re.compile(r'\b[A-Z]\d{3}\b')
101 DOCSTRING_REGEX = re.compile(r'u?r?["\']')
102 EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[[({] | []}),;:]')
103 WHITESPACE_AFTER_COMMA_REGEX = re.compile(r'[,;:]\s*(?: |\t)')
104 COMPARE_SINGLETON_REGEX = re.compile(r'([=!]=)\s*(None|False|True)')
105 COMPARE_NEGATIVE_REGEX = re.compile(r'\b(not)\s+[^[({ ]+\s+(in|is)\s')
106 COMPARE_TYPE_REGEX = re.compile(r'(?:[=!]=|is(?:\s+not)?)\s*type(?:s.\w+Type'
107 r'|\s*\(\s*([^)]*[^ )])\s*\))')
108 KEYWORD_REGEX = re.compile(r'(\s*)\b(?:%s)\b(\s*)' % r'|'.join(KEYWORDS))
109 OPERATOR_REGEX = re.compile(r'(?:[^,\s])(\s*)(?:[-+*/|!<=>%&^]+)(\s*)')
110 LAMBDA_REGEX = re.compile(r'\blambda\b')
111 HUNK_REGEX = re.compile(r'^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@.*$')
113 # Work around Python < 2.6 behaviour, which does not generate NL after
114 # a comment which is on a line by itself.
115 COMMENT_WITH_NL = tokenize.generate_tokens(['#\n'].pop).send(None)[1] == '#\n'
118 ##############################################################################
119 # Plugins (check functions) for physical lines
120 ##############################################################################
123 def tabs_or_spaces(physical_line, indent_char):
124 r"""Never mix tabs and spaces.
126 The most popular way of indenting Python is with spaces only. The
127 second-most popular way is with tabs only. Code indented with a mixture
128 of tabs and spaces should be converted to using spaces exclusively. When
129 invoking the Python command line interpreter with the -t option, it issues
130 warnings about code that illegally mixes tabs and spaces. When using -tt
131 these warnings become errors. These options are highly recommended!
133 Okay: if a == 0:\n a = 1\n b = 1
134 E101: if a == 0:\n a = 1\n\tb = 1
136 indent = INDENT_REGEX.match(physical_line).group(1)
137 for offset, char in enumerate(indent):
138 if char != indent_char:
139 return offset, "E101 indentation contains mixed spaces and tabs"
142 def tabs_obsolete(physical_line):
143 r"""For new projects, spaces-only are strongly recommended over tabs.
145 Okay: if True:\n return
146 W191: if True:\n\treturn
148 indent = INDENT_REGEX.match(physical_line).group(1)
150 return indent.index('\t'), "W191 indentation contains tabs"
153 def trailing_whitespace(physical_line):
154 r"""Trailing whitespace is superfluous.
156 The warning returned varies on whether the line itself is blank, for easier
157 filtering for those who want to indent their blank lines.
161 W293: class Foo(object):\n \n bang = 12
163 physical_line = physical_line.rstrip('\n') # chr(10), newline
164 physical_line = physical_line.rstrip('\r') # chr(13), carriage return
165 physical_line = physical_line.rstrip('\x0c') # chr(12), form feed, ^L
166 stripped = physical_line.rstrip(' \t\v')
167 if physical_line != stripped:
169 return len(stripped), "W291 trailing whitespace"
171 return 0, "W293 blank line contains whitespace"
174 def trailing_blank_lines(physical_line, lines, line_number, total_lines):
175 r"""Trailing blank lines are superfluous.
180 However the last line should end with a new line (warning W292).
182 if line_number == total_lines:
183 stripped_last_line = physical_line.rstrip()
184 if not stripped_last_line:
185 return 0, "W391 blank line at end of file"
186 if stripped_last_line == physical_line:
187 return len(physical_line), "W292 no newline at end of file"
190 def maximum_line_length(physical_line, max_line_length, multiline):
191 r"""Limit all lines to a maximum of 79 characters.
193 There are still many devices around that are limited to 80 character
194 lines; plus, limiting windows to 80 characters makes it possible to have
195 several windows side-by-side. The default wrapping on such devices looks
196 ugly. Therefore, please limit all lines to a maximum of 79 characters.
197 For flowing long blocks of text (docstrings or comments), limiting the
198 length to 72 characters is recommended.
202 line = physical_line.rstrip()
204 if length > max_line_length and not noqa(line):
205 # Special case for long URLs in multi-line docstrings or comments,
206 # but still report the error when the 72 first chars are whitespaces.
207 chunks = line.split()
208 if ((len(chunks) == 1 and multiline) or
209 (len(chunks) == 2 and chunks[0] == '#')) and \
210 len(line) - len(chunks[-1]) < max_line_length - 7:
212 if hasattr(line, 'decode'): # Python 2
213 # The line could contain multi-byte characters
215 length = len(line.decode('utf-8'))
218 if length > max_line_length:
219 return (max_line_length, "E501 line too long "
220 "(%d > %d characters)" % (length, max_line_length))
223 ##############################################################################
224 # Plugins (check functions) for logical lines
225 ##############################################################################
228 def blank_lines(logical_line, blank_lines, indent_level, line_number,
229 blank_before, previous_logical, previous_indent_level):
230 r"""Separate top-level function and class definitions with two blank lines.
232 Method definitions inside a class are separated by a single blank line.
234 Extra blank lines may be used (sparingly) to separate groups of related
235 functions. Blank lines may be omitted between a bunch of related
236 one-liners (e.g. a set of dummy implementations).
238 Use blank lines in functions, sparingly, to indicate logical sections.
240 Okay: def a():\n pass\n\n\ndef b():\n pass
241 Okay: def a():\n pass\n\n\n# Foo\n# Bar\n\ndef b():\n pass
243 E301: class Foo:\n b = 0\n def bar():\n pass
244 E302: def a():\n pass\n\ndef b(n):\n pass
245 E303: def a():\n pass\n\n\n\ndef b(n):\n pass
246 E303: def a():\n\n\n\n pass
247 E304: @decorator\n\ndef a():\n pass
249 if line_number < 3 and not previous_logical:
250 return # Don't expect blank lines before the first line
251 if previous_logical.startswith('@'):
253 yield 0, "E304 blank lines found after function decorator"
254 elif blank_lines > 2 or (indent_level and blank_lines == 2):
255 yield 0, "E303 too many blank lines (%d)" % blank_lines
256 elif logical_line.startswith(('def ', 'class ', '@')):
258 if not (blank_before or previous_indent_level < indent_level or
259 DOCSTRING_REGEX.match(previous_logical)):
260 yield 0, "E301 expected 1 blank line, found 0"
261 elif blank_before != 2:
262 yield 0, "E302 expected 2 blank lines, found %d" % blank_before
265 def extraneous_whitespace(logical_line):
266 r"""Avoid extraneous whitespace.
268 Avoid extraneous whitespace in these situations:
269 - Immediately inside parentheses, brackets or braces.
270 - Immediately before a comma, semicolon, or colon.
272 Okay: spam(ham[1], {eggs: 2})
273 E201: spam( ham[1], {eggs: 2})
274 E201: spam(ham[ 1], {eggs: 2})
275 E201: spam(ham[1], { eggs: 2})
276 E202: spam(ham[1], {eggs: 2} )
277 E202: spam(ham[1 ], {eggs: 2})
278 E202: spam(ham[1], {eggs: 2 })
280 E203: if x == 4: print x, y; x, y = y , x
281 E203: if x == 4: print x, y ; x, y = y, x
282 E203: if x == 4 : print x, y; x, y = y, x
285 for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line):
288 found = match.start()
289 if text == char + ' ':
290 # assert char in '([{'
291 yield found + 1, "E201 whitespace after '%s'" % char
292 elif line[found - 1] != ',':
293 code = ('E202' if char in '}])' else 'E203') # if char in ',;:'
294 yield found, "%s whitespace before '%s'" % (code, char)
297 def whitespace_around_keywords(logical_line):
298 r"""Avoid extraneous whitespace around keywords.
303 E273: True and\tFalse
304 E274: True\tand False
306 for match in KEYWORD_REGEX.finditer(logical_line):
307 before, after = match.groups()
310 yield match.start(1), "E274 tab before keyword"
311 elif len(before) > 1:
312 yield match.start(1), "E272 multiple spaces before keyword"
315 yield match.start(2), "E273 tab after keyword"
317 yield match.start(2), "E271 multiple spaces after keyword"
320 def missing_whitespace(logical_line):
321 r"""Each comma, semicolon or colon should be followed by whitespace.
334 for index in range(len(line) - 1):
336 if char in ',;:' and line[index + 1] not in WHITESPACE:
337 before = line[:index]
338 if char == ':' and before.count('[') > before.count(']') and \
339 before.rfind('{') < before.rfind('['):
340 continue # Slice syntax, no space required
341 if char == ',' and line[index + 1] == ')':
342 continue # Allow tuple with only one element: (3,)
343 yield index, "E231 missing whitespace after '%s'" % char
346 def indentation(logical_line, previous_logical, indent_char,
347 indent_level, previous_indent_level):
348 r"""Use 4 spaces per indentation level.
350 For really old code that you don't want to mess up, you can continue to
354 Okay: if a == 0:\n a = 1
358 Okay: for item in items:\n pass
359 E112: for item in items:\npass
360 E115: for item in items:\n# Hi\n pass
364 E116: a = 1\n # b = 2
366 c = 0 if logical_line else 3
367 tmpl = "E11%d %s" if logical_line else "E11%d %s (comment)"
369 yield 0, tmpl % (1 + c, "indentation is not a multiple of four")
370 indent_expect = previous_logical.endswith(':')
371 if indent_expect and indent_level <= previous_indent_level:
372 yield 0, tmpl % (2 + c, "expected an indented block")
373 elif not indent_expect and indent_level > previous_indent_level:
374 yield 0, tmpl % (3 + c, "unexpected indentation")
377 def continued_indentation(logical_line, tokens, indent_level, hang_closing,
378 indent_char, noqa, verbose):
379 r"""Continuation lines indentation.
381 Continuation lines should align wrapped elements either vertically
382 using Python's implicit line joining inside parentheses, brackets
383 and braces, or using a hanging indent.
385 When using a hanging indent these considerations should be applied:
386 - there should be no arguments on the first line, and
387 - further indentation should be used to clearly distinguish itself as a
397 E124: a = (24,\n 42\n)
398 E125: if (\n b):\n pass
402 E129: if (a or\n b):\n pass
403 E131: a = (\n 42\n 24)
405 first_row = tokens[0][2][0]
406 nrows = 1 + tokens[-1][2][0] - first_row
407 if noqa or nrows == 1:
410 # indent_next tells us whether the next block is indented; assuming
411 # that it is indented by 4 spaces, then we should not allow 4-space
412 # indents on the final continuation line; in turn, some other
413 # indents are allowed to have an extra 4 spaces.
414 indent_next = logical_line.endswith(':')
417 valid_hangs = (4,) if indent_char != '\t' else (4, 8)
418 # remember how many brackets were opened on each line
420 # relative indents of physical lines
421 rel_indent = [0] * nrows
422 # for each depth, collect a list of opening rows
424 # for each depth, memorize the hanging indentation
428 last_indent = tokens[0][2]
430 # for each depth, memorize the visual indent column
431 indent = [last_indent[1]]
433 print(">>> " + tokens[0][4].rstrip())
435 for token_type, text, start, end, line in tokens:
437 newline = row < start[0] - first_row
439 row = start[0] - first_row
440 newline = not last_token_multiline and token_type not in NEWLINE
443 # this is the beginning of a continuation line.
446 print("... " + line.rstrip())
448 # record the initial indent.
449 rel_indent[row] = expand_indent(line) - indent_level
451 # identify closing bracket
452 close_bracket = (token_type == tokenize.OP and text in ']})')
454 # is the indent relative to an opening bracket line?
455 for open_row in reversed(open_rows[depth]):
456 hang = rel_indent[row] - rel_indent[open_row]
457 hanging_indent = hang in valid_hangs
461 hanging_indent = (hang == hangs[depth])
462 # is there any chance of visual indent?
463 visual_indent = (not close_bracket and hang > 0 and
464 indent_chances.get(start[1]))
466 if close_bracket and indent[depth]:
467 # closing bracket for visual indent
468 if start[1] != indent[depth]:
469 yield (start, "E124 closing bracket does not match "
470 "visual indentation")
471 elif close_bracket and not hang:
472 # closing bracket matches indentation of opening bracket's line
474 yield start, "E133 closing bracket is missing indentation"
475 elif indent[depth] and start[1] < indent[depth]:
476 if visual_indent is not True:
477 # visual indent is broken
478 yield (start, "E128 continuation line "
479 "under-indented for visual indent")
480 elif hanging_indent or (indent_next and rel_indent[row] == 8):
481 # hanging indent is verified
482 if close_bracket and not hang_closing:
483 yield (start, "E123 closing bracket does not match "
484 "indentation of opening bracket's line")
486 elif visual_indent is True:
487 # visual indent is verified
488 indent[depth] = start[1]
489 elif visual_indent in (text, str):
490 # ignore token lined up with matching one from a previous line
495 error = "E122", "missing indentation or outdented"
497 error = "E127", "over-indented for visual indent"
498 elif not close_bracket and hangs[depth]:
499 error = "E131", "unaligned for hanging indent"
503 error = "E126", "over-indented for hanging indent"
505 error = "E121", "under-indented for hanging indent"
506 yield start, "%s continuation line %s" % error
508 # look for visual indenting
509 if (parens[row] and token_type not in (tokenize.NL, tokenize.COMMENT)
510 and not indent[depth]):
511 indent[depth] = start[1]
512 indent_chances[start[1]] = True
514 print("bracket depth %s indent to %s" % (depth, start[1]))
515 # deal with implicit string concatenation
516 elif (token_type in (tokenize.STRING, tokenize.COMMENT) or
517 text in ('u', 'ur', 'b', 'br')):
518 indent_chances[start[1]] = str
519 # special case for the "if" statement because len("if (") == 4
520 elif not indent_chances and not row and not depth and text == 'if':
521 indent_chances[end[1] + 1] = True
522 elif text == ':' and line[end[1]:].isspace():
523 open_rows[depth].append(row)
525 # keep track of bracket depth
526 if token_type == tokenize.OP:
531 if len(open_rows) == depth:
533 open_rows[depth].append(row)
536 print("bracket depth %s seen, col %s, visual min = %s" %
537 (depth, start[1], indent[depth]))
538 elif text in ')]}' and depth > 0:
539 # parent indents should not be more than this one
540 prev_indent = indent.pop() or last_indent[1]
542 for d in range(depth):
543 if indent[d] > prev_indent:
545 for ind in list(indent_chances):
546 if ind >= prev_indent:
547 del indent_chances[ind]
548 del open_rows[depth + 1:]
551 indent_chances[indent[depth]] = True
552 for idx in range(row, -1, -1):
556 assert len(indent) == depth + 1
557 if start[1] not in indent_chances:
558 # allow to line up tokens
559 indent_chances[start[1]] = text
561 last_token_multiline = (start[0] != end[0])
562 if last_token_multiline:
563 rel_indent[end[0] - first_row] = rel_indent[row]
565 if indent_next and expand_indent(line) == indent_level + 4:
566 pos = (start[0], indent[0] + 4)
568 code = "E129 visually indented line"
570 code = "E125 continuation line"
571 yield pos, "%s with same indent as next logical line" % code
574 def whitespace_before_parameters(logical_line, tokens):
575 r"""Avoid extraneous whitespace.
577 Avoid extraneous whitespace in the following situations:
578 - before the open parenthesis that starts the argument list of a
580 - before the open parenthesis that starts an indexing or slicing.
585 Okay: dict['key'] = list[index]
586 E211: dict ['key'] = list[index]
587 E211: dict['key'] = list [index]
589 prev_type, prev_text, __, prev_end, __ = tokens[0]
590 for index in range(1, len(tokens)):
591 token_type, text, start, end, __ = tokens[index]
592 if (token_type == tokenize.OP and
594 start != prev_end and
595 (prev_type == tokenize.NAME or prev_text in '}])') and
596 # Syntax "class A (B):" is allowed, but avoid it
597 (index < 2 or tokens[index - 2][1] != 'class') and
598 # Allow "return (a.foo for a in range(5))"
599 not keyword.iskeyword(prev_text)):
600 yield prev_end, "E211 whitespace before '%s'" % text
601 prev_type = token_type
606 def whitespace_around_operator(logical_line):
607 r"""Avoid extraneous whitespace around an operator.
615 for match in OPERATOR_REGEX.finditer(logical_line):
616 before, after = match.groups()
619 yield match.start(1), "E223 tab before operator"
620 elif len(before) > 1:
621 yield match.start(1), "E221 multiple spaces before operator"
624 yield match.start(2), "E224 tab after operator"
626 yield match.start(2), "E222 multiple spaces after operator"
629 def missing_whitespace_around_operator(logical_line, tokens):
630 r"""Surround operators with a single space on either side.
632 - Always surround these binary operators with a single space on
633 either side: assignment (=), augmented assignment (+=, -= etc.),
634 comparisons (==, <, >, !=, <=, >=, in, not in, is, is not),
635 Booleans (and, or, not).
637 - If operators with different priorities are used, consider adding
638 whitespace around the operators with the lowest priorities.
643 Okay: hypot2 = x * x + y * y
644 Okay: c = (a + b) * (a - b)
645 Okay: foo(bar, key='word', *args, **kwargs)
652 E226: c = (a+b) * (a-b)
653 E226: hypot2 = x*x + y*y
655 E228: msg = fmt%(errno, errmsg)
659 prev_type = tokenize.OP
660 prev_text = prev_end = None
661 for token_type, text, start, end, line in tokens:
662 if token_type in SKIP_COMMENTS:
664 if text in ('(', 'lambda'):
669 if start != prev_end:
670 # Found a (probably) needed space
671 if need_space is not True and not need_space[1]:
672 yield (need_space[0],
673 "E225 missing whitespace around operator")
675 elif text == '>' and prev_text in ('<', '-'):
676 # Tolerate the "<>" operator, even if running Python 3
677 # Deal with Python 3's annotated return value "->"
680 if need_space is True or need_space[1]:
681 # A needed trailing space was not found
682 yield prev_end, "E225 missing whitespace around operator"
684 code, optype = 'E226', 'arithmetic'
686 code, optype = 'E228', 'modulo'
687 elif prev_text not in ARITHMETIC_OP:
688 code, optype = 'E227', 'bitwise or shift'
689 yield (need_space[0], "%s missing whitespace "
690 "around %s operator" % (code, optype))
692 elif token_type == tokenize.OP and prev_end is not None:
693 if text == '=' and parens:
694 # Allow keyword args or defaults: foo(bar=None).
696 elif text in WS_NEEDED_OPERATORS:
698 elif text in UNARY_OPERATORS:
699 # Check if the operator is being used as a binary operator
700 # Allow unary operators: -123, -x, +1.
701 # Allow argument unpacking: foo(*args, **kwargs).
702 if (prev_text in '}])' if prev_type == tokenize.OP
703 else prev_text not in KEYWORDS):
705 elif text in WS_OPTIONAL_OPERATORS:
708 if need_space is None:
709 # Surrounding space is optional, but ensure that
710 # trailing space matches opening space
711 need_space = (prev_end, start != prev_end)
712 elif need_space and start == prev_end:
713 # A needed opening space was not found
714 yield prev_end, "E225 missing whitespace around operator"
716 prev_type = token_type
721 def whitespace_around_comma(logical_line):
722 r"""Avoid extraneous whitespace after a comma or a colon.
724 Note: these checks are disabled by default
731 for m in WHITESPACE_AFTER_COMMA_REGEX.finditer(line):
732 found = m.start() + 1
733 if '\t' in m.group():
734 yield found, "E242 tab after '%s'" % m.group()[0]
736 yield found, "E241 multiple spaces after '%s'" % m.group()[0]
739 def whitespace_around_named_parameter_equals(logical_line, tokens):
740 r"""Don't use spaces around the '=' sign in function arguments.
742 Don't use spaces around the '=' sign when used to indicate a
743 keyword argument or a default parameter value.
745 Okay: def complex(real, imag=0.0):
746 Okay: return magic(r=real, i=imag)
747 Okay: boolean(a == b)
748 Okay: boolean(a != b)
749 Okay: boolean(a <= b)
750 Okay: boolean(a >= b)
752 E251: def complex(real, imag = 0.0):
753 E251: return magic(r = real, i = imag)
758 message = "E251 unexpected spaces around keyword / parameter equals"
759 for token_type, text, start, end, line in tokens:
760 if token_type == tokenize.NL:
764 if start != prev_end:
765 yield (prev_end, message)
766 elif token_type == tokenize.OP:
771 elif parens and text == '=':
773 if start != prev_end:
774 yield (prev_end, message)
778 def whitespace_before_comment(logical_line, tokens):
779 r"""Separate inline comments by at least two spaces.
781 An inline comment is a comment on the same line as a statement. Inline
782 comments should be separated by at least two spaces from the statement.
783 They should start with a # and a single space.
785 Each line of a block comment starts with a # and a single space
786 (unless it is indented text inside the comment).
788 Okay: x = x + 1 # Increment x
789 Okay: x = x + 1 # Increment x
790 Okay: # Block comment
791 E261: x = x + 1 # Increment x
792 E262: x = x + 1 #Increment x
793 E262: x = x + 1 # Increment x
795 E266: ### Block comment
798 for token_type, text, start, end, line in tokens:
799 if token_type == tokenize.COMMENT:
800 inline_comment = line[:start[1]].strip()
802 if prev_end[0] == start[0] and start[1] < prev_end[1] + 2:
804 "E261 at least two spaces before inline comment")
805 symbol, sp, comment = text.partition(' ')
806 bad_prefix = symbol not in '#:' and (symbol.lstrip('#')[:1] or '#')
808 if bad_prefix or comment[:1] in WHITESPACE:
809 yield start, "E262 inline comment should start with '# '"
810 elif bad_prefix and (bad_prefix != '!' or start[0] > 1):
811 if bad_prefix != '#':
812 yield start, "E265 block comment should start with '# '"
814 yield start, "E266 too many leading '#' for block comment"
815 elif token_type != tokenize.NL:
819 def imports_on_separate_lines(logical_line):
820 r"""Imports should usually be on separate lines.
822 Okay: import os\nimport sys
825 Okay: from subprocess import Popen, PIPE
826 Okay: from myclas import MyClass
827 Okay: from foo.bar.yourclass import YourClass
829 Okay: import foo.bar.yourclass
832 if line.startswith('import '):
833 found = line.find(',')
834 if -1 < found and ';' not in line[:found]:
835 yield found, "E401 multiple imports on one line"
838 def imports_on_top_of_file(logical_line, indent_level, checker_state, noqa):
839 r"""Imports are always put at the top of the file, just after any module
840 comments and docstrings, and before module globals and constants.
843 Okay: # this is a comment\nimport os
844 Okay: '''this is a module docstring'''\nimport os
845 Okay: r'''this is a module docstring'''\nimport os
846 Okay: __version__ = "123"\nimport os
848 E402: 'One string'\n"Two string"\nimport os
849 E402: a=1\nfrom sys import x
851 Okay: if x:\n import os
853 def is_string_literal(line):
854 if line[0] in 'uUbB':
856 if line and line[0] in 'rR':
858 return line and (line[0] == '"' or line[0] == "'")
860 if indent_level: # Allow imports in conditional statements or functions
862 if not logical_line: # Allow empty lines or comments
867 if line.startswith('import ') or line.startswith('from '):
868 if checker_state.get('seen_non_imports', False):
869 yield 0, "E402 import not at top of file"
870 elif line.startswith('__version__ '):
871 # These lines should be included after the module's docstring, before
872 # any other code, separated by a blank line above and below.
874 elif is_string_literal(line):
875 # The first literal is a docstring, allow it. Otherwise, report error.
876 if checker_state.get('seen_docstring', False):
877 checker_state['seen_non_imports'] = True
879 checker_state['seen_docstring'] = True
881 checker_state['seen_non_imports'] = True
884 def compound_statements(logical_line):
885 r"""Compound statements (on the same line) are generally discouraged.
887 While sometimes it's okay to put an if/for/while with a small body
888 on the same line, never do this for multi-clause statements.
889 Also avoid folding such long lines!
891 Always use a def statement instead of an assignment statement that
892 binds a lambda expression directly to a name.
894 Okay: if foo == 'blah':\n do_blah_thing()
899 E701: if foo == 'blah': do_blah_thing()
900 E701: for x in lst: total += x
901 E701: while t < 10: t = delay()
902 E701: if foo == 'blah': do_blah_thing()
903 E701: else: do_non_blah_thing()
904 E701: try: something()
905 E701: finally: cleanup()
906 E701: if foo == 'blah': one(); two(); three()
907 E702: do_one(); do_two(); do_three()
908 E703: do_four(); # useless semicolon
909 E704: def f(x): return 2*x
910 E731: f = lambda x: 2*x
913 last_char = len(line) - 1
914 found = line.find(':')
915 while -1 < found < last_char:
916 before = line[:found]
917 if ((before.count('{') <= before.count('}') and # {'a': 1} (dict)
918 before.count('[') <= before.count(']') and # [1:2] (slice)
919 before.count('(') <= before.count(')'))): # (annotation)
920 if LAMBDA_REGEX.search(before):
921 yield 0, "E731 do not assign a lambda expression, use a def"
923 if before.startswith('def '):
924 yield 0, "E704 multiple statements on one line (def)"
926 yield found, "E701 multiple statements on one line (colon)"
927 found = line.find(':', found + 1)
928 found = line.find(';')
930 if found < last_char:
931 yield found, "E702 multiple statements on one line (semicolon)"
933 yield found, "E703 statement ends with a semicolon"
934 found = line.find(';', found + 1)
937 def explicit_line_join(logical_line, tokens):
938 r"""Avoid explicit line join between brackets.
940 The preferred way of wrapping long lines is by using Python's implied line
941 continuation inside parentheses, brackets and braces. Long lines can be
942 broken over multiple lines by wrapping expressions in parentheses. These
943 should be used in preference to using a backslash for line continuation.
945 E502: aaa = [123, \\n 123]
946 E502: aaa = ("bbb " \\n "ccc")
948 Okay: aaa = [123,\n 123]
949 Okay: aaa = ("bbb "\n "ccc")
950 Okay: aaa = "bbb " \\n "ccc"
952 prev_start = prev_end = parens = 0
953 for token_type, text, start, end, line in tokens:
954 if start[0] != prev_start and parens and backslash:
955 yield backslash, "E502 the backslash is redundant between brackets"
956 if end[0] != prev_end:
957 if line.rstrip('\r\n').endswith('\\'):
958 backslash = (end[0], len(line.splitlines()[-1]) - 1)
961 prev_start = prev_end = end[0]
963 prev_start = start[0]
964 if token_type == tokenize.OP:
971 def comparison_to_singleton(logical_line, noqa):
972 r"""Comparison to singletons should use "is" or "is not".
974 Comparisons to singletons like None should always be done
975 with "is" or "is not", never the equality operators.
977 Okay: if arg is not None:
978 E711: if arg != None:
979 E712: if arg == True:
981 Also, beware of writing if x when you really mean if x is not None --
982 e.g. when testing whether a variable or argument that defaults to None was
983 set to some other value. The other value might have a type (such as a
984 container) that could be false in a boolean context!
986 match = not noqa and COMPARE_SINGLETON_REGEX.search(logical_line)
988 same = (match.group(1) == '==')
989 singleton = match.group(2)
990 msg = "'if cond is %s:'" % (('' if same else 'not ') + singleton)
991 if singleton in ('None',):
995 nonzero = ((singleton == 'True' and same) or
996 (singleton == 'False' and not same))
997 msg += " or 'if %scond:'" % ('' if nonzero else 'not ')
998 yield match.start(1), ("%s comparison to %s should be %s" %
999 (code, singleton, msg))
1002 def comparison_negative(logical_line):
1003 r"""Negative comparison should be done using "not in" and "is not".
1005 Okay: if x not in y:\n pass
1006 Okay: assert (X in Y or X is Z)
1007 Okay: if not (X in Y):\n pass
1008 Okay: zz = x is not y
1009 E713: Z = not X in Y
1010 E713: if not X.B in Y:\n pass
1011 E714: if not X is Y:\n pass
1012 E714: Z = not X.B is Y
1014 match = COMPARE_NEGATIVE_REGEX.search(logical_line)
1016 pos = match.start(1)
1017 if match.group(2) == 'in':
1018 yield pos, "E713 test for membership should be 'not in'"
1020 yield pos, "E714 test for object identity should be 'is not'"
1023 def comparison_type(logical_line):
1024 r"""Object type comparisons should always use isinstance().
1026 Do not compare types directly.
1028 Okay: if isinstance(obj, int):
1029 E721: if type(obj) is type(1):
1031 When checking if an object is a string, keep in mind that it might be a
1032 unicode string too! In Python 2.3, str and unicode have a common base
1033 class, basestring, so you can do:
1035 Okay: if isinstance(obj, basestring):
1036 Okay: if type(a1) is type(b1):
1038 match = COMPARE_TYPE_REGEX.search(logical_line)
1040 inst = match.group(1)
1041 if inst and isidentifier(inst) and inst not in SINGLETONS:
1042 return # Allow comparison for types which are not obvious
1043 yield match.start(), "E721 do not compare types, use 'isinstance()'"
1046 def python_3000_has_key(logical_line, noqa):
1047 r"""The {}.has_key() method is removed in Python 3: use the 'in' operator.
1049 Okay: if "alph" in d:\n print d["alph"]
1050 W601: assert d.has_key('alph')
1052 pos = logical_line.find('.has_key(')
1053 if pos > -1 and not noqa:
1054 yield pos, "W601 .has_key() is deprecated, use 'in'"
1057 def python_3000_raise_comma(logical_line):
1058 r"""When raising an exception, use "raise ValueError('message')".
1060 The older form is removed in Python 3.
1062 Okay: raise DummyError("Message")
1063 W602: raise DummyError, "Message"
1065 match = RAISE_COMMA_REGEX.match(logical_line)
1066 if match and not RERAISE_COMMA_REGEX.match(logical_line):
1067 yield match.end() - 1, "W602 deprecated form of raising exception"
1070 def python_3000_not_equal(logical_line):
1071 r"""New code should always use != instead of <>.
1073 The older syntax is removed in Python 3.
1078 pos = logical_line.find('<>')
1080 yield pos, "W603 '<>' is deprecated, use '!='"
1083 def python_3000_backticks(logical_line):
1084 r"""Backticks are removed in Python 3: use repr() instead.
1086 Okay: val = repr(1 + 2)
1089 pos = logical_line.find('`')
1091 yield pos, "W604 backticks are deprecated, use 'repr()'"
1094 ##############################################################################
1096 ##############################################################################
1099 if '' == ''.encode():
1100 # Python 2: implicit encoding.
1101 def readlines(filename):
1102 """Read the source code."""
1103 with open(filename, 'rU') as f:
1104 return f.readlines()
1105 isidentifier = re.compile(r'[a-zA-Z_]\w*').match
1106 stdin_get_value = sys.stdin.read
1109 def readlines(filename):
1110 """Read the source code."""
1112 with open(filename, 'rb') as f:
1113 (coding, lines) = tokenize.detect_encoding(f.readline)
1114 f = TextIOWrapper(f, coding, line_buffering=True)
1115 return [l.decode(coding) for l in lines] + f.readlines()
1116 except (LookupError, SyntaxError, UnicodeError):
1117 # Fall back if file encoding is improperly declared
1118 with open(filename, encoding='latin-1') as f:
1119 return f.readlines()
1120 isidentifier = str.isidentifier
1122 def stdin_get_value():
1123 return TextIOWrapper(sys.stdin.buffer, errors='ignore').read()
1124 noqa = re.compile(r'# no(?:qa|pep8)\b', re.I).search
1127 def expand_indent(line):
1128 r"""Return the amount of indentation.
1130 Tabs are expanded to the next multiple of 8.
1132 >>> expand_indent(' ')
1134 >>> expand_indent('\t')
1136 >>> expand_indent(' \t')
1138 >>> expand_indent(' \t')
1141 if '\t' not in line:
1142 return len(line) - len(line.lstrip())
1146 result = result // 8 * 8 + 8
1154 def mute_string(text):
1155 """Replace contents with 'xxx' to prevent syntax matching.
1157 >>> mute_string('"abc"')
1159 >>> mute_string("'''abc'''")
1161 >>> mute_string("r'abc'")
1164 # String modifiers (e.g. u or r)
1165 start = text.index(text[-1]) + 1
1168 if text[-3:] in ('"""', "'''"):
1171 return text[:start] + 'x' * (end - start) + text[end:]
1174 def parse_udiff(diff, patterns=None, parent='.'):
1175 """Return a dictionary of matching lines."""
1176 # For each file of the diff, the entry key is the filename,
1177 # and the value is a set of row numbers to consider.
1180 for line in diff.splitlines():
1185 if line[:3] == '@@ ':
1186 hunk_match = HUNK_REGEX.match(line)
1187 (row, nrows) = [int(g or '1') for g in hunk_match.groups()]
1188 rv[path].update(range(row, row + nrows))
1189 elif line[:3] == '+++':
1190 path = line[4:].split('\t', 1)[0]
1191 if path[:2] == 'b/':
1194 return dict([(os.path.join(parent, path), rows)
1195 for (path, rows) in rv.items()
1196 if rows and filename_match(path, patterns)])
1199 def normalize_paths(value, parent=os.curdir):
1200 """Parse a comma-separated list of paths.
1202 Return a list of absolute paths.
1204 if not value or isinstance(value, list):
1207 for path in value.split(','):
1209 path = os.path.abspath(os.path.join(parent, path))
1210 paths.append(path.rstrip('/'))
1214 def filename_match(filename, patterns, default=True):
1215 """Check if patterns contains a pattern that matches filename.
1217 If patterns is unspecified, this always returns True.
1221 return any(fnmatch(filename, pattern) for pattern in patterns)
1225 def _is_eol_token(token):
1226 return (token[0] in NEWLINE or
1227 (token[0] == tokenize.COMMENT and token[1] == token[4]))
1229 def _is_eol_token(token):
1230 return token[0] in NEWLINE
1233 ##############################################################################
1234 # Framework to run all checks
1235 ##############################################################################
1238 _checks = {'physical_line': {}, 'logical_line': {}, 'tree': {}}
1241 def register_check(check, codes=None):
1242 """Register a new check object."""
1243 def _add_check(check, kind, codes, args):
1244 if check in _checks[kind]:
1245 _checks[kind][check][0].extend(codes or [])
1247 _checks[kind][check] = (codes or [''], args)
1248 if inspect.isfunction(check):
1249 args = inspect.getargspec(check)[0]
1250 if args and args[0] in ('physical_line', 'logical_line'):
1252 codes = ERRORCODE_REGEX.findall(check.__doc__ or '')
1253 _add_check(check, args[0], codes, args)
1254 elif inspect.isclass(check):
1255 if inspect.getargspec(check.__init__)[0][:2] == ['self', 'tree']:
1256 _add_check(check, 'tree', codes, None)
1259 def init_checks_registry():
1260 """Register all globally visible functions.
1262 The first argument name is either 'physical_line' or 'logical_line'.
1264 mod = inspect.getmodule(register_check)
1265 for (name, function) in inspect.getmembers(mod, inspect.isfunction):
1266 register_check(function)
1267 init_checks_registry()
1270 class Checker(object):
1271 """Load a Python source file, tokenize it, check coding style."""
1273 def __init__(self, filename=None, lines=None,
1274 options=None, report=None, **kwargs):
1276 options = StyleGuide(kwargs).options
1279 self._io_error = None
1280 self._physical_checks = options.physical_checks
1281 self._logical_checks = options.logical_checks
1282 self._ast_checks = options.ast_checks
1283 self.max_line_length = options.max_line_length
1284 self.multiline = False # in a multiline string?
1285 self.hang_closing = options.hang_closing
1286 self.verbose = options.verbose
1287 self.filename = filename
1288 # Dictionary where a checker can store its custom state.
1289 self._checker_states = {}
1290 if filename is None:
1291 self.filename = 'stdin'
1292 self.lines = lines or []
1293 elif filename == '-':
1294 self.filename = 'stdin'
1295 self.lines = stdin_get_value().splitlines(True)
1298 self.lines = readlines(filename)
1300 (exc_type, exc) = sys.exc_info()[:2]
1301 self._io_error = '%s: %s' % (exc_type.__name__, exc)
1306 ord0 = ord(self.lines[0][0])
1307 if ord0 in (0xef, 0xfeff): # Strip the UTF-8 BOM
1309 self.lines[0] = self.lines[0][1:]
1310 elif self.lines[0][:3] == '\xef\xbb\xbf':
1311 self.lines[0] = self.lines[0][3:]
1312 self.report = report or options.report
1313 self.report_error = self.report.error
1315 def report_invalid_syntax(self):
1316 """Check if the syntax is valid."""
1317 (exc_type, exc) = sys.exc_info()[:2]
1318 if len(exc.args) > 1:
1319 offset = exc.args[1]
1321 offset = offset[1:3]
1324 self.report_error(offset[0], offset[1] or 0,
1325 'E901 %s: %s' % (exc_type.__name__, exc.args[0]),
1326 self.report_invalid_syntax)
1329 """Get the next line from the input buffer."""
1330 if self.line_number >= self.total_lines:
1332 line = self.lines[self.line_number]
1333 self.line_number += 1
1334 if self.indent_char is None and line[:1] in WHITESPACE:
1335 self.indent_char = line[0]
1338 def run_check(self, check, argument_names):
1339 """Run a check plugin."""
1341 for name in argument_names:
1342 arguments.append(getattr(self, name))
1343 return check(*arguments)
1345 def init_checker_state(self, name, argument_names):
1346 """ Prepares a custom state for the specific checker plugin."""
1347 if 'checker_state' in argument_names:
1348 self.checker_state = self._checker_states.setdefault(name, {})
1350 def check_physical(self, line):
1351 """Run all physical checks on a raw input line."""
1352 self.physical_line = line
1353 for name, check, argument_names in self._physical_checks:
1354 self.init_checker_state(name, argument_names)
1355 result = self.run_check(check, argument_names)
1356 if result is not None:
1357 (offset, text) = result
1358 self.report_error(self.line_number, offset, text, check)
1359 if text[:4] == 'E101':
1360 self.indent_char = line[0]
1362 def build_tokens_line(self):
1363 """Build a logical line from tokens."""
1367 prev_row = prev_col = mapping = None
1368 for token_type, text, start, end, line in self.tokens:
1369 if token_type in SKIP_TOKENS:
1372 mapping = [(0, start)]
1373 if token_type == tokenize.COMMENT:
1374 comments.append(text)
1376 if token_type == tokenize.STRING:
1377 text = mute_string(text)
1379 (start_row, start_col) = start
1380 if prev_row != start_row: # different row
1381 prev_text = self.lines[prev_row - 1][prev_col - 1]
1382 if prev_text == ',' or (prev_text not in '{[('
1383 and text not in '}])'):
1385 elif prev_col != start_col: # different column
1386 text = line[prev_col:start_col] + text
1387 logical.append(text)
1389 mapping.append((length, end))
1390 (prev_row, prev_col) = end
1391 self.logical_line = ''.join(logical)
1392 self.noqa = comments and noqa(''.join(comments))
1395 def check_logical(self):
1396 """Build a line from tokens and run all logical checks on it."""
1397 self.report.increment_logical_line()
1398 mapping = self.build_tokens_line()
1399 (start_row, start_col) = mapping[0][1]
1400 start_line = self.lines[start_row - 1]
1401 self.indent_level = expand_indent(start_line[:start_col])
1402 if self.blank_before < self.blank_lines:
1403 self.blank_before = self.blank_lines
1404 if self.verbose >= 2:
1405 print(self.logical_line[:80].rstrip())
1406 for name, check, argument_names in self._logical_checks:
1407 if self.verbose >= 4:
1409 self.init_checker_state(name, argument_names)
1410 for offset, text in self.run_check(check, argument_names) or ():
1411 if not isinstance(offset, tuple):
1412 for token_offset, pos in mapping:
1413 if offset <= token_offset:
1415 offset = (pos[0], pos[1] + offset - token_offset)
1416 self.report_error(offset[0], offset[1], text, check)
1417 if self.logical_line:
1418 self.previous_indent_level = self.indent_level
1419 self.previous_logical = self.logical_line
1420 self.blank_lines = 0
1423 def check_ast(self):
1424 """Build the file's AST and run all AST checks."""
1426 tree = compile(''.join(self.lines), '', 'exec', PyCF_ONLY_AST)
1427 except (SyntaxError, TypeError):
1428 return self.report_invalid_syntax()
1429 for name, cls, __ in self._ast_checks:
1430 checker = cls(tree, self.filename)
1431 for lineno, offset, text, check in checker.run():
1432 if not self.lines or not noqa(self.lines[lineno - 1]):
1433 self.report_error(lineno, offset, text, check)
1435 def generate_tokens(self):
1436 """Tokenize the file, run physical line checks and yield tokens."""
1438 self.report_error(1, 0, 'E902 %s' % self._io_error, readlines)
1439 tokengen = tokenize.generate_tokens(self.readline)
1441 for token in tokengen:
1442 if token[2][0] > self.total_lines:
1444 self.maybe_check_physical(token)
1446 except (SyntaxError, tokenize.TokenError):
1447 self.report_invalid_syntax()
1449 def maybe_check_physical(self, token):
1450 """If appropriate (based on token), check current physical line(s)."""
1451 # Called after every token, but act only on end of line.
1452 if _is_eol_token(token):
1453 # Obviously, a newline token ends a single physical line.
1454 self.check_physical(token[4])
1455 elif token[0] == tokenize.STRING and '\n' in token[1]:
1456 # Less obviously, a string that contains newlines is a
1457 # multiline string, either triple-quoted or with internal
1458 # newlines backslash-escaped. Check every physical line in the
1459 # string *except* for the last one: its newline is outside of
1460 # the multiline string, so we consider it a regular physical
1461 # line, and will check it like any other physical line.
1464 # - we don't *completely* ignore the last line; if it contains
1465 # the magical "# noqa" comment, we disable all physical
1466 # checks for the entire multiline string
1467 # - have to wind self.line_number back because initially it
1468 # points to the last line of the string, and we want
1469 # check_physical() to give accurate feedback
1472 self.multiline = True
1473 self.line_number = token[2][0]
1474 for line in token[1].split('\n')[:-1]:
1475 self.check_physical(line + '\n')
1476 self.line_number += 1
1477 self.multiline = False
1479 def check_all(self, expected=None, line_offset=0):
1480 """Run all checks on the input file."""
1481 self.report.init_file(self.filename, self.lines, expected, line_offset)
1482 self.total_lines = len(self.lines)
1483 if self._ast_checks:
1485 self.line_number = 0
1486 self.indent_char = None
1487 self.indent_level = self.previous_indent_level = 0
1488 self.previous_logical = ''
1490 self.blank_lines = self.blank_before = 0
1492 for token in self.generate_tokens():
1493 self.tokens.append(token)
1494 token_type, text = token[0:2]
1495 if self.verbose >= 3:
1496 if token[2][0] == token[3][0]:
1497 pos = '[%s:%s]' % (token[2][1] or '', token[3][1])
1499 pos = 'l.%s' % token[3][0]
1500 print('l.%s\t%s\t%s\t%r' %
1501 (token[2][0], pos, tokenize.tok_name[token[0]], text))
1502 if token_type == tokenize.OP:
1508 if token_type in NEWLINE:
1509 if token_type == tokenize.NEWLINE:
1510 self.check_logical()
1511 self.blank_before = 0
1512 elif len(self.tokens) == 1:
1513 # The physical line contains only this token.
1514 self.blank_lines += 1
1517 self.check_logical()
1518 elif COMMENT_WITH_NL and token_type == tokenize.COMMENT:
1519 if len(self.tokens) == 1:
1520 # The comment also ends a physical line
1522 token[1] = text.rstrip('\r\n')
1523 token[3] = (token[2][0], token[2][1] + len(token[1]))
1524 self.tokens = [tuple(token)]
1525 self.check_logical()
1527 self.check_physical(self.lines[-1])
1528 self.check_logical()
1529 return self.report.get_file_results()
1532 class BaseReport(object):
1533 """Collect the results of the checks."""
1535 print_filename = False
1537 def __init__(self, options):
1538 self._benchmark_keys = options.benchmark_keys
1539 self._ignore_code = options.ignore_code
1542 self.total_errors = 0
1543 self.counters = dict.fromkeys(self._benchmark_keys, 0)
1547 """Start the timer."""
1548 self._start_time = time.time()
1551 """Stop the timer."""
1552 self.elapsed = time.time() - self._start_time
1554 def init_file(self, filename, lines, expected, line_offset):
1555 """Signal a new file."""
1556 self.filename = filename
1558 self.expected = expected or ()
1559 self.line_offset = line_offset
1560 self.file_errors = 0
1561 self.counters['files'] += 1
1562 self.counters['physical lines'] += len(lines)
1564 def increment_logical_line(self):
1565 """Signal a new logical line."""
1566 self.counters['logical lines'] += 1
1568 def error(self, line_number, offset, text, check):
1569 """Report an error, according to options."""
1571 if self._ignore_code(code):
1573 if code in self.counters:
1574 self.counters[code] += 1
1576 self.counters[code] = 1
1577 self.messages[code] = text[5:]
1578 # Don't care about expected errors or warnings
1579 if code in self.expected:
1581 if self.print_filename and not self.file_errors:
1582 print(self.filename)
1583 self.file_errors += 1
1584 self.total_errors += 1
1587 def get_file_results(self):
1588 """Return the count of errors and warnings for this file."""
1589 return self.file_errors
1591 def get_count(self, prefix=''):
1592 """Return the total count of errors and warnings."""
1593 return sum([self.counters[key]
1594 for key in self.messages if key.startswith(prefix)])
1596 def get_statistics(self, prefix=''):
1597 """Get statistics for message codes that start with the prefix.
1599 prefix='' matches all errors and warnings
1600 prefix='E' matches all errors
1601 prefix='W' matches all warnings
1602 prefix='E4' matches all errors that have to do with imports
1604 return ['%-7s %s %s' % (self.counters[key], key, self.messages[key])
1605 for key in sorted(self.messages) if key.startswith(prefix)]
1607 def print_statistics(self, prefix=''):
1608 """Print overall statistics (number of errors and warnings)."""
1609 for line in self.get_statistics(prefix):
1612 def print_benchmark(self):
1613 """Print benchmark numbers."""
1614 print('%-7.2f %s' % (self.elapsed, 'seconds elapsed'))
1616 for key in self._benchmark_keys:
1617 print('%-7d %s per second (%d total)' %
1618 (self.counters[key] / self.elapsed, key,
1619 self.counters[key]))
1622 class FileReport(BaseReport):
1623 """Collect the results of the checks and print only the filenames."""
1624 print_filename = True
1627 class StandardReport(BaseReport):
1628 """Collect and print the results of the checks."""
1630 def __init__(self, options):
1631 super(StandardReport, self).__init__(options)
1632 self._fmt = REPORT_FORMAT.get(options.format.lower(),
1634 self._repeat = options.repeat
1635 self._show_source = options.show_source
1636 self._show_pep8 = options.show_pep8
1638 def init_file(self, filename, lines, expected, line_offset):
1639 """Signal a new file."""
1640 self._deferred_print = []
1641 return super(StandardReport, self).init_file(
1642 filename, lines, expected, line_offset)
1644 def error(self, line_number, offset, text, check):
1645 """Report an error, according to options."""
1646 code = super(StandardReport, self).error(line_number, offset,
1648 if code and (self.counters[code] == 1 or self._repeat):
1649 self._deferred_print.append(
1650 (line_number, offset, code, text[5:], check.__doc__))
1653 def get_file_results(self):
1654 """Print the result and return the overall count for this file."""
1655 self._deferred_print.sort()
1656 for line_number, offset, code, text, doc in self._deferred_print:
1658 'path': self.filename,
1659 'row': self.line_offset + line_number, 'col': offset + 1,
1660 'code': code, 'text': text,
1662 if self._show_source:
1663 if line_number > len(self.lines):
1666 line = self.lines[line_number - 1]
1667 print(line.rstrip())
1668 print(re.sub(r'\S', ' ', line[:offset]) + '^')
1669 if self._show_pep8 and doc:
1670 print(' ' + doc.strip())
1671 return self.file_errors
1674 class DiffReport(StandardReport):
1675 """Collect and print the results for the changed lines only."""
1677 def __init__(self, options):
1678 super(DiffReport, self).__init__(options)
1679 self._selected = options.selected_lines
1681 def error(self, line_number, offset, text, check):
1682 if line_number not in self._selected[self.filename]:
1684 return super(DiffReport, self).error(line_number, offset, text, check)
1687 class StyleGuide(object):
1688 """Initialize a PEP-8 instance with few options."""
1690 def __init__(self, *args, **kwargs):
1691 # build options from the command line
1692 self.checker_class = kwargs.pop('checker_class', Checker)
1693 parse_argv = kwargs.pop('parse_argv', False)
1694 config_file = kwargs.pop('config_file', None)
1695 parser = kwargs.pop('parser', None)
1696 # build options from dict
1697 options_dict = dict(*args, **kwargs)
1698 arglist = None if parse_argv else options_dict.get('paths', None)
1699 options, self.paths = process_options(
1700 arglist, parse_argv, config_file, parser)
1702 options.__dict__.update(options_dict)
1703 if 'paths' in options_dict:
1704 self.paths = options_dict['paths']
1706 self.runner = self.input_file
1707 self.options = options
1709 if not options.reporter:
1710 options.reporter = BaseReport if options.quiet else StandardReport
1712 options.select = tuple(options.select or ())
1713 if not (options.select or options.ignore or
1714 options.testsuite or options.doctest) and DEFAULT_IGNORE:
1715 # The default choice: ignore controversial checks
1716 options.ignore = tuple(DEFAULT_IGNORE.split(','))
1718 # Ignore all checks which are not explicitly selected
1719 options.ignore = ('',) if options.select else tuple(options.ignore)
1720 options.benchmark_keys = BENCHMARK_KEYS[:]
1721 options.ignore_code = self.ignore_code
1722 options.physical_checks = self.get_checks('physical_line')
1723 options.logical_checks = self.get_checks('logical_line')
1724 options.ast_checks = self.get_checks('tree')
1727 def init_report(self, reporter=None):
1728 """Initialize the report instance."""
1729 self.options.report = (reporter or self.options.reporter)(self.options)
1730 return self.options.report
1732 def check_files(self, paths=None):
1733 """Run all checks on the paths."""
1736 report = self.options.report
1737 runner = self.runner
1741 if os.path.isdir(path):
1742 self.input_dir(path)
1743 elif not self.excluded(path):
1745 except KeyboardInterrupt:
1746 print('... stopped')
1750 def input_file(self, filename, lines=None, expected=None, line_offset=0):
1751 """Run all checks on a Python source file."""
1752 if self.options.verbose:
1753 print('checking %s' % filename)
1754 fchecker = self.checker_class(
1755 filename, lines=lines, options=self.options)
1756 return fchecker.check_all(expected=expected, line_offset=line_offset)
1758 def input_dir(self, dirname):
1759 """Check all files in this directory and all subdirectories."""
1760 dirname = dirname.rstrip('/')
1761 if self.excluded(dirname):
1763 counters = self.options.report.counters
1764 verbose = self.options.verbose
1765 filepatterns = self.options.filename
1766 runner = self.runner
1767 for root, dirs, files in os.walk(dirname):
1769 print('directory ' + root)
1770 counters['directories'] += 1
1771 for subdir in sorted(dirs):
1772 if self.excluded(subdir, root):
1774 for filename in sorted(files):
1775 # contain a pattern that matches?
1776 if ((filename_match(filename, filepatterns) and
1777 not self.excluded(filename, root))):
1778 runner(os.path.join(root, filename))
1780 def excluded(self, filename, parent=None):
1781 """Check if the file should be excluded.
1783 Check if 'options.exclude' contains a pattern that matches filename.
1785 if not self.options.exclude:
1787 basename = os.path.basename(filename)
1788 if filename_match(basename, self.options.exclude):
1791 filename = os.path.join(parent, filename)
1792 filename = os.path.abspath(filename)
1793 return filename_match(filename, self.options.exclude)
1795 def ignore_code(self, code):
1796 """Check if the error code should be ignored.
1798 If 'options.select' contains a prefix of the error code,
1799 return False. Else, if 'options.ignore' contains a prefix of
1800 the error code, return True.
1802 if len(code) < 4 and any(s.startswith(code)
1803 for s in self.options.select):
1805 return (code.startswith(self.options.ignore) and
1806 not code.startswith(self.options.select))
1808 def get_checks(self, argument_name):
1809 """Get all the checks for this category.
1811 Find all globally visible functions where the first argument name
1812 starts with argument_name and which contain selected tests.
1815 for check, attrs in _checks[argument_name].items():
1816 (codes, args) = attrs
1817 if any(not (code and self.ignore_code(code)) for code in codes):
1818 checks.append((check.__name__, check, args))
1819 return sorted(checks)
1822 def get_parser(prog='pep8', version=__version__):
1823 parser = OptionParser(prog=prog, version=version,
1824 usage="%prog [options] input ...")
1825 parser.config_options = [
1826 'exclude', 'filename', 'select', 'ignore', 'max-line-length',
1827 'hang-closing', 'count', 'format', 'quiet', 'show-pep8',
1828 'show-source', 'statistics', 'verbose']
1829 parser.add_option('-v', '--verbose', default=0, action='count',
1830 help="print status messages, or debug with -vv")
1831 parser.add_option('-q', '--quiet', default=0, action='count',
1832 help="report only file names, or nothing with -qq")
1833 parser.add_option('-r', '--repeat', default=True, action='store_true',
1834 help="(obsolete) show all occurrences of the same error")
1835 parser.add_option('--first', action='store_false', dest='repeat',
1836 help="show first occurrence of each error")
1837 parser.add_option('--exclude', metavar='patterns', default=DEFAULT_EXCLUDE,
1838 help="exclude files or directories which match these "
1839 "comma separated patterns (default: %default)")
1840 parser.add_option('--filename', metavar='patterns', default='*.py',
1841 help="when parsing directories, only check filenames "
1842 "matching these comma separated patterns "
1843 "(default: %default)")
1844 parser.add_option('--select', metavar='errors', default='',
1845 help="select errors and warnings (e.g. E,W6)")
1846 parser.add_option('--ignore', metavar='errors', default='',
1847 help="skip errors and warnings (e.g. E4,W)")
1848 parser.add_option('--show-source', action='store_true',
1849 help="show source code for each error")
1850 parser.add_option('--show-pep8', action='store_true',
1851 help="show text of PEP 8 for each error "
1852 "(implies --first)")
1853 parser.add_option('--statistics', action='store_true',
1854 help="count errors and warnings")
1855 parser.add_option('--count', action='store_true',
1856 help="print total number of errors and warnings "
1857 "to standard error and set exit code to 1 if "
1858 "total is not null")
1859 parser.add_option('--max-line-length', type='int', metavar='n',
1860 default=MAX_LINE_LENGTH,
1861 help="set maximum allowed line length "
1862 "(default: %default)")
1863 parser.add_option('--hang-closing', action='store_true',
1864 help="hang closing bracket instead of matching "
1865 "indentation of opening bracket's line")
1866 parser.add_option('--format', metavar='format', default='default',
1867 help="set the error format [default|pylint|<custom>]")
1868 parser.add_option('--diff', action='store_true',
1869 help="report only lines changed according to the "
1870 "unified diff received on STDIN")
1871 group = parser.add_option_group("Testing Options")
1872 if os.path.exists(TESTSUITE_PATH):
1873 group.add_option('--testsuite', metavar='dir',
1874 help="run regression tests from dir")
1875 group.add_option('--doctest', action='store_true',
1876 help="run doctest on myself")
1877 group.add_option('--benchmark', action='store_true',
1878 help="measure processing speed")
1882 def read_config(options, args, arglist, parser):
1883 """Read both user configuration and local configuration."""
1884 config = RawConfigParser()
1886 user_conf = options.config
1887 if user_conf and os.path.isfile(user_conf):
1889 print('user configuration: %s' % user_conf)
1890 config.read(user_conf)
1892 local_dir = os.curdir
1893 parent = tail = args and os.path.abspath(os.path.commonprefix(args))
1895 if config.read([os.path.join(parent, fn) for fn in PROJECT_CONFIG]):
1898 print('local configuration: in %s' % parent)
1900 (parent, tail) = os.path.split(parent)
1902 pep8_section = parser.prog
1903 if config.has_section(pep8_section):
1904 option_list = dict([(o.dest, o.type or o.action)
1905 for o in parser.option_list])
1907 # First, read the default values
1908 (new_options, __) = parser.parse_args([])
1910 # Second, parse the configuration
1911 for opt in config.options(pep8_section):
1912 if opt.replace('_', '-') not in parser.config_options:
1913 print(" unknown option '%s' ignored" % opt)
1915 if options.verbose > 1:
1916 print(" %s = %s" % (opt, config.get(pep8_section, opt)))
1917 normalized_opt = opt.replace('-', '_')
1918 opt_type = option_list[normalized_opt]
1919 if opt_type in ('int', 'count'):
1920 value = config.getint(pep8_section, opt)
1921 elif opt_type == 'string':
1922 value = config.get(pep8_section, opt)
1923 if normalized_opt == 'exclude':
1924 value = normalize_paths(value, local_dir)
1926 assert opt_type in ('store_true', 'store_false')
1927 value = config.getboolean(pep8_section, opt)
1928 setattr(new_options, normalized_opt, value)
1930 # Third, overwrite with the command-line options
1931 (options, __) = parser.parse_args(arglist, values=new_options)
1932 options.doctest = options.testsuite = False
1936 def process_options(arglist=None, parse_argv=False, config_file=None,
1938 """Process options passed either via arglist or via command line args."""
1940 parser = get_parser()
1941 if not parser.has_option('--config'):
1942 if config_file is True:
1943 config_file = DEFAULT_CONFIG
1944 group = parser.add_option_group("Configuration", description=(
1945 "The project options are read from the [%s] section of the "
1946 "tox.ini file or the setup.cfg file located in any parent folder "
1947 "of the path(s) being processed. Allowed options are: %s." %
1948 (parser.prog, ', '.join(parser.config_options))))
1949 group.add_option('--config', metavar='path', default=config_file,
1950 help="user config file location (default: %default)")
1951 # Don't read the command line if the module is used as a library.
1952 if not arglist and not parse_argv:
1954 # If parse_argv is True and arglist is None, arguments are
1955 # parsed from the command line (sys.argv)
1956 (options, args) = parser.parse_args(arglist)
1957 options.reporter = None
1959 if options.ensure_value('testsuite', False):
1960 args.append(options.testsuite)
1961 elif not options.ensure_value('doctest', False):
1962 if parse_argv and not args:
1963 if options.diff or any(os.path.exists(name)
1964 for name in PROJECT_CONFIG):
1967 parser.error('input not specified')
1968 options = read_config(options, args, arglist, parser)
1969 options.reporter = parse_argv and options.quiet == 1 and FileReport
1971 options.filename = options.filename and options.filename.split(',')
1972 options.exclude = normalize_paths(options.exclude)
1973 options.select = options.select and options.select.split(',')
1974 options.ignore = options.ignore and options.ignore.split(',')
1977 options.reporter = DiffReport
1978 stdin = stdin_get_value()
1979 options.selected_lines = parse_udiff(stdin, options.filename, args[0])
1980 args = sorted(options.selected_lines)
1982 return options, args
1986 """Parse options and run checks on Python source."""
1989 # Handle "Broken pipe" gracefully
1991 signal.signal(signal.SIGPIPE, lambda signum, frame: sys.exit(1))
1992 except AttributeError:
1993 pass # not supported on Windows
1995 pep8style = StyleGuide(parse_argv=True, config_file=True)
1996 options = pep8style.options
1997 if options.doctest or options.testsuite:
1998 from testsuite.support import run_tests
1999 report = run_tests(pep8style)
2001 report = pep8style.check_files()
2002 if options.statistics:
2003 report.print_statistics()
2004 if options.benchmark:
2005 report.print_benchmark()
2006 if options.testsuite and not options.quiet:
2007 report.print_results()
2008 if report.total_errors:
2010 sys.stderr.write(str(report.total_errors) + '\n')
2013 if __name__ == '__main__':