0671ac7f513f6387d7b21277068df6274cf57e4c
[third_party/pep8] / pep8.py
1 #!/usr/bin/env python
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>
5 #
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:
13 #
14 # The above copyright notice and this permission notice shall be
15 # included in all copies or substantial portions of the Software.
16 #
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
24 # SOFTWARE.
25
26 r"""
27 Check Python source code formatting, according to PEP 8.
28
29 For usage and a list of options, try this:
30 $ python pep8.py -h
31
32 This program and its regression test suite live here:
33 http://github.com/jcrocholl/pep8
34
35 Groups of errors and warnings:
36 E errors
37 W warnings
38 100 indentation
39 200 whitespace
40 300 blank lines
41 400 imports
42 500 line length
43 600 deprecation
44 700 statements
45 900 syntax error
46 """
47 from __future__ import with_statement
48
49 __version__ = '1.5.7a0'
50
51 import os
52 import sys
53 import re
54 import time
55 import inspect
56 import keyword
57 import tokenize
58 from optparse import OptionParser
59 from fnmatch import fnmatch
60 try:
61     from configparser import RawConfigParser
62     from io import TextIOWrapper
63 except ImportError:
64     from ConfigParser import RawConfigParser
65
66 DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__'
67 DEFAULT_IGNORE = 'E123,E226,E24'
68 if sys.platform == 'win32':
69     DEFAULT_CONFIG = os.path.expanduser(r'~\.pep8')
70 else:
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')
75 MAX_LINE_LENGTH = 79
76 REPORT_FORMAT = {
77     'default': '%(path)s:%(row)d:%(col)d: %(code)s %(text)s',
78     'pylint': '%(path)s:%(row)d: [%(code)s] %(text)s',
79 }
80
81 PyCF_ONLY_AST = 1024
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']
96
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+))? @@.*$')
112
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'
116
117
118 ##############################################################################
119 # Plugins (check functions) for physical lines
120 ##############################################################################
121
122
123 def tabs_or_spaces(physical_line, indent_char):
124     r"""Never mix tabs and spaces.
125
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!
132
133     Okay: if a == 0:\n        a = 1\n        b = 1
134     E101: if a == 0:\n        a = 1\n\tb = 1
135     """
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"
140
141
142 def tabs_obsolete(physical_line):
143     r"""For new projects, spaces-only are strongly recommended over tabs.
144
145     Okay: if True:\n    return
146     W191: if True:\n\treturn
147     """
148     indent = INDENT_REGEX.match(physical_line).group(1)
149     if '\t' in indent:
150         return indent.index('\t'), "W191 indentation contains tabs"
151
152
153 def trailing_whitespace(physical_line):
154     r"""Trailing whitespace is superfluous.
155
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.
158
159     Okay: spam(1)\n#
160     W291: spam(1) \n#
161     W293: class Foo(object):\n    \n    bang = 12
162     """
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:
168         if stripped:
169             return len(stripped), "W291 trailing whitespace"
170         else:
171             return 0, "W293 blank line contains whitespace"
172
173
174 def trailing_blank_lines(physical_line, lines, line_number, total_lines):
175     r"""Trailing blank lines are superfluous.
176
177     Okay: spam(1)
178     W391: spam(1)\n
179
180     However the last line should end with a new line (warning W292).
181     """
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"
188
189
190 def maximum_line_length(physical_line, max_line_length, multiline):
191     r"""Limit all lines to a maximum of 79 characters.
192
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.
199
200     Reports error E501.
201     """
202     line = physical_line.rstrip()
203     length = len(line)
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:
211             return
212         if hasattr(line, 'decode'):   # Python 2
213             # The line could contain multi-byte characters
214             try:
215                 length = len(line.decode('utf-8'))
216             except UnicodeError:
217                 pass
218         if length > max_line_length:
219             return (max_line_length, "E501 line too long "
220                     "(%d > %d characters)" % (length, max_line_length))
221
222
223 ##############################################################################
224 # Plugins (check functions) for logical lines
225 ##############################################################################
226
227
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.
231
232     Method definitions inside a class are separated by a single blank line.
233
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).
237
238     Use blank lines in functions, sparingly, to indicate logical sections.
239
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
242
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
248     """
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('@'):
252         if blank_lines:
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 ', '@')):
257         if indent_level:
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
263
264
265 def extraneous_whitespace(logical_line):
266     r"""Avoid extraneous whitespace.
267
268     Avoid extraneous whitespace in these situations:
269     - Immediately inside parentheses, brackets or braces.
270     - Immediately before a comma, semicolon, or colon.
271
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 })
279
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
283     """
284     line = logical_line
285     for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line):
286         text = match.group()
287         char = text.strip()
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)
295
296
297 def whitespace_around_keywords(logical_line):
298     r"""Avoid extraneous whitespace around keywords.
299
300     Okay: True and False
301     E271: True and  False
302     E272: True  and False
303     E273: True and\tFalse
304     E274: True\tand False
305     """
306     for match in KEYWORD_REGEX.finditer(logical_line):
307         before, after = match.groups()
308
309         if '\t' in before:
310             yield match.start(1), "E274 tab before keyword"
311         elif len(before) > 1:
312             yield match.start(1), "E272 multiple spaces before keyword"
313
314         if '\t' in after:
315             yield match.start(2), "E273 tab after keyword"
316         elif len(after) > 1:
317             yield match.start(2), "E271 multiple spaces after keyword"
318
319
320 def missing_whitespace(logical_line):
321     r"""Each comma, semicolon or colon should be followed by whitespace.
322
323     Okay: [a, b]
324     Okay: (3,)
325     Okay: a[1:4]
326     Okay: a[:4]
327     Okay: a[1:]
328     Okay: a[1:4:2]
329     E231: ['a','b']
330     E231: foo(bar,baz)
331     E231: [{'a':'b'}]
332     """
333     line = logical_line
334     for index in range(len(line) - 1):
335         char = line[index]
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
344
345
346 def indentation(logical_line, previous_logical, indent_char,
347                 indent_level, previous_indent_level):
348     r"""Use 4 spaces per indentation level.
349
350     For really old code that you don't want to mess up, you can continue to
351     use 8-space tabs.
352
353     Okay: a = 1
354     Okay: if a == 0:\n    a = 1
355     E111:   a = 1
356
357     Okay: for item in items:\n    pass
358     E112: for item in items:\npass
359
360     Okay: a = 1\nb = 2
361     E113: a = 1\n    b = 2
362     """
363     if indent_char == ' ' and indent_level % 4:
364         yield 0, "E111 indentation is not a multiple of four"
365     indent_expect = previous_logical.endswith(':')
366     if indent_expect and indent_level <= previous_indent_level:
367         yield 0, "E112 expected an indented block"
368     if indent_level > previous_indent_level and not indent_expect:
369         yield 0, "E113 unexpected indentation"
370
371
372 def continued_indentation(logical_line, tokens, indent_level, hang_closing,
373                           indent_char, noqa, verbose):
374     r"""Continuation lines indentation.
375
376     Continuation lines should align wrapped elements either vertically
377     using Python's implicit line joining inside parentheses, brackets
378     and braces, or using a hanging indent.
379
380     When using a hanging indent these considerations should be applied:
381     - there should be no arguments on the first line, and
382     - further indentation should be used to clearly distinguish itself as a
383       continuation line.
384
385     Okay: a = (\n)
386     E123: a = (\n    )
387
388     Okay: a = (\n    42)
389     E121: a = (\n   42)
390     E122: a = (\n42)
391     E123: a = (\n    42\n    )
392     E124: a = (24,\n     42\n)
393     E125: if (\n    b):\n    pass
394     E126: a = (\n        42)
395     E127: a = (24,\n      42)
396     E128: a = (24,\n    42)
397     E129: if (a or\n    b):\n    pass
398     E131: a = (\n    42\n 24)
399     """
400     first_row = tokens[0][2][0]
401     nrows = 1 + tokens[-1][2][0] - first_row
402     if noqa or nrows == 1:
403         return
404
405     # indent_next tells us whether the next block is indented; assuming
406     # that it is indented by 4 spaces, then we should not allow 4-space
407     # indents on the final continuation line; in turn, some other
408     # indents are allowed to have an extra 4 spaces.
409     indent_next = logical_line.endswith(':')
410
411     row = depth = 0
412     valid_hangs = (4,) if indent_char != '\t' else (4, 8)
413     # remember how many brackets were opened on each line
414     parens = [0] * nrows
415     # relative indents of physical lines
416     rel_indent = [0] * nrows
417     # for each depth, collect a list of opening rows
418     open_rows = [[0]]
419     # for each depth, memorize the hanging indentation
420     hangs = [None]
421     # visual indents
422     indent_chances = {}
423     last_indent = tokens[0][2]
424     visual_indent = None
425     # for each depth, memorize the visual indent column
426     indent = [last_indent[1]]
427     if verbose >= 3:
428         print(">>> " + tokens[0][4].rstrip())
429
430     for token_type, text, start, end, line in tokens:
431
432         newline = row < start[0] - first_row
433         if newline:
434             row = start[0] - first_row
435             newline = not last_token_multiline and token_type not in NEWLINE
436
437         if newline:
438             # this is the beginning of a continuation line.
439             last_indent = start
440             if verbose >= 3:
441                 print("... " + line.rstrip())
442
443             # record the initial indent.
444             rel_indent[row] = expand_indent(line) - indent_level
445
446             # identify closing bracket
447             close_bracket = (token_type == tokenize.OP and text in ']})')
448
449             # is the indent relative to an opening bracket line?
450             for open_row in reversed(open_rows[depth]):
451                 hang = rel_indent[row] - rel_indent[open_row]
452                 hanging_indent = hang in valid_hangs
453                 if hanging_indent:
454                     break
455             if hangs[depth]:
456                 hanging_indent = (hang == hangs[depth])
457             # is there any chance of visual indent?
458             visual_indent = (not close_bracket and hang > 0 and
459                              indent_chances.get(start[1]))
460
461             if close_bracket and indent[depth]:
462                 # closing bracket for visual indent
463                 if start[1] != indent[depth]:
464                     yield (start, "E124 closing bracket does not match "
465                            "visual indentation")
466             elif close_bracket and not hang:
467                 # closing bracket matches indentation of opening bracket's line
468                 if hang_closing:
469                     yield start, "E133 closing bracket is missing indentation"
470             elif indent[depth] and start[1] < indent[depth]:
471                 if visual_indent is not True:
472                     # visual indent is broken
473                     yield (start, "E128 continuation line "
474                            "under-indented for visual indent")
475             elif hanging_indent or (indent_next and rel_indent[row] == 8):
476                 # hanging indent is verified
477                 if close_bracket and not hang_closing:
478                     yield (start, "E123 closing bracket does not match "
479                            "indentation of opening bracket's line")
480                 hangs[depth] = hang
481             elif visual_indent is True:
482                 # visual indent is verified
483                 indent[depth] = start[1]
484             elif visual_indent in (text, str):
485                 # ignore token lined up with matching one from a previous line
486                 pass
487             else:
488                 # indent is broken
489                 if hang <= 0:
490                     error = "E122", "missing indentation or outdented"
491                 elif indent[depth]:
492                     error = "E127", "over-indented for visual indent"
493                 elif not close_bracket and hangs[depth]:
494                     error = "E131", "unaligned for hanging indent"
495                 else:
496                     hangs[depth] = hang
497                     if hang > 4:
498                         error = "E126", "over-indented for hanging indent"
499                     else:
500                         error = "E121", "under-indented for hanging indent"
501                 yield start, "%s continuation line %s" % error
502
503         # look for visual indenting
504         if (parens[row] and token_type not in (tokenize.NL, tokenize.COMMENT)
505                 and not indent[depth]):
506             indent[depth] = start[1]
507             indent_chances[start[1]] = True
508             if verbose >= 4:
509                 print("bracket depth %s indent to %s" % (depth, start[1]))
510         # deal with implicit string concatenation
511         elif (token_type in (tokenize.STRING, tokenize.COMMENT) or
512               text in ('u', 'ur', 'b', 'br')):
513             indent_chances[start[1]] = str
514         # special case for the "if" statement because len("if (") == 4
515         elif not indent_chances and not row and not depth and text == 'if':
516             indent_chances[end[1] + 1] = True
517         elif text == ':' and line[end[1]:].isspace():
518             open_rows[depth].append(row)
519
520         # keep track of bracket depth
521         if token_type == tokenize.OP:
522             if text in '([{':
523                 depth += 1
524                 indent.append(0)
525                 hangs.append(None)
526                 if len(open_rows) == depth:
527                     open_rows.append([])
528                 open_rows[depth].append(row)
529                 parens[row] += 1
530                 if verbose >= 4:
531                     print("bracket depth %s seen, col %s, visual min = %s" %
532                           (depth, start[1], indent[depth]))
533             elif text in ')]}' and depth > 0:
534                 # parent indents should not be more than this one
535                 prev_indent = indent.pop() or last_indent[1]
536                 hangs.pop()
537                 for d in range(depth):
538                     if indent[d] > prev_indent:
539                         indent[d] = 0
540                 for ind in list(indent_chances):
541                     if ind >= prev_indent:
542                         del indent_chances[ind]
543                 del open_rows[depth + 1:]
544                 depth -= 1
545                 if depth:
546                     indent_chances[indent[depth]] = True
547                 for idx in range(row, -1, -1):
548                     if parens[idx]:
549                         parens[idx] -= 1
550                         break
551             assert len(indent) == depth + 1
552             if start[1] not in indent_chances:
553                 # allow to line up tokens
554                 indent_chances[start[1]] = text
555
556         last_token_multiline = (start[0] != end[0])
557         if last_token_multiline:
558             rel_indent[end[0] - first_row] = rel_indent[row]
559
560     if indent_next and expand_indent(line) == indent_level + 4:
561         pos = (start[0], indent[0] + 4)
562         if visual_indent:
563             code = "E129 visually indented line"
564         else:
565             code = "E125 continuation line"
566         yield pos, "%s with same indent as next logical line" % code
567
568
569 def whitespace_before_parameters(logical_line, tokens):
570     r"""Avoid extraneous whitespace.
571
572     Avoid extraneous whitespace in the following situations:
573     - before the open parenthesis that starts the argument list of a
574       function call.
575     - before the open parenthesis that starts an indexing or slicing.
576
577     Okay: spam(1)
578     E211: spam (1)
579
580     Okay: dict['key'] = list[index]
581     E211: dict ['key'] = list[index]
582     E211: dict['key'] = list [index]
583     """
584     prev_type, prev_text, __, prev_end, __ = tokens[0]
585     for index in range(1, len(tokens)):
586         token_type, text, start, end, __ = tokens[index]
587         if (token_type == tokenize.OP and
588             text in '([' and
589             start != prev_end and
590             (prev_type == tokenize.NAME or prev_text in '}])') and
591             # Syntax "class A (B):" is allowed, but avoid it
592             (index < 2 or tokens[index - 2][1] != 'class') and
593                 # Allow "return (a.foo for a in range(5))"
594                 not keyword.iskeyword(prev_text)):
595             yield prev_end, "E211 whitespace before '%s'" % text
596         prev_type = token_type
597         prev_text = text
598         prev_end = end
599
600
601 def whitespace_around_operator(logical_line):
602     r"""Avoid extraneous whitespace around an operator.
603
604     Okay: a = 12 + 3
605     E221: a = 4  + 5
606     E222: a = 4 +  5
607     E223: a = 4\t+ 5
608     E224: a = 4 +\t5
609     """
610     for match in OPERATOR_REGEX.finditer(logical_line):
611         before, after = match.groups()
612
613         if '\t' in before:
614             yield match.start(1), "E223 tab before operator"
615         elif len(before) > 1:
616             yield match.start(1), "E221 multiple spaces before operator"
617
618         if '\t' in after:
619             yield match.start(2), "E224 tab after operator"
620         elif len(after) > 1:
621             yield match.start(2), "E222 multiple spaces after operator"
622
623
624 def missing_whitespace_around_operator(logical_line, tokens):
625     r"""Surround operators with a single space on either side.
626
627     - Always surround these binary operators with a single space on
628       either side: assignment (=), augmented assignment (+=, -= etc.),
629       comparisons (==, <, >, !=, <=, >=, in, not in, is, is not),
630       Booleans (and, or, not).
631
632     - If operators with different priorities are used, consider adding
633       whitespace around the operators with the lowest priorities.
634
635     Okay: i = i + 1
636     Okay: submitted += 1
637     Okay: x = x * 2 - 1
638     Okay: hypot2 = x * x + y * y
639     Okay: c = (a + b) * (a - b)
640     Okay: foo(bar, key='word', *args, **kwargs)
641     Okay: alpha[:-i]
642
643     E225: i=i+1
644     E225: submitted +=1
645     E225: x = x /2 - 1
646     E225: z = x **y
647     E226: c = (a+b) * (a-b)
648     E226: hypot2 = x*x + y*y
649     E227: c = a|b
650     E228: msg = fmt%(errno, errmsg)
651     """
652     parens = 0
653     need_space = False
654     prev_type = tokenize.OP
655     prev_text = prev_end = None
656     for token_type, text, start, end, line in tokens:
657         if token_type in SKIP_COMMENTS:
658             continue
659         if text in ('(', 'lambda'):
660             parens += 1
661         elif text == ')':
662             parens -= 1
663         if need_space:
664             if start != prev_end:
665                 # Found a (probably) needed space
666                 if need_space is not True and not need_space[1]:
667                     yield (need_space[0],
668                            "E225 missing whitespace around operator")
669                 need_space = False
670             elif text == '>' and prev_text in ('<', '-'):
671                 # Tolerate the "<>" operator, even if running Python 3
672                 # Deal with Python 3's annotated return value "->"
673                 pass
674             else:
675                 if need_space is True or need_space[1]:
676                     # A needed trailing space was not found
677                     yield prev_end, "E225 missing whitespace around operator"
678                 else:
679                     code, optype = 'E226', 'arithmetic'
680                     if prev_text == '%':
681                         code, optype = 'E228', 'modulo'
682                     elif prev_text not in ARITHMETIC_OP:
683                         code, optype = 'E227', 'bitwise or shift'
684                     yield (need_space[0], "%s missing whitespace "
685                            "around %s operator" % (code, optype))
686                 need_space = False
687         elif token_type == tokenize.OP and prev_end is not None:
688             if text == '=' and parens:
689                 # Allow keyword args or defaults: foo(bar=None).
690                 pass
691             elif text in WS_NEEDED_OPERATORS:
692                 need_space = True
693             elif text in UNARY_OPERATORS:
694                 # Check if the operator is being used as a binary operator
695                 # Allow unary operators: -123, -x, +1.
696                 # Allow argument unpacking: foo(*args, **kwargs).
697                 if (prev_text in '}])' if prev_type == tokenize.OP
698                         else prev_text not in KEYWORDS):
699                     need_space = None
700             elif text in WS_OPTIONAL_OPERATORS:
701                 need_space = None
702
703             if need_space is None:
704                 # Surrounding space is optional, but ensure that
705                 # trailing space matches opening space
706                 need_space = (prev_end, start != prev_end)
707             elif need_space and start == prev_end:
708                 # A needed opening space was not found
709                 yield prev_end, "E225 missing whitespace around operator"
710                 need_space = False
711         prev_type = token_type
712         prev_text = text
713         prev_end = end
714
715
716 def whitespace_around_comma(logical_line):
717     r"""Avoid extraneous whitespace after a comma or a colon.
718
719     Note: these checks are disabled by default
720
721     Okay: a = (1, 2)
722     E241: a = (1,  2)
723     E242: a = (1,\t2)
724     """
725     line = logical_line
726     for m in WHITESPACE_AFTER_COMMA_REGEX.finditer(line):
727         found = m.start() + 1
728         if '\t' in m.group():
729             yield found, "E242 tab after '%s'" % m.group()[0]
730         else:
731             yield found, "E241 multiple spaces after '%s'" % m.group()[0]
732
733
734 def whitespace_around_named_parameter_equals(logical_line, tokens):
735     r"""Don't use spaces around the '=' sign in function arguments.
736
737     Don't use spaces around the '=' sign when used to indicate a
738     keyword argument or a default parameter value.
739
740     Okay: def complex(real, imag=0.0):
741     Okay: return magic(r=real, i=imag)
742     Okay: boolean(a == b)
743     Okay: boolean(a != b)
744     Okay: boolean(a <= b)
745     Okay: boolean(a >= b)
746
747     E251: def complex(real, imag = 0.0):
748     E251: return magic(r = real, i = imag)
749     """
750     parens = 0
751     no_space = False
752     prev_end = None
753     message = "E251 unexpected spaces around keyword / parameter equals"
754     for token_type, text, start, end, line in tokens:
755         if token_type == tokenize.NL:
756             continue
757         if no_space:
758             no_space = False
759             if start != prev_end:
760                 yield (prev_end, message)
761         elif token_type == tokenize.OP:
762             if text == '(':
763                 parens += 1
764             elif text == ')':
765                 parens -= 1
766             elif parens and text == '=':
767                 no_space = True
768                 if start != prev_end:
769                     yield (prev_end, message)
770         prev_end = end
771
772
773 def whitespace_before_comment(logical_line, tokens):
774     r"""Separate inline comments by at least two spaces.
775
776     An inline comment is a comment on the same line as a statement.  Inline
777     comments should be separated by at least two spaces from the statement.
778     They should start with a # and a single space.
779
780     Each line of a block comment starts with a # and a single space
781     (unless it is indented text inside the comment).
782
783     Okay: x = x + 1  # Increment x
784     Okay: x = x + 1    # Increment x
785     Okay: # Block comment
786     E261: x = x + 1 # Increment x
787     E262: x = x + 1  #Increment x
788     E262: x = x + 1  #  Increment x
789     E265: #Block comment
790     """
791     prev_end = (0, 0)
792     for token_type, text, start, end, line in tokens:
793         if token_type == tokenize.COMMENT:
794             inline_comment = line[:start[1]].strip()
795             if inline_comment:
796                 if prev_end[0] == start[0] and start[1] < prev_end[1] + 2:
797                     yield (prev_end,
798                            "E261 at least two spaces before inline comment")
799             symbol, sp, comment = text.partition(' ')
800             bad_prefix = symbol not in ('#', '#:')
801             if inline_comment:
802                 if bad_prefix or comment[:1].isspace():
803                     yield start, "E262 inline comment should start with '# '"
804             elif bad_prefix:
805                 if text.rstrip('#') and (start[0] > 1 or symbol[1] != '!'):
806                     yield start, "E265 block comment should start with '# '"
807         elif token_type != tokenize.NL:
808             prev_end = end
809
810
811 def imports_on_separate_lines(logical_line):
812     r"""Imports should usually be on separate lines.
813
814     Okay: import os\nimport sys
815     E401: import sys, os
816
817     Okay: from subprocess import Popen, PIPE
818     Okay: from myclas import MyClass
819     Okay: from foo.bar.yourclass import YourClass
820     Okay: import myclass
821     Okay: import foo.bar.yourclass
822     """
823     line = logical_line
824     if line.startswith('import '):
825         found = line.find(',')
826         if -1 < found and ';' not in line[:found]:
827             yield found, "E401 multiple imports on one line"
828
829
830 def compound_statements(logical_line):
831     r"""Compound statements (on the same line) are generally discouraged.
832
833     While sometimes it's okay to put an if/for/while with a small body
834     on the same line, never do this for multi-clause statements.
835     Also avoid folding such long lines!
836
837     Okay: if foo == 'blah':\n    do_blah_thing()
838     Okay: do_one()
839     Okay: do_two()
840     Okay: do_three()
841
842     E701: if foo == 'blah': do_blah_thing()
843     E701: for x in lst: total += x
844     E701: while t < 10: t = delay()
845     E701: if foo == 'blah': do_blah_thing()
846     E701: else: do_non_blah_thing()
847     E701: try: something()
848     E701: finally: cleanup()
849     E701: if foo == 'blah': one(); two(); three()
850
851     E702: do_one(); do_two(); do_three()
852     E703: do_four();  # useless semicolon
853     """
854     line = logical_line
855     last_char = len(line) - 1
856     found = line.find(':')
857     while -1 < found < last_char:
858         before = line[:found]
859         if (before.count('{') <= before.count('}') and  # {'a': 1} (dict)
860             before.count('[') <= before.count(']') and  # [1:2] (slice)
861             before.count('(') <= before.count(')') and  # (Python 3 annotation)
862                 not LAMBDA_REGEX.search(before)):       # lambda x: x
863             yield found, "E701 multiple statements on one line (colon)"
864         found = line.find(':', found + 1)
865     found = line.find(';')
866     while -1 < found:
867         if found < last_char:
868             yield found, "E702 multiple statements on one line (semicolon)"
869         else:
870             yield found, "E703 statement ends with a semicolon"
871         found = line.find(';', found + 1)
872
873
874 def explicit_line_join(logical_line, tokens):
875     r"""Avoid explicit line join between brackets.
876
877     The preferred way of wrapping long lines is by using Python's implied line
878     continuation inside parentheses, brackets and braces.  Long lines can be
879     broken over multiple lines by wrapping expressions in parentheses.  These
880     should be used in preference to using a backslash for line continuation.
881
882     E502: aaa = [123, \\n       123]
883     E502: aaa = ("bbb " \\n       "ccc")
884
885     Okay: aaa = [123,\n       123]
886     Okay: aaa = ("bbb "\n       "ccc")
887     Okay: aaa = "bbb " \\n    "ccc"
888     """
889     prev_start = prev_end = parens = 0
890     for token_type, text, start, end, line in tokens:
891         if start[0] != prev_start and parens and backslash:
892             yield backslash, "E502 the backslash is redundant between brackets"
893         if end[0] != prev_end:
894             if line.rstrip('\r\n').endswith('\\'):
895                 backslash = (end[0], len(line.splitlines()[-1]) - 1)
896             else:
897                 backslash = None
898             prev_start = prev_end = end[0]
899         else:
900             prev_start = start[0]
901         if token_type == tokenize.OP:
902             if text in '([{':
903                 parens += 1
904             elif text in ')]}':
905                 parens -= 1
906
907
908 def comparison_to_singleton(logical_line, noqa):
909     r"""Comparison to singletons should use "is" or "is not".
910
911     Comparisons to singletons like None should always be done
912     with "is" or "is not", never the equality operators.
913
914     Okay: if arg is not None:
915     E711: if arg != None:
916     E712: if arg == True:
917
918     Also, beware of writing if x when you really mean if x is not None --
919     e.g. when testing whether a variable or argument that defaults to None was
920     set to some other value.  The other value might have a type (such as a
921     container) that could be false in a boolean context!
922     """
923     match = not noqa and COMPARE_SINGLETON_REGEX.search(logical_line)
924     if match:
925         same = (match.group(1) == '==')
926         singleton = match.group(2)
927         msg = "'if cond is %s:'" % (('' if same else 'not ') + singleton)
928         if singleton in ('None',):
929             code = 'E711'
930         else:
931             code = 'E712'
932             nonzero = ((singleton == 'True' and same) or
933                        (singleton == 'False' and not same))
934             msg += " or 'if %scond:'" % ('' if nonzero else 'not ')
935         yield match.start(1), ("%s comparison to %s should be %s" %
936                                (code, singleton, msg))
937
938
939 def comparison_negative(logical_line):
940     r"""Negative comparison should be done using "not in" and "is not".
941
942     Okay: if x not in y:\n    pass
943     Okay: assert (X in Y or X is Z)
944     Okay: if not (X in Y):\n    pass
945     Okay: zz = x is not y
946     E713: Z = not X in Y
947     E713: if not X.B in Y:\n    pass
948     E714: if not X is Y:\n    pass
949     E714: Z = not X.B is Y
950     """
951     match = COMPARE_NEGATIVE_REGEX.search(logical_line)
952     if match:
953         pos = match.start(1)
954         if match.group(2) == 'in':
955             yield pos, "E713 test for membership should be 'not in'"
956         else:
957             yield pos, "E714 test for object identity should be 'is not'"
958
959
960 def comparison_type(logical_line):
961     r"""Object type comparisons should always use isinstance().
962
963     Do not compare types directly.
964
965     Okay: if isinstance(obj, int):
966     E721: if type(obj) is type(1):
967
968     When checking if an object is a string, keep in mind that it might be a
969     unicode string too! In Python 2.3, str and unicode have a common base
970     class, basestring, so you can do:
971
972     Okay: if isinstance(obj, basestring):
973     Okay: if type(a1) is type(b1):
974     """
975     match = COMPARE_TYPE_REGEX.search(logical_line)
976     if match:
977         inst = match.group(1)
978         if inst and isidentifier(inst) and inst not in SINGLETONS:
979             return  # Allow comparison for types which are not obvious
980         yield match.start(), "E721 do not compare types, use 'isinstance()'"
981
982
983 def python_3000_has_key(logical_line, noqa):
984     r"""The {}.has_key() method is removed in Python 3: use the 'in' operator.
985
986     Okay: if "alph" in d:\n    print d["alph"]
987     W601: assert d.has_key('alph')
988     """
989     pos = logical_line.find('.has_key(')
990     if pos > -1 and not noqa:
991         yield pos, "W601 .has_key() is deprecated, use 'in'"
992
993
994 def python_3000_raise_comma(logical_line):
995     r"""When raising an exception, use "raise ValueError('message')".
996
997     The older form is removed in Python 3.
998
999     Okay: raise DummyError("Message")
1000     W602: raise DummyError, "Message"
1001     """
1002     match = RAISE_COMMA_REGEX.match(logical_line)
1003     if match and not RERAISE_COMMA_REGEX.match(logical_line):
1004         yield match.end() - 1, "W602 deprecated form of raising exception"
1005
1006
1007 def python_3000_not_equal(logical_line):
1008     r"""New code should always use != instead of <>.
1009
1010     The older syntax is removed in Python 3.
1011
1012     Okay: if a != 'no':
1013     W603: if a <> 'no':
1014     """
1015     pos = logical_line.find('<>')
1016     if pos > -1:
1017         yield pos, "W603 '<>' is deprecated, use '!='"
1018
1019
1020 def python_3000_backticks(logical_line):
1021     r"""Backticks are removed in Python 3: use repr() instead.
1022
1023     Okay: val = repr(1 + 2)
1024     W604: val = `1 + 2`
1025     """
1026     pos = logical_line.find('`')
1027     if pos > -1:
1028         yield pos, "W604 backticks are deprecated, use 'repr()'"
1029
1030
1031 ##############################################################################
1032 # Helper functions
1033 ##############################################################################
1034
1035
1036 if '' == ''.encode():
1037     # Python 2: implicit encoding.
1038     def readlines(filename):
1039         """Read the source code."""
1040         with open(filename) as f:
1041             return f.readlines()
1042     isidentifier = re.compile(r'[a-zA-Z_]\w*').match
1043     stdin_get_value = sys.stdin.read
1044 else:
1045     # Python 3
1046     def readlines(filename):
1047         """Read the source code."""
1048         try:
1049             with open(filename, 'rb') as f:
1050                 (coding, lines) = tokenize.detect_encoding(f.readline)
1051                 f = TextIOWrapper(f, coding, line_buffering=True)
1052                 return [l.decode(coding) for l in lines] + f.readlines()
1053         except (LookupError, SyntaxError, UnicodeError):
1054             # Fall back if file encoding is improperly declared
1055             with open(filename, encoding='latin-1') as f:
1056                 return f.readlines()
1057     isidentifier = str.isidentifier
1058
1059     def stdin_get_value():
1060         return TextIOWrapper(sys.stdin.buffer, errors='ignore').read()
1061 noqa = re.compile(r'# no(?:qa|pep8)\b', re.I).search
1062
1063
1064 def expand_indent(line):
1065     r"""Return the amount of indentation.
1066
1067     Tabs are expanded to the next multiple of 8.
1068
1069     >>> expand_indent('    ')
1070     4
1071     >>> expand_indent('\t')
1072     8
1073     >>> expand_indent('       \t')
1074     8
1075     >>> expand_indent('        \t')
1076     16
1077     """
1078     if '\t' not in line:
1079         return len(line) - len(line.lstrip())
1080     result = 0
1081     for char in line:
1082         if char == '\t':
1083             result = result // 8 * 8 + 8
1084         elif char == ' ':
1085             result += 1
1086         else:
1087             break
1088     return result
1089
1090
1091 def mute_string(text):
1092     """Replace contents with 'xxx' to prevent syntax matching.
1093
1094     >>> mute_string('"abc"')
1095     '"xxx"'
1096     >>> mute_string("'''abc'''")
1097     "'''xxx'''"
1098     >>> mute_string("r'abc'")
1099     "r'xxx'"
1100     """
1101     # String modifiers (e.g. u or r)
1102     start = text.index(text[-1]) + 1
1103     end = len(text) - 1
1104     # Triple quotes
1105     if text[-3:] in ('"""', "'''"):
1106         start += 2
1107         end -= 2
1108     return text[:start] + 'x' * (end - start) + text[end:]
1109
1110
1111 def parse_udiff(diff, patterns=None, parent='.'):
1112     """Return a dictionary of matching lines."""
1113     # For each file of the diff, the entry key is the filename,
1114     # and the value is a set of row numbers to consider.
1115     rv = {}
1116     path = nrows = None
1117     for line in diff.splitlines():
1118         if nrows:
1119             if line[:1] != '-':
1120                 nrows -= 1
1121             continue
1122         if line[:3] == '@@ ':
1123             hunk_match = HUNK_REGEX.match(line)
1124             (row, nrows) = [int(g or '1') for g in hunk_match.groups()]
1125             rv[path].update(range(row, row + nrows))
1126         elif line[:3] == '+++':
1127             path = line[4:].split('\t', 1)[0]
1128             if path[:2] == 'b/':
1129                 path = path[2:]
1130             rv[path] = set()
1131     return dict([(os.path.join(parent, path), rows)
1132                  for (path, rows) in rv.items()
1133                  if rows and filename_match(path, patterns)])
1134
1135
1136 def normalize_paths(value, parent=os.curdir):
1137     """Parse a comma-separated list of paths.
1138
1139     Return a list of absolute paths.
1140     """
1141     if not value or isinstance(value, list):
1142         return value
1143     paths = []
1144     for path in value.split(','):
1145         if '/' in path:
1146             path = os.path.abspath(os.path.join(parent, path))
1147         paths.append(path.rstrip('/'))
1148     return paths
1149
1150
1151 def filename_match(filename, patterns, default=True):
1152     """Check if patterns contains a pattern that matches filename.
1153
1154     If patterns is unspecified, this always returns True.
1155     """
1156     if not patterns:
1157         return default
1158     return any(fnmatch(filename, pattern) for pattern in patterns)
1159
1160
1161 if COMMENT_WITH_NL:
1162     def _is_eol_token(token):
1163         return (token[0] in NEWLINE or
1164                 (token[0] == tokenize.COMMENT and token[1] == token[4]))
1165 else:
1166     def _is_eol_token(token):
1167         return token[0] in NEWLINE
1168
1169
1170 ##############################################################################
1171 # Framework to run all checks
1172 ##############################################################################
1173
1174
1175 _checks = {'physical_line': {}, 'logical_line': {}, 'tree': {}}
1176
1177
1178 def register_check(check, codes=None):
1179     """Register a new check object."""
1180     def _add_check(check, kind, codes, args):
1181         if check in _checks[kind]:
1182             _checks[kind][check][0].extend(codes or [])
1183         else:
1184             _checks[kind][check] = (codes or [''], args)
1185     if inspect.isfunction(check):
1186         args = inspect.getargspec(check)[0]
1187         if args and args[0] in ('physical_line', 'logical_line'):
1188             if codes is None:
1189                 codes = ERRORCODE_REGEX.findall(check.__doc__ or '')
1190             _add_check(check, args[0], codes, args)
1191     elif inspect.isclass(check):
1192         if inspect.getargspec(check.__init__)[0][:2] == ['self', 'tree']:
1193             _add_check(check, 'tree', codes, None)
1194
1195
1196 def init_checks_registry():
1197     """Register all globally visible functions.
1198
1199     The first argument name is either 'physical_line' or 'logical_line'.
1200     """
1201     mod = inspect.getmodule(register_check)
1202     for (name, function) in inspect.getmembers(mod, inspect.isfunction):
1203         register_check(function)
1204 init_checks_registry()
1205
1206
1207 class Checker(object):
1208     """Load a Python source file, tokenize it, check coding style."""
1209
1210     def __init__(self, filename=None, lines=None,
1211                  options=None, report=None, **kwargs):
1212         if options is None:
1213             options = StyleGuide(kwargs).options
1214         else:
1215             assert not kwargs
1216         self._io_error = None
1217         self._physical_checks = options.physical_checks
1218         self._logical_checks = options.logical_checks
1219         self._ast_checks = options.ast_checks
1220         self.max_line_length = options.max_line_length
1221         self.multiline = False  # in a multiline string?
1222         self.hang_closing = options.hang_closing
1223         self.verbose = options.verbose
1224         self.filename = filename
1225         if filename is None:
1226             self.filename = 'stdin'
1227             self.lines = lines or []
1228         elif filename == '-':
1229             self.filename = 'stdin'
1230             self.lines = stdin_get_value().splitlines(True)
1231         elif lines is None:
1232             try:
1233                 self.lines = readlines(filename)
1234             except IOError:
1235                 (exc_type, exc) = sys.exc_info()[:2]
1236                 self._io_error = '%s: %s' % (exc_type.__name__, exc)
1237                 self.lines = []
1238         else:
1239             self.lines = lines
1240         if self.lines:
1241             ord0 = ord(self.lines[0][0])
1242             if ord0 in (0xef, 0xfeff):  # Strip the UTF-8 BOM
1243                 if ord0 == 0xfeff:
1244                     self.lines[0] = self.lines[0][1:]
1245                 elif self.lines[0][:3] == '\xef\xbb\xbf':
1246                     self.lines[0] = self.lines[0][3:]
1247         self.report = report or options.report
1248         self.report_error = self.report.error
1249
1250     def report_invalid_syntax(self):
1251         """Check if the syntax is valid."""
1252         (exc_type, exc) = sys.exc_info()[:2]
1253         if len(exc.args) > 1:
1254             offset = exc.args[1]
1255             if len(offset) > 2:
1256                 offset = offset[1:3]
1257         else:
1258             offset = (1, 0)
1259         self.report_error(offset[0], offset[1] or 0,
1260                           'E901 %s: %s' % (exc_type.__name__, exc.args[0]),
1261                           self.report_invalid_syntax)
1262
1263     def readline(self):
1264         """Get the next line from the input buffer."""
1265         if self.line_number >= self.total_lines:
1266             return ''
1267         line = self.lines[self.line_number]
1268         self.line_number += 1
1269         if self.indent_char is None and line[:1] in WHITESPACE:
1270             self.indent_char = line[0]
1271         return line
1272
1273     def run_check(self, check, argument_names):
1274         """Run a check plugin."""
1275         arguments = []
1276         for name in argument_names:
1277             arguments.append(getattr(self, name))
1278         return check(*arguments)
1279
1280     def check_physical(self, line):
1281         """Run all physical checks on a raw input line."""
1282         self.physical_line = line
1283         for name, check, argument_names in self._physical_checks:
1284             result = self.run_check(check, argument_names)
1285             if result is not None:
1286                 (offset, text) = result
1287                 self.report_error(self.line_number, offset, text, check)
1288                 if text[:4] == 'E101':
1289                     self.indent_char = line[0]
1290
1291     def build_tokens_line(self):
1292         """Build a logical line from tokens."""
1293         logical = []
1294         comments = []
1295         length = 0
1296         prev_row = prev_col = mapping = None
1297         for token_type, text, start, end, line in self.tokens:
1298             if token_type in SKIP_TOKENS:
1299                 continue
1300             if not mapping:
1301                 mapping = [(0, start)]
1302             if token_type == tokenize.COMMENT:
1303                 comments.append(text)
1304                 continue
1305             if token_type == tokenize.STRING:
1306                 text = mute_string(text)
1307             if prev_row:
1308                 (start_row, start_col) = start
1309                 if prev_row != start_row:    # different row
1310                     prev_text = self.lines[prev_row - 1][prev_col - 1]
1311                     if prev_text == ',' or (prev_text not in '{[('
1312                                             and text not in '}])'):
1313                         text = ' ' + text
1314                 elif prev_col != start_col:  # different column
1315                     text = line[prev_col:start_col] + text
1316             logical.append(text)
1317             length += len(text)
1318             mapping.append((length, end))
1319             (prev_row, prev_col) = end
1320         self.logical_line = ''.join(logical)
1321         self.noqa = comments and noqa(''.join(comments))
1322         return mapping
1323
1324     def check_logical(self):
1325         """Build a line from tokens and run all logical checks on it."""
1326         self.report.increment_logical_line()
1327         mapping = self.build_tokens_line()
1328         (start_row, start_col) = mapping[0][1]
1329         start_line = self.lines[start_row - 1]
1330         self.indent_level = expand_indent(start_line[:start_col])
1331         if self.blank_before < self.blank_lines:
1332             self.blank_before = self.blank_lines
1333         if self.verbose >= 2:
1334             print(self.logical_line[:80].rstrip())
1335         for name, check, argument_names in self._logical_checks:
1336             if self.verbose >= 4:
1337                 print('   ' + name)
1338             for offset, text in self.run_check(check, argument_names) or ():
1339                 if not isinstance(offset, tuple):
1340                     for token_offset, pos in mapping:
1341                         if offset <= token_offset:
1342                             break
1343                     offset = (pos[0], pos[1] + offset - token_offset)
1344                 self.report_error(offset[0], offset[1], text, check)
1345         if self.logical_line:
1346             self.previous_indent_level = self.indent_level
1347             self.previous_logical = self.logical_line
1348         self.blank_lines = 0
1349         self.tokens = []
1350
1351     def check_ast(self):
1352         """Build the file's AST and run all AST checks."""
1353         try:
1354             tree = compile(''.join(self.lines), '', 'exec', PyCF_ONLY_AST)
1355         except (SyntaxError, TypeError):
1356             return self.report_invalid_syntax()
1357         for name, cls, __ in self._ast_checks:
1358             checker = cls(tree, self.filename)
1359             for lineno, offset, text, check in checker.run():
1360                 if not self.lines or not noqa(self.lines[lineno - 1]):
1361                     self.report_error(lineno, offset, text, check)
1362
1363     def generate_tokens(self):
1364         """Tokenize the file, run physical line checks and yield tokens."""
1365         if self._io_error:
1366             self.report_error(1, 0, 'E902 %s' % self._io_error, readlines)
1367         tokengen = tokenize.generate_tokens(self.readline)
1368         try:
1369             for token in tokengen:
1370                 self.maybe_check_physical(token)
1371                 yield token
1372         except (SyntaxError, tokenize.TokenError):
1373             self.report_invalid_syntax()
1374
1375     def maybe_check_physical(self, token):
1376         """If appropriate (based on token), check current physical line(s)."""
1377         # Called after every token, but act only on end of line.
1378         if _is_eol_token(token):
1379             # Obviously, a newline token ends a single physical line.
1380             self.check_physical(token[4])
1381         elif token[0] == tokenize.STRING and '\n' in token[1]:
1382             # Less obviously, a string that contains newlines is a
1383             # multiline string, either triple-quoted or with internal
1384             # newlines backslash-escaped. Check every physical line in the
1385             # string *except* for the last one: its newline is outside of
1386             # the multiline string, so we consider it a regular physical
1387             # line, and will check it like any other physical line.
1388             #
1389             # Subtleties:
1390             # - we don't *completely* ignore the last line; if it contains
1391             #   the magical "# noqa" comment, we disable all physical
1392             #   checks for the entire multiline string
1393             # - have to wind self.line_number back because initially it
1394             #   points to the last line of the string, and we want
1395             #   check_physical() to give accurate feedback
1396             if noqa(token[4]):
1397                 return
1398             self.multiline = True
1399             self.line_number = token[2][0]
1400             for line in token[1].split('\n')[:-1]:
1401                 self.check_physical(line + '\n')
1402                 self.line_number += 1
1403             self.multiline = False
1404
1405     def check_all(self, expected=None, line_offset=0):
1406         """Run all checks on the input file."""
1407         self.report.init_file(self.filename, self.lines, expected, line_offset)
1408         self.total_lines = len(self.lines)
1409         if self._ast_checks:
1410             self.check_ast()
1411         self.line_number = 0
1412         self.indent_char = None
1413         self.indent_level = self.previous_indent_level = 0
1414         self.previous_logical = ''
1415         self.tokens = []
1416         self.blank_lines = self.blank_before = 0
1417         parens = 0
1418         for token in self.generate_tokens():
1419             self.tokens.append(token)
1420             token_type, text = token[0:2]
1421             if self.verbose >= 3:
1422                 if token[2][0] == token[3][0]:
1423                     pos = '[%s:%s]' % (token[2][1] or '', token[3][1])
1424                 else:
1425                     pos = 'l.%s' % token[3][0]
1426                 print('l.%s\t%s\t%s\t%r' %
1427                       (token[2][0], pos, tokenize.tok_name[token[0]], text))
1428             if token_type == tokenize.OP:
1429                 if text in '([{':
1430                     parens += 1
1431                 elif text in '}])':
1432                     parens -= 1
1433             elif not parens:
1434                 if token_type in NEWLINE:
1435                     if token_type == tokenize.NEWLINE:
1436                         self.check_logical()
1437                         self.blank_before = 0
1438                     elif len(self.tokens) == 1:
1439                         # The physical line contains only this token.
1440                         self.blank_lines += 1
1441                         del self.tokens[0]
1442                     else:
1443                         self.check_logical()
1444                 elif COMMENT_WITH_NL and token_type == tokenize.COMMENT:
1445                     if len(self.tokens) == 1:
1446                         # The comment also ends a physical line
1447                         token = list(token)
1448                         token[1] = text.rstrip('\r\n')
1449                         token[3] = (token[2][0], token[2][1] + len(token[1]))
1450                         self.tokens = [tuple(token)]
1451                         self.check_logical()
1452         if len(self.tokens) > 1 and (token_type == tokenize.ENDMARKER and
1453                                      self.tokens[-2][0] not in SKIP_TOKENS):
1454             self.tokens.pop()
1455             self.check_physical(self.tokens[-1][4])
1456             self.check_logical()
1457         return self.report.get_file_results()
1458
1459
1460 class BaseReport(object):
1461     """Collect the results of the checks."""
1462
1463     print_filename = False
1464
1465     def __init__(self, options):
1466         self._benchmark_keys = options.benchmark_keys
1467         self._ignore_code = options.ignore_code
1468         # Results
1469         self.elapsed = 0
1470         self.total_errors = 0
1471         self.counters = dict.fromkeys(self._benchmark_keys, 0)
1472         self.messages = {}
1473
1474     def start(self):
1475         """Start the timer."""
1476         self._start_time = time.time()
1477
1478     def stop(self):
1479         """Stop the timer."""
1480         self.elapsed = time.time() - self._start_time
1481
1482     def init_file(self, filename, lines, expected, line_offset):
1483         """Signal a new file."""
1484         self.filename = filename
1485         self.lines = lines
1486         self.expected = expected or ()
1487         self.line_offset = line_offset
1488         self.file_errors = 0
1489         self.counters['files'] += 1
1490         self.counters['physical lines'] += len(lines)
1491
1492     def increment_logical_line(self):
1493         """Signal a new logical line."""
1494         self.counters['logical lines'] += 1
1495
1496     def error(self, line_number, offset, text, check):
1497         """Report an error, according to options."""
1498         code = text[:4]
1499         if self._ignore_code(code):
1500             return
1501         if code in self.counters:
1502             self.counters[code] += 1
1503         else:
1504             self.counters[code] = 1
1505             self.messages[code] = text[5:]
1506         # Don't care about expected errors or warnings
1507         if code in self.expected:
1508             return
1509         if self.print_filename and not self.file_errors:
1510             print(self.filename)
1511         self.file_errors += 1
1512         self.total_errors += 1
1513         return code
1514
1515     def get_file_results(self):
1516         """Return the count of errors and warnings for this file."""
1517         return self.file_errors
1518
1519     def get_count(self, prefix=''):
1520         """Return the total count of errors and warnings."""
1521         return sum([self.counters[key]
1522                     for key in self.messages if key.startswith(prefix)])
1523
1524     def get_statistics(self, prefix=''):
1525         """Get statistics for message codes that start with the prefix.
1526
1527         prefix='' matches all errors and warnings
1528         prefix='E' matches all errors
1529         prefix='W' matches all warnings
1530         prefix='E4' matches all errors that have to do with imports
1531         """
1532         return ['%-7s %s %s' % (self.counters[key], key, self.messages[key])
1533                 for key in sorted(self.messages) if key.startswith(prefix)]
1534
1535     def print_statistics(self, prefix=''):
1536         """Print overall statistics (number of errors and warnings)."""
1537         for line in self.get_statistics(prefix):
1538             print(line)
1539
1540     def print_benchmark(self):
1541         """Print benchmark numbers."""
1542         print('%-7.2f %s' % (self.elapsed, 'seconds elapsed'))
1543         if self.elapsed:
1544             for key in self._benchmark_keys:
1545                 print('%-7d %s per second (%d total)' %
1546                       (self.counters[key] / self.elapsed, key,
1547                        self.counters[key]))
1548
1549
1550 class FileReport(BaseReport):
1551     """Collect the results of the checks and print only the filenames."""
1552     print_filename = True
1553
1554
1555 class StandardReport(BaseReport):
1556     """Collect and print the results of the checks."""
1557
1558     def __init__(self, options):
1559         super(StandardReport, self).__init__(options)
1560         self._fmt = REPORT_FORMAT.get(options.format.lower(),
1561                                       options.format)
1562         self._repeat = options.repeat
1563         self._show_source = options.show_source
1564         self._show_pep8 = options.show_pep8
1565
1566     def init_file(self, filename, lines, expected, line_offset):
1567         """Signal a new file."""
1568         self._deferred_print = []
1569         return super(StandardReport, self).init_file(
1570             filename, lines, expected, line_offset)
1571
1572     def error(self, line_number, offset, text, check):
1573         """Report an error, according to options."""
1574         code = super(StandardReport, self).error(line_number, offset,
1575                                                  text, check)
1576         if code and (self.counters[code] == 1 or self._repeat):
1577             self._deferred_print.append(
1578                 (line_number, offset, code, text[5:], check.__doc__))
1579         return code
1580
1581     def get_file_results(self):
1582         """Print the result and return the overall count for this file."""
1583         self._deferred_print.sort()
1584         for line_number, offset, code, text, doc in self._deferred_print:
1585             print(self._fmt % {
1586                 'path': self.filename,
1587                 'row': self.line_offset + line_number, 'col': offset + 1,
1588                 'code': code, 'text': text,
1589             })
1590             if self._show_source:
1591                 if line_number > len(self.lines):
1592                     line = ''
1593                 else:
1594                     line = self.lines[line_number - 1]
1595                 print(line.rstrip())
1596                 print(re.sub(r'\S', ' ', line[:offset]) + '^')
1597             if self._show_pep8 and doc:
1598                 print('    ' + doc.strip())
1599         return self.file_errors
1600
1601
1602 class DiffReport(StandardReport):
1603     """Collect and print the results for the changed lines only."""
1604
1605     def __init__(self, options):
1606         super(DiffReport, self).__init__(options)
1607         self._selected = options.selected_lines
1608
1609     def error(self, line_number, offset, text, check):
1610         if line_number not in self._selected[self.filename]:
1611             return
1612         return super(DiffReport, self).error(line_number, offset, text, check)
1613
1614
1615 class StyleGuide(object):
1616     """Initialize a PEP-8 instance with few options."""
1617
1618     def __init__(self, *args, **kwargs):
1619         # build options from the command line
1620         self.checker_class = kwargs.pop('checker_class', Checker)
1621         parse_argv = kwargs.pop('parse_argv', False)
1622         config_file = kwargs.pop('config_file', None)
1623         parser = kwargs.pop('parser', None)
1624         # build options from dict
1625         options_dict = dict(*args, **kwargs)
1626         arglist = None if parse_argv else options_dict.get('paths', None)
1627         options, self.paths = process_options(
1628             arglist, parse_argv, config_file, parser)
1629         if options_dict:
1630             options.__dict__.update(options_dict)
1631             if 'paths' in options_dict:
1632                 self.paths = options_dict['paths']
1633
1634         self.runner = self.input_file
1635         self.options = options
1636
1637         if not options.reporter:
1638             options.reporter = BaseReport if options.quiet else StandardReport
1639
1640         options.select = tuple(options.select or ())
1641         if not (options.select or options.ignore or
1642                 options.testsuite or options.doctest) and DEFAULT_IGNORE:
1643             # The default choice: ignore controversial checks
1644             options.ignore = tuple(DEFAULT_IGNORE.split(','))
1645         else:
1646             # Ignore all checks which are not explicitly selected
1647             options.ignore = ('',) if options.select else tuple(options.ignore)
1648         options.benchmark_keys = BENCHMARK_KEYS[:]
1649         options.ignore_code = self.ignore_code
1650         options.physical_checks = self.get_checks('physical_line')
1651         options.logical_checks = self.get_checks('logical_line')
1652         options.ast_checks = self.get_checks('tree')
1653         self.init_report()
1654
1655     def init_report(self, reporter=None):
1656         """Initialize the report instance."""
1657         self.options.report = (reporter or self.options.reporter)(self.options)
1658         return self.options.report
1659
1660     def check_files(self, paths=None):
1661         """Run all checks on the paths."""
1662         if paths is None:
1663             paths = self.paths
1664         report = self.options.report
1665         runner = self.runner
1666         report.start()
1667         try:
1668             for path in paths:
1669                 if os.path.isdir(path):
1670                     self.input_dir(path)
1671                 elif not self.excluded(path):
1672                     runner(path)
1673         except KeyboardInterrupt:
1674             print('... stopped')
1675         report.stop()
1676         return report
1677
1678     def input_file(self, filename, lines=None, expected=None, line_offset=0):
1679         """Run all checks on a Python source file."""
1680         if self.options.verbose:
1681             print('checking %s' % filename)
1682         fchecker = self.checker_class(
1683             filename, lines=lines, options=self.options)
1684         return fchecker.check_all(expected=expected, line_offset=line_offset)
1685
1686     def input_dir(self, dirname):
1687         """Check all files in this directory and all subdirectories."""
1688         dirname = dirname.rstrip('/')
1689         if self.excluded(dirname):
1690             return 0
1691         counters = self.options.report.counters
1692         verbose = self.options.verbose
1693         filepatterns = self.options.filename
1694         runner = self.runner
1695         for root, dirs, files in os.walk(dirname):
1696             if verbose:
1697                 print('directory ' + root)
1698             counters['directories'] += 1
1699             for subdir in sorted(dirs):
1700                 if self.excluded(subdir, root):
1701                     dirs.remove(subdir)
1702             for filename in sorted(files):
1703                 # contain a pattern that matches?
1704                 if ((filename_match(filename, filepatterns) and
1705                      not self.excluded(filename, root))):
1706                     runner(os.path.join(root, filename))
1707
1708     def excluded(self, filename, parent=None):
1709         """Check if the file should be excluded.
1710
1711         Check if 'options.exclude' contains a pattern that matches filename.
1712         """
1713         if not self.options.exclude:
1714             return False
1715         basename = os.path.basename(filename)
1716         if filename_match(basename, self.options.exclude):
1717             return True
1718         if parent:
1719             filename = os.path.join(parent, filename)
1720         filename = os.path.abspath(filename)
1721         return filename_match(filename, self.options.exclude)
1722
1723     def ignore_code(self, code):
1724         """Check if the error code should be ignored.
1725
1726         If 'options.select' contains a prefix of the error code,
1727         return False.  Else, if 'options.ignore' contains a prefix of
1728         the error code, return True.
1729         """
1730         if len(code) < 4 and any(s.startswith(code)
1731                                  for s in self.options.select):
1732             return False
1733         return (code.startswith(self.options.ignore) and
1734                 not code.startswith(self.options.select))
1735
1736     def get_checks(self, argument_name):
1737         """Get all the checks for this category.
1738
1739         Find all globally visible functions where the first argument name
1740         starts with argument_name and which contain selected tests.
1741         """
1742         checks = []
1743         for check, attrs in _checks[argument_name].items():
1744             (codes, args) = attrs
1745             if any(not (code and self.ignore_code(code)) for code in codes):
1746                 checks.append((check.__name__, check, args))
1747         return sorted(checks)
1748
1749
1750 def get_parser(prog='pep8', version=__version__):
1751     parser = OptionParser(prog=prog, version=version,
1752                           usage="%prog [options] input ...")
1753     parser.config_options = [
1754         'exclude', 'filename', 'select', 'ignore', 'max-line-length',
1755         'hang-closing', 'count', 'format', 'quiet', 'show-pep8',
1756         'show-source', 'statistics', 'verbose']
1757     parser.add_option('-v', '--verbose', default=0, action='count',
1758                       help="print status messages, or debug with -vv")
1759     parser.add_option('-q', '--quiet', default=0, action='count',
1760                       help="report only file names, or nothing with -qq")
1761     parser.add_option('-r', '--repeat', default=True, action='store_true',
1762                       help="(obsolete) show all occurrences of the same error")
1763     parser.add_option('--first', action='store_false', dest='repeat',
1764                       help="show first occurrence of each error")
1765     parser.add_option('--exclude', metavar='patterns', default=DEFAULT_EXCLUDE,
1766                       help="exclude files or directories which match these "
1767                            "comma separated patterns (default: %default)")
1768     parser.add_option('--filename', metavar='patterns', default='*.py',
1769                       help="when parsing directories, only check filenames "
1770                            "matching these comma separated patterns "
1771                            "(default: %default)")
1772     parser.add_option('--select', metavar='errors', default='',
1773                       help="select errors and warnings (e.g. E,W6)")
1774     parser.add_option('--ignore', metavar='errors', default='',
1775                       help="skip errors and warnings (e.g. E4,W)")
1776     parser.add_option('--show-source', action='store_true',
1777                       help="show source code for each error")
1778     parser.add_option('--show-pep8', action='store_true',
1779                       help="show text of PEP 8 for each error "
1780                            "(implies --first)")
1781     parser.add_option('--statistics', action='store_true',
1782                       help="count errors and warnings")
1783     parser.add_option('--count', action='store_true',
1784                       help="print total number of errors and warnings "
1785                            "to standard error and set exit code to 1 if "
1786                            "total is not null")
1787     parser.add_option('--max-line-length', type='int', metavar='n',
1788                       default=MAX_LINE_LENGTH,
1789                       help="set maximum allowed line length "
1790                            "(default: %default)")
1791     parser.add_option('--hang-closing', action='store_true',
1792                       help="hang closing bracket instead of matching "
1793                            "indentation of opening bracket's line")
1794     parser.add_option('--format', metavar='format', default='default',
1795                       help="set the error format [default|pylint|<custom>]")
1796     parser.add_option('--diff', action='store_true',
1797                       help="report only lines changed according to the "
1798                            "unified diff received on STDIN")
1799     group = parser.add_option_group("Testing Options")
1800     if os.path.exists(TESTSUITE_PATH):
1801         group.add_option('--testsuite', metavar='dir',
1802                          help="run regression tests from dir")
1803         group.add_option('--doctest', action='store_true',
1804                          help="run doctest on myself")
1805     group.add_option('--benchmark', action='store_true',
1806                      help="measure processing speed")
1807     return parser
1808
1809
1810 def read_config(options, args, arglist, parser):
1811     """Read both user configuration and local configuration."""
1812     config = RawConfigParser()
1813
1814     user_conf = options.config
1815     if user_conf and os.path.isfile(user_conf):
1816         if options.verbose:
1817             print('user configuration: %s' % user_conf)
1818         config.read(user_conf)
1819
1820     local_dir = os.curdir
1821     parent = tail = args and os.path.abspath(os.path.commonprefix(args))
1822     while tail:
1823         if config.read([os.path.join(parent, fn) for fn in PROJECT_CONFIG]):
1824             local_dir = parent
1825             if options.verbose:
1826                 print('local configuration: in %s' % parent)
1827             break
1828         (parent, tail) = os.path.split(parent)
1829
1830     pep8_section = parser.prog
1831     if config.has_section(pep8_section):
1832         option_list = dict([(o.dest, o.type or o.action)
1833                             for o in parser.option_list])
1834
1835         # First, read the default values
1836         (new_options, __) = parser.parse_args([])
1837
1838         # Second, parse the configuration
1839         for opt in config.options(pep8_section):
1840             if options.verbose > 1:
1841                 print("  %s = %s" % (opt, config.get(pep8_section, opt)))
1842             if opt.replace('_', '-') not in parser.config_options:
1843                 print("Unknown option: '%s'\n  not in [%s]" %
1844                       (opt, ' '.join(parser.config_options)))
1845                 sys.exit(1)
1846             normalized_opt = opt.replace('-', '_')
1847             opt_type = option_list[normalized_opt]
1848             if opt_type in ('int', 'count'):
1849                 value = config.getint(pep8_section, opt)
1850             elif opt_type == 'string':
1851                 value = config.get(pep8_section, opt)
1852                 if normalized_opt == 'exclude':
1853                     value = normalize_paths(value, local_dir)
1854             else:
1855                 assert opt_type in ('store_true', 'store_false')
1856                 value = config.getboolean(pep8_section, opt)
1857             setattr(new_options, normalized_opt, value)
1858
1859         # Third, overwrite with the command-line options
1860         (options, __) = parser.parse_args(arglist, values=new_options)
1861     options.doctest = options.testsuite = False
1862     return options
1863
1864
1865 def process_options(arglist=None, parse_argv=False, config_file=None,
1866                     parser=None):
1867     """Process options passed either via arglist or via command line args."""
1868     if not parser:
1869         parser = get_parser()
1870     if not parser.has_option('--config'):
1871         if config_file is True:
1872             config_file = DEFAULT_CONFIG
1873         group = parser.add_option_group("Configuration", description=(
1874             "The project options are read from the [%s] section of the "
1875             "tox.ini file or the setup.cfg file located in any parent folder "
1876             "of the path(s) being processed.  Allowed options are: %s." %
1877             (parser.prog, ', '.join(parser.config_options))))
1878         group.add_option('--config', metavar='path', default=config_file,
1879                          help="user config file location (default: %default)")
1880     # Don't read the command line if the module is used as a library.
1881     if not arglist and not parse_argv:
1882         arglist = []
1883     # If parse_argv is True and arglist is None, arguments are
1884     # parsed from the command line (sys.argv)
1885     (options, args) = parser.parse_args(arglist)
1886     options.reporter = None
1887
1888     if options.ensure_value('testsuite', False):
1889         args.append(options.testsuite)
1890     elif not options.ensure_value('doctest', False):
1891         if parse_argv and not args:
1892             if options.diff or any(os.path.exists(name)
1893                                    for name in PROJECT_CONFIG):
1894                 args = ['.']
1895             else:
1896                 parser.error('input not specified')
1897         options = read_config(options, args, arglist, parser)
1898         options.reporter = parse_argv and options.quiet == 1 and FileReport
1899
1900     options.filename = options.filename and options.filename.split(',')
1901     options.exclude = normalize_paths(options.exclude)
1902     options.select = options.select and options.select.split(',')
1903     options.ignore = options.ignore and options.ignore.split(',')
1904
1905     if options.diff:
1906         options.reporter = DiffReport
1907         stdin = stdin_get_value()
1908         options.selected_lines = parse_udiff(stdin, options.filename, args[0])
1909         args = sorted(options.selected_lines)
1910
1911     return options, args
1912
1913
1914 def _main():
1915     """Parse options and run checks on Python source."""
1916     import signal
1917
1918     # Handle "Broken pipe" gracefully
1919     try:
1920         signal.signal(signal.SIGPIPE, lambda signum, frame: sys.exit(1))
1921     except AttributeError:
1922         pass    # not supported on Windows
1923
1924     pep8style = StyleGuide(parse_argv=True, config_file=True)
1925     options = pep8style.options
1926     if options.doctest or options.testsuite:
1927         from testsuite.support import run_tests
1928         report = run_tests(pep8style)
1929     else:
1930         report = pep8style.check_files()
1931     if options.statistics:
1932         report.print_statistics()
1933     if options.benchmark:
1934         report.print_benchmark()
1935     if options.testsuite and not options.quiet:
1936         report.print_results()
1937     if report.total_errors:
1938         if options.count:
1939             sys.stderr.write(str(report.total_errors) + '\n')
1940         sys.exit(1)
1941
1942 if __name__ == '__main__':
1943     _main()