Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pycodestyle.py: 68%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/bin/env python
2# pycodestyle.py - Check Python source code formatting, according to
3# PEP 8
4#
5# Copyright (C) 2006-2009 Johann C. Rocholl <johann@rocholl.net>
6# Copyright (C) 2009-2014 Florent Xicluna <florent.xicluna@gmail.com>
7# Copyright (C) 2014-2016 Ian Lee <ianlee1521@gmail.com>
8#
9# Permission is hereby granted, free of charge, to any person
10# obtaining a copy of this software and associated documentation files
11# (the "Software"), to deal in the Software without restriction,
12# including without limitation the rights to use, copy, modify, merge,
13# publish, distribute, sublicense, and/or sell copies of the Software,
14# and to permit persons to whom the Software is furnished to do so,
15# subject to the following conditions:
16#
17# The above copyright notice and this permission notice shall be
18# included in all copies or substantial portions of the Software.
19#
20# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27# SOFTWARE.
28r"""
29Check Python source code formatting, according to PEP 8.
31For usage and a list of options, try this:
32$ python pycodestyle.py -h
34This program and its regression test suite live here:
35https://github.com/pycqa/pycodestyle
37Groups of errors and warnings:
38E errors
39W warnings
40100 indentation
41200 whitespace
42300 blank lines
43400 imports
44500 line length
45600 deprecation
46700 statements
47900 syntax error
48"""
49import bisect
50import configparser
51import inspect
52import io
53import keyword
54import os
55import re
56import sys
57import time
58import tokenize
59import warnings
60from fnmatch import fnmatch
61from functools import lru_cache
62from itertools import pairwise
63from optparse import OptionParser
65__version__ = '2.15.0'
67DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox'
68DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503,W504'
69try:
70 if sys.platform == 'win32': # pragma: win32 cover
71 USER_CONFIG = os.path.expanduser(r'~\.pycodestyle')
72 else: # pragma: win32 no cover
73 USER_CONFIG = os.path.join(
74 os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config'),
75 'pycodestyle'
76 )
77except ImportError:
78 USER_CONFIG = None
80PROJECT_CONFIG = ('setup.cfg', 'tox.ini')
81MAX_LINE_LENGTH = 79
82# Number of blank lines between various code parts.
83BLANK_LINES_CONFIG = {
84 # Top level class and function.
85 'top_level': 2,
86 # Methods and nested class and function.
87 'method': 1,
88}
89MAX_DOC_LENGTH = 72
90INDENT_SIZE = 4
91REPORT_FORMAT = {
92 'default': '%(path)s:%(row)d:%(col)d: %(code)s %(text)s',
93 'pylint': '%(path)s:%(row)d: [%(code)s] %(text)s',
94}
96PyCF_ONLY_AST = 1024
97SINGLETONS = frozenset(['False', 'None', 'True'])
98KEYWORDS = frozenset(keyword.kwlist + ['print']) - SINGLETONS
99UNARY_OPERATORS = frozenset(['>>', '**', '*', '+', '-'])
100ARITHMETIC_OP = frozenset(['**', '*', '/', '//', '+', '-', '@'])
101WS_OPTIONAL_OPERATORS = ARITHMETIC_OP.union(['^', '&', '|', '<<', '>>', '%'])
102WS_NEEDED_OPERATORS = frozenset([
103 '**=', '*=', '/=', '//=', '+=', '-=', '!=', '<', '>',
104 '%=', '^=', '&=', '|=', '==', '<=', '>=', '<<=', '>>=', '=',
105 'and', 'in', 'is', 'or', '->', ':='])
106WHITESPACE = frozenset(' \t\xa0')
107NEWLINE = frozenset([tokenize.NL, tokenize.NEWLINE])
108SKIP_TOKENS = NEWLINE.union([tokenize.INDENT, tokenize.DEDENT])
109# ERRORTOKEN is triggered by backticks in Python 3
110SKIP_COMMENTS = SKIP_TOKENS.union([tokenize.COMMENT, tokenize.ERRORTOKEN])
111BENCHMARK_KEYS = ['directories', 'files', 'logical lines', 'physical lines']
113INDENT_REGEX = re.compile(r'([ \t]*)')
114ERRORCODE_REGEX = re.compile(r'\b[A-Z]\d{3}\b')
115DOCSTRING_REGEX = re.compile(r'u?r?["\']')
116EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[\[({][ \t]|[ \t][\]}),;:](?!=)')
117WHITESPACE_AFTER_DECORATOR_REGEX = re.compile(r'@\s')
118WHITESPACE_AFTER_COMMA_REGEX = re.compile(r'[,;:]\s*(?: |\t)')
119COMPARE_SINGLETON_REGEX = re.compile(r'(\bNone|\bFalse|\bTrue)?\s*([=!]=)'
120 r'\s*(?(1)|(None|False|True))\b')
121COMPARE_NEGATIVE_REGEX = re.compile(r'\b(?<!is\s)(not)\s+[^][)(}{ ]+\s+'
122 r'(in|is)\s')
123COMPARE_TYPE_REGEX = re.compile(
124 r'[=!]=\s+type(?:\s*\(\s*([^)]*[^\s)])\s*\))'
125 r'|(?<!\.)\btype(?:\s*\(\s*([^)]*[^\s)])\s*\))\s+[=!]='
126)
127KEYWORD_REGEX = re.compile(r'(\s*)\b(?:%s)\b(\s*)' % r'|'.join(KEYWORDS))
128OPERATOR_REGEX = re.compile(r'(?:[^,\s])(\s*)(?:[-+*/|!<=>%&^]+|:=)(\s*)')
129LAMBDA_REGEX = re.compile(r'\blambda\b')
130HUNK_REGEX = re.compile(r'^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@.*$')
131STARTSWITH_DEF_REGEX = re.compile(r'^(async\s+def|def)\b')
132STARTSWITH_GENERIC_REGEX = re.compile(r'^(async\s+def|def|class|type)\s+\w+\[')
133STARTSWITH_TOP_LEVEL_REGEX = re.compile(r'^(async\s+def\s+|def\s+|class\s+|@)')
134STARTSWITH_INDENT_STATEMENT_REGEX = re.compile(
135 r'^\s*({})\b'.format('|'.join(s.replace(' ', r'\s+') for s in (
136 'def', 'async def',
137 'for', 'async for',
138 'if', 'elif', 'else',
139 'try', 'except', 'finally',
140 'with', 'async with',
141 'class',
142 'while',
143 )))
144)
145DUNDER_REGEX = re.compile(r"^__([^\s]+)__(?::\s*[a-zA-Z.0-9_\[\]\"]+)? = ")
146BLANK_EXCEPT_REGEX = re.compile(r"except\s*:")
148if sys.version_info >= (3, 12): # pragma: >=3.12 cover
149 FSTRING_START = tokenize.FSTRING_START
150 FSTRING_MIDDLE = tokenize.FSTRING_MIDDLE
151 FSTRING_END = tokenize.FSTRING_END
152else: # pragma: <3.12 cover
153 FSTRING_START = FSTRING_MIDDLE = FSTRING_END = -1
155if sys.version_info >= (3, 14): # pragma: >=3.14 cover
156 TSTRING_START = tokenize.TSTRING_START
157 TSTRING_MIDDLE = tokenize.TSTRING_MIDDLE
158 TSTRING_END = tokenize.TSTRING_END
159else: # pragma: <3.14 cover
160 TSTRING_START = TSTRING_MIDDLE = TSTRING_END = -1
162_checks = {'physical_line': {}, 'logical_line': {}, 'tree': {}}
165def _get_parameters(function):
166 return [parameter.name
167 for parameter
168 in inspect.signature(function).parameters.values()
169 if parameter.kind == parameter.POSITIONAL_OR_KEYWORD]
172def register_check(check, codes=None):
173 """Register a new check object."""
174 def _add_check(check, kind, codes, args):
175 if check in _checks[kind]:
176 _checks[kind][check][0].extend(codes or [])
177 else:
178 _checks[kind][check] = (codes or [''], args)
179 if inspect.isfunction(check):
180 args = _get_parameters(check)
181 if args and args[0] in ('physical_line', 'logical_line'):
182 if codes is None:
183 codes = ERRORCODE_REGEX.findall(check.__doc__ or '')
184 _add_check(check, args[0], codes, args)
185 elif inspect.isclass(check):
186 if _get_parameters(check.__init__)[:2] == ['self', 'tree']:
187 _add_check(check, 'tree', codes, None)
188 return check
191########################################################################
192# Plugins (check functions) for physical lines
193########################################################################
195@register_check
196def tabs_or_spaces(physical_line, indent_char):
197 r"""Never mix tabs and spaces.
199 The most popular way of indenting Python is with spaces only. The
200 second-most popular way is with tabs only. Code indented with a
201 mixture of tabs and spaces should be converted to using spaces
202 exclusively. When invoking the Python command line interpreter with
203 the -t option, it issues warnings about code that illegally mixes
204 tabs and spaces. When using -tt these warnings become errors.
205 These options are highly recommended!
207 Okay: if a == 0:\n a = 1\n b = 1
208 """
209 indent = INDENT_REGEX.match(physical_line).group(1)
210 for offset, char in enumerate(indent):
211 if char != indent_char:
212 return offset, "E101 indentation contains mixed spaces and tabs"
215@register_check
216def tabs_obsolete(physical_line):
217 r"""On new projects, spaces-only are strongly recommended over tabs.
219 Okay: if True:\n return
220 W191: if True:\n\treturn
221 """
222 indent = INDENT_REGEX.match(physical_line).group(1)
223 if '\t' in indent:
224 return indent.index('\t'), "W191 indentation contains tabs"
227@register_check
228def trailing_whitespace(physical_line):
229 r"""Trailing whitespace is superfluous.
231 The warning returned varies on whether the line itself is blank,
232 for easier filtering for those who want to indent their blank lines.
234 Okay: spam(1)\n#
235 W291: spam(1) \n#
236 W293: class Foo(object):\n \n bang = 12
237 """
238 # Strip these trailing characters:
239 # - chr(10), newline
240 # - chr(13), carriage return
241 # - chr(12), form feed, ^L
242 physical_line = physical_line.rstrip('\n\r\x0c')
243 stripped = physical_line.rstrip(' \t\v')
244 if physical_line != stripped:
245 if stripped:
246 return len(stripped), "W291 trailing whitespace"
247 else:
248 return 0, "W293 blank line contains whitespace"
251@register_check
252def trailing_blank_lines(physical_line, lines, line_number, total_lines):
253 r"""Trailing blank lines are superfluous.
255 Okay: spam(1)
256 W391: spam(1)\n
258 However the last line should end with a new line (warning W292).
259 """
260 if line_number == total_lines:
261 stripped_last_line = physical_line.rstrip('\r\n')
262 if physical_line and not stripped_last_line:
263 return 0, "W391 blank line at end of file"
264 if stripped_last_line == physical_line:
265 return len(lines[-1]), "W292 no newline at end of file"
268@register_check
269def maximum_line_length(physical_line, max_line_length, multiline,
270 line_number, noqa):
271 r"""Limit all lines to a maximum of 79 characters.
273 There are still many devices around that are limited to 80 character
274 lines; plus, limiting windows to 80 characters makes it possible to
275 have several windows side-by-side. The default wrapping on such
276 devices looks ugly. Therefore, please limit all lines to a maximum
277 of 79 characters. For flowing long blocks of text (docstrings or
278 comments), limiting the length to 72 characters is recommended.
280 Reports error E501.
281 """
282 line = physical_line.rstrip()
283 length = len(line)
284 if length > max_line_length and not noqa:
285 # Special case: ignore long shebang lines.
286 if line_number == 1 and line.startswith('#!'):
287 return
288 # Special case for long URLs in multi-line docstrings or
289 # comments, but still report the error when the 72 first chars
290 # are whitespaces.
291 chunks = line.split()
292 if ((len(chunks) == 1 and multiline) or
293 (len(chunks) == 2 and chunks[0] == '#')) and \
294 len(line) - len(chunks[-1]) < max_line_length - 7:
295 return
296 if length > max_line_length:
297 return (max_line_length, "E501 line too long "
298 "(%d > %d characters)" % (length, max_line_length))
301########################################################################
302# Plugins (check functions) for logical lines
303########################################################################
306def _is_one_liner(logical_line, indent_level, lines, line_number):
307 if not STARTSWITH_TOP_LEVEL_REGEX.match(logical_line):
308 return False
310 line_idx = line_number - 1
312 if line_idx < 1:
313 prev_indent = 0
314 else:
315 prev_indent = expand_indent(lines[line_idx - 1])
317 if prev_indent > indent_level:
318 return False
320 while line_idx < len(lines):
321 line = lines[line_idx].strip()
322 if not line.startswith('@') and STARTSWITH_TOP_LEVEL_REGEX.match(line):
323 break
324 else:
325 line_idx += 1
326 else:
327 return False # invalid syntax: EOF while searching for def/class
329 next_idx = line_idx + 1
330 while next_idx < len(lines):
331 if lines[next_idx].strip():
332 break
333 else:
334 next_idx += 1
335 else:
336 return True # line is last in the file
338 return expand_indent(lines[next_idx]) <= indent_level
341@register_check
342def blank_lines(logical_line, blank_lines, indent_level, line_number,
343 blank_before, previous_logical,
344 previous_unindented_logical_line, previous_indent_level,
345 lines):
346 r"""Separate top-level function and class definitions with two blank
347 lines.
349 Method definitions inside a class are separated by a single blank
350 line.
352 Extra blank lines may be used (sparingly) to separate groups of
353 related functions. Blank lines may be omitted between a bunch of
354 related one-liners (e.g. a set of dummy implementations).
356 Use blank lines in functions, sparingly, to indicate logical
357 sections.
359 Okay: def a():\n pass\n\n\ndef b():\n pass
360 Okay: def a():\n pass\n\n\nasync def b():\n pass
361 Okay: def a():\n pass\n\n\n# Foo\n# Bar\n\ndef b():\n pass
362 Okay: default = 1\nfoo = 1
363 Okay: classify = 1\nfoo = 1
365 E301: class Foo:\n b = 0\n def bar():\n pass
366 E302: def a():\n pass\n\ndef b(n):\n pass
367 E302: def a():\n pass\n\nasync def b(n):\n pass
368 E303: def a():\n pass\n\n\n\ndef b(n):\n pass
369 E303: def a():\n\n\n\n pass
370 E304: @decorator\n\ndef a():\n pass
371 E305: def a():\n pass\na()
372 E306: def a():\n def b():\n pass\n def c():\n pass
373 """ # noqa
374 top_level_lines = BLANK_LINES_CONFIG['top_level']
375 method_lines = BLANK_LINES_CONFIG['method']
377 if not previous_logical and blank_before < top_level_lines:
378 return # Don't expect blank lines before the first line
379 if previous_logical.startswith('@'):
380 if blank_lines:
381 yield 0, "E304 blank lines found after function decorator"
382 elif (blank_lines > top_level_lines or
383 (indent_level and blank_lines == method_lines + 1)
384 ):
385 yield 0, "E303 too many blank lines (%d)" % blank_lines
386 elif STARTSWITH_TOP_LEVEL_REGEX.match(logical_line):
387 # allow a group of one-liners
388 if (
389 _is_one_liner(logical_line, indent_level, lines, line_number) and
390 blank_before == 0
391 ):
392 return
393 if indent_level:
394 if not (blank_before == method_lines or
395 previous_indent_level < indent_level or
396 DOCSTRING_REGEX.match(previous_logical)
397 ):
398 ancestor_level = indent_level
399 nested = False
400 # Search backwards for a def ancestor or tree root
401 # (top level).
402 for line in lines[line_number - top_level_lines::-1]:
403 if line.strip() and expand_indent(line) < ancestor_level:
404 ancestor_level = expand_indent(line)
405 nested = STARTSWITH_DEF_REGEX.match(line.lstrip())
406 if nested or ancestor_level == 0:
407 break
408 if nested:
409 yield 0, "E306 expected %s blank line before a " \
410 "nested definition, found 0" % (method_lines,)
411 else:
412 yield 0, "E301 expected {} blank line, found 0".format(
413 method_lines)
414 elif blank_before != top_level_lines:
415 yield 0, "E302 expected %s blank lines, found %d" % (
416 top_level_lines, blank_before)
417 elif (logical_line and
418 not indent_level and
419 blank_before != top_level_lines and
420 previous_unindented_logical_line.startswith(('def ', 'class '))
421 ):
422 yield 0, "E305 expected %s blank lines after " \
423 "class or function definition, found %d" % (
424 top_level_lines, blank_before)
427@register_check
428def extraneous_whitespace(logical_line):
429 r"""Avoid extraneous whitespace.
431 Avoid extraneous whitespace in these situations:
432 - Immediately inside parentheses, brackets or braces.
433 - Immediately before a comma, semicolon, or colon.
435 Okay: spam(ham[1], {eggs: 2})
436 E201: spam( ham[1], {eggs: 2})
437 E201: spam(ham[ 1], {eggs: 2})
438 E201: spam(ham[1], { eggs: 2})
439 E202: spam(ham[1], {eggs: 2} )
440 E202: spam(ham[1 ], {eggs: 2})
441 E202: spam(ham[1], {eggs: 2 })
443 E203: if x == 4: print x, y; x, y = y , x
444 E203: if x == 4: print x, y ; x, y = y, x
445 E203: if x == 4 : print x, y; x, y = y, x
447 Okay: @decorator
448 E204: @ decorator
449 """
450 line = logical_line
451 for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line):
452 text = match.group()
453 char = text.strip()
454 found = match.start()
455 if text[-1].isspace():
456 # assert char in '([{'
457 yield found + 1, "E201 whitespace after '%s'" % char
458 elif line[found - 1] != ',':
459 code = ('E202' if char in '}])' else 'E203') # if char in ',;:'
460 yield found, f"{code} whitespace before '{char}'"
462 if WHITESPACE_AFTER_DECORATOR_REGEX.match(logical_line):
463 yield 1, "E204 whitespace after decorator '@'"
466@register_check
467def whitespace_around_keywords(logical_line):
468 r"""Avoid extraneous whitespace around keywords.
470 Okay: True and False
471 E271: True and False
472 E272: True and False
473 E273: True and\tFalse
474 E274: True\tand False
475 """
476 for match in KEYWORD_REGEX.finditer(logical_line):
477 before, after = match.groups()
479 if '\t' in before:
480 yield match.start(1), "E274 tab before keyword"
481 elif len(before) > 1:
482 yield match.start(1), "E272 multiple spaces before keyword"
484 if '\t' in after:
485 yield match.start(2), "E273 tab after keyword"
486 elif len(after) > 1:
487 yield match.start(2), "E271 multiple spaces after keyword"
490@register_check
491def missing_whitespace_after_keyword(logical_line, tokens):
492 r"""Keywords should be followed by whitespace.
494 Okay: from foo import (bar, baz)
495 E275: from foo import(bar, baz)
496 E275: from importable.module import(bar, baz)
497 E275: if(foo): bar
498 """
499 for tok0, tok1 in pairwise(tokens):
500 # This must exclude the True/False/None singletons, which can
501 # appear e.g. as "if x is None:", and async/await, which were
502 # valid identifier names in old Python versions.
503 if (tok0.end == tok1.start and
504 tok0.type == tokenize.NAME and
505 keyword.iskeyword(tok0.string) and
506 tok0.string not in SINGLETONS and
507 not (tok0.string == 'except' and tok1.string == '*') and
508 not (tok0.string == 'yield' and tok1.string == ')') and
509 (tok1.string and tok1.string != ':' and tok1.string != '\n')):
510 yield tok0.end, "E275 missing whitespace after keyword"
513@register_check
514def indentation(logical_line, previous_logical, indent_char,
515 indent_level, previous_indent_level,
516 indent_size):
517 r"""Use indent_size (PEP8 says 4) spaces per indentation level.
519 For really old code that you don't want to mess up, you can continue
520 to use 8-space tabs.
522 Okay: a = 1
523 Okay: if a == 0:\n a = 1
524 E111: a = 1
525 E114: # a = 1
527 Okay: for item in items:\n pass
528 E112: for item in items:\npass
529 E115: for item in items:\n# Hi\n pass
531 Okay: a = 1\nb = 2
532 E113: a = 1\n b = 2
533 E116: a = 1\n # b = 2
534 """
535 c = 0 if logical_line else 3
536 tmpl = "E11%d %s" if logical_line else "E11%d %s (comment)"
537 if indent_level % indent_size:
538 yield 0, tmpl % (
539 1 + c,
540 "indentation is not a multiple of " + str(indent_size),
541 )
542 indent_expect = previous_logical.endswith(':')
543 if indent_expect and indent_level <= previous_indent_level:
544 yield 0, tmpl % (2 + c, "expected an indented block")
545 elif not indent_expect and indent_level > previous_indent_level:
546 yield 0, tmpl % (3 + c, "unexpected indentation")
548 if indent_expect:
549 expected_indent_amount = 8 if indent_char == '\t' else 4
550 expected_indent_level = previous_indent_level + expected_indent_amount
551 if indent_level > expected_indent_level:
552 yield 0, tmpl % (7, 'over-indented')
555@register_check
556def continued_indentation(logical_line, tokens, indent_level, hang_closing,
557 indent_char, indent_size, noqa, verbose):
558 r"""Continuation lines indentation.
560 Continuation lines should align wrapped elements either vertically
561 using Python's implicit line joining inside parentheses, brackets
562 and braces, or using a hanging indent.
564 When using a hanging indent these considerations should be applied:
565 - there should be no arguments on the first line, and
566 - further indentation should be used to clearly distinguish itself
567 as a continuation line.
569 Okay: a = (\n)
570 E123: a = (\n )
572 Okay: a = (\n 42)
573 E121: a = (\n 42)
574 E122: a = (\n42)
575 E123: a = (\n 42\n )
576 E124: a = (24,\n 42\n)
577 E125: if (\n b):\n pass
578 E126: a = (\n 42)
579 E127: a = (24,\n 42)
580 E128: a = (24,\n 42)
581 E129: if (a or\n b):\n pass
582 E131: a = (\n 42\n 24)
583 """
584 first_row = tokens[0][2][0]
585 nrows = 1 + tokens[-1][2][0] - first_row
586 if noqa or nrows == 1:
587 return
589 # indent_next tells us whether the next block is indented; assuming
590 # that it is indented by 4 spaces, then we should not allow 4-space
591 # indents on the final continuation line; in turn, some other
592 # indents are allowed to have an extra 4 spaces.
593 indent_next = logical_line.endswith(':')
595 row = depth = 0
596 valid_hangs = (indent_size,) if indent_char != '\t' \
597 else (indent_size, indent_size * 2)
598 # remember how many brackets were opened on each line
599 parens = [0] * nrows
600 # relative indents of physical lines
601 rel_indent = [0] * nrows
602 # for each depth, collect a list of opening rows
603 open_rows = [[0]]
604 # for each depth, memorize the hanging indentation
605 hangs = [None]
606 # visual indents
607 indent_chances = {}
608 last_indent = tokens[0][2]
609 visual_indent = None
610 last_token_multiline = False
611 # for each depth, memorize the visual indent column
612 indent = [last_indent[1]]
613 if verbose >= 3:
614 print(">>> " + tokens[0][4].rstrip())
616 for token_type, text, start, end, line in tokens:
618 newline = row < start[0] - first_row
619 if newline:
620 row = start[0] - first_row
621 newline = not last_token_multiline and token_type not in NEWLINE
623 if newline:
624 # this is the beginning of a continuation line.
625 last_indent = start
626 if verbose >= 3:
627 print("... " + line.rstrip())
629 # record the initial indent.
630 rel_indent[row] = expand_indent(line) - indent_level
632 # identify closing bracket
633 close_bracket = (token_type == tokenize.OP and text in ']})')
635 # is the indent relative to an opening bracket line?
636 for open_row in reversed(open_rows[depth]):
637 hang = rel_indent[row] - rel_indent[open_row]
638 hanging_indent = hang in valid_hangs
639 if hanging_indent:
640 break
641 if hangs[depth]:
642 hanging_indent = (hang == hangs[depth])
643 # is there any chance of visual indent?
644 visual_indent = (not close_bracket and hang > 0 and
645 indent_chances.get(start[1]))
647 if close_bracket and indent[depth]:
648 # closing bracket for visual indent
649 if start[1] != indent[depth]:
650 yield (start, "E124 closing bracket does not match "
651 "visual indentation")
652 elif close_bracket and not hang:
653 # closing bracket matches indentation of opening
654 # bracket's line
655 if hang_closing:
656 yield start, "E133 closing bracket is missing indentation"
657 elif indent[depth] and start[1] < indent[depth]:
658 if visual_indent is not True:
659 # visual indent is broken
660 yield (start, "E128 continuation line "
661 "under-indented for visual indent")
662 elif hanging_indent or (indent_next and
663 rel_indent[row] == 2 * indent_size):
664 # hanging indent is verified
665 if close_bracket and not hang_closing:
666 yield (start, "E123 closing bracket does not match "
667 "indentation of opening bracket's line")
668 hangs[depth] = hang
669 elif visual_indent is True:
670 # visual indent is verified
671 indent[depth] = start[1]
672 elif visual_indent in (text, str):
673 # ignore token lined up with matching one from a
674 # previous line
675 pass
676 else:
677 # indent is broken
678 if hang <= 0:
679 error = "E122", "missing indentation or outdented"
680 elif indent[depth]:
681 error = "E127", "over-indented for visual indent"
682 elif not close_bracket and hangs[depth]:
683 error = "E131", "unaligned for hanging indent"
684 else:
685 hangs[depth] = hang
686 if hang > indent_size:
687 error = "E126", "over-indented for hanging indent"
688 else:
689 error = "E121", "under-indented for hanging indent"
690 yield start, "%s continuation line %s" % error
692 # look for visual indenting
693 if (parens[row] and
694 token_type not in (tokenize.NL, tokenize.COMMENT) and
695 not indent[depth]):
696 indent[depth] = start[1]
697 indent_chances[start[1]] = True
698 if verbose >= 4:
699 print(f"bracket depth {depth} indent to {start[1]}")
700 # deal with implicit string concatenation
701 elif token_type in {
702 tokenize.STRING,
703 tokenize.COMMENT,
704 FSTRING_START,
705 TSTRING_START
706 }:
707 indent_chances[start[1]] = str
708 # visual indent after assert/raise/with
709 elif not row and not depth and text in ["assert", "raise", "with"]:
710 indent_chances[end[1] + 1] = True
711 # special case for the "if" statement because len("if (") == 4
712 elif not indent_chances and not row and not depth and text == 'if':
713 indent_chances[end[1] + 1] = True
714 elif text == ':' and line[end[1]:].isspace():
715 open_rows[depth].append(row)
717 # keep track of bracket depth
718 if token_type == tokenize.OP:
719 if text in '([{':
720 depth += 1
721 indent.append(0)
722 hangs.append(None)
723 if len(open_rows) == depth:
724 open_rows.append([])
725 open_rows[depth].append(row)
726 parens[row] += 1
727 if verbose >= 4:
728 print("bracket depth %s seen, col %s, visual min = %s" %
729 (depth, start[1], indent[depth]))
730 elif text in ')]}' and depth > 0:
731 # parent indents should not be more than this one
732 prev_indent = indent.pop() or last_indent[1]
733 hangs.pop()
734 for d in range(depth):
735 if indent[d] > prev_indent:
736 indent[d] = 0
737 for ind in list(indent_chances):
738 if ind >= prev_indent:
739 del indent_chances[ind]
740 del open_rows[depth + 1:]
741 depth -= 1
742 if depth:
743 indent_chances[indent[depth]] = True
744 for idx in range(row, -1, -1):
745 if parens[idx]:
746 parens[idx] -= 1
747 break
748 assert len(indent) == depth + 1
749 if start[1] not in indent_chances:
750 # allow lining up tokens
751 indent_chances[start[1]] = text
753 last_token_multiline = (start[0] != end[0])
754 if last_token_multiline:
755 rel_indent[end[0] - first_row] = rel_indent[row]
757 if indent_next and expand_indent(line) == indent_level + indent_size:
758 pos = (start[0], indent[0] + indent_size)
759 if visual_indent:
760 code = "E129 visually indented line"
761 else:
762 code = "E125 continuation line"
763 yield pos, "%s with same indent as next logical line" % code
766@register_check
767def whitespace_before_parameters(logical_line, tokens):
768 r"""Avoid extraneous whitespace.
770 Avoid extraneous whitespace in the following situations:
771 - before the open parenthesis that starts the argument list of a
772 function call.
773 - before the open parenthesis that starts an indexing or slicing.
775 Okay: spam(1)
776 E211: spam (1)
778 Okay: dict['key'] = list[index]
779 E211: dict ['key'] = list[index]
780 E211: dict['key'] = list [index]
781 """
782 prev_type, prev_text, __, prev_end, __ = tokens[0]
783 for index in range(1, len(tokens)):
784 token_type, text, start, end, __ = tokens[index]
785 if (
786 token_type == tokenize.OP and
787 text in '([' and
788 start != prev_end and
789 (prev_type == tokenize.NAME or prev_text in '}])') and
790 # Syntax "class A (B):" is allowed, but avoid it
791 (index < 2 or tokens[index - 2][1] != 'class') and
792 # Allow "return (a.foo for a in range(5))"
793 not keyword.iskeyword(prev_text) and
794 (
795 # 3.12+: type is a soft keyword but no braces after
796 prev_text == 'type' or
797 not keyword.issoftkeyword(prev_text)
798 )
799 ):
800 yield prev_end, "E211 whitespace before '%s'" % text
801 prev_type = token_type
802 prev_text = text
803 prev_end = end
806@register_check
807def whitespace_around_operator(logical_line):
808 r"""Avoid extraneous whitespace around an operator.
810 Okay: a = 12 + 3
811 E221: a = 4 + 5
812 E222: a = 4 + 5
813 E223: a = 4\t+ 5
814 E224: a = 4 +\t5
815 """
816 for match in OPERATOR_REGEX.finditer(logical_line):
817 before, after = match.groups()
819 if '\t' in before:
820 yield match.start(1), "E223 tab before operator"
821 elif len(before) > 1:
822 yield match.start(1), "E221 multiple spaces before operator"
824 if '\t' in after:
825 yield match.start(2), "E224 tab after operator"
826 elif len(after) > 1:
827 yield match.start(2), "E222 multiple spaces after operator"
830@register_check
831def missing_whitespace(logical_line, tokens):
832 r"""Surround operators with the correct amount of whitespace.
834 - Always surround these binary operators with a single space on
835 either side: assignment (=), augmented assignment (+=, -= etc.),
836 comparisons (==, <, >, !=, <=, >=, in, not in, is, is not),
837 Booleans (and, or, not).
839 - Each comma, semicolon or colon should be followed by whitespace.
841 - If operators with different priorities are used, consider adding
842 whitespace around the operators with the lowest priorities.
844 Okay: i = i + 1
845 Okay: submitted += 1
846 Okay: x = x * 2 - 1
847 Okay: hypot2 = x * x + y * y
848 Okay: c = (a + b) * (a - b)
849 Okay: foo(bar, key='word', *args, **kwargs)
850 Okay: alpha[:-i]
851 Okay: [a, b]
852 Okay: (3,)
853 Okay: a[3,] = 1
854 Okay: a[1:4]
855 Okay: a[:4]
856 Okay: a[1:]
857 Okay: a[1:4:2]
859 E225: i=i+1
860 E225: submitted +=1
861 E225: x = x /2 - 1
862 E225: z = x **y
863 E225: z = 1and 1
864 E226: c = (a+b) * (a-b)
865 E226: hypot2 = x*x + y*y
866 E227: c = a|b
867 E228: msg = fmt%(errno, errmsg)
868 E231: ['a','b']
869 E231: foo(bar,baz)
870 E231: [{'a':'b'}]
871 """
872 need_space = False
873 prev_type = tokenize.OP
874 prev_text = prev_end = None
875 operator_types = (tokenize.OP, tokenize.NAME)
876 brace_stack = []
877 for token_type, text, start, end, line in tokens:
878 if token_type == tokenize.OP and text in {'[', '(', '{'}:
879 brace_stack.append(text)
880 elif token_type == FSTRING_START: # pragma: >=3.12 cover
881 brace_stack.append('f')
882 elif token_type == TSTRING_START: # pragma: >=3.14 cover
883 brace_stack.append('t')
884 elif token_type == tokenize.NAME and text == 'lambda':
885 brace_stack.append('l')
886 elif brace_stack:
887 if token_type == tokenize.OP and text in {']', ')', '}'}:
888 brace_stack.pop()
889 elif token_type == FSTRING_END: # pragma: >=3.12 cover
890 brace_stack.pop()
891 elif token_type == TSTRING_END: # pragma: >=3.14 cover
892 brace_stack.pop()
893 elif (
894 brace_stack[-1] == 'l' and
895 token_type == tokenize.OP and
896 text == ':'
897 ):
898 brace_stack.pop()
900 if token_type in SKIP_COMMENTS:
901 continue
903 if token_type == tokenize.OP and text in {',', ';', ':'}:
904 next_char = line[end[1]:end[1] + 1]
905 if next_char not in WHITESPACE and next_char not in '\r\n':
906 # slice
907 if text == ':' and brace_stack[-1:] == ['[']:
908 pass
909 # 3.12+ fstring format specifier
910 elif text == ':' and brace_stack[-2:] == ['f', '{']: # pragma: >=3.12 cover # noqa: E501
911 pass
912 # 3.14+ tstring format specifier
913 elif text == ':' and brace_stack[-2:] == ['t', '{']: # pragma: >=3.14 cover # noqa: E501
914 pass
915 # tuple (and list for some reason?)
916 elif text == ',' and next_char in ')]':
917 pass
918 else:
919 yield start, f'E231 missing whitespace after {text!r}'
921 if need_space:
922 if start != prev_end:
923 # Found a (probably) needed space
924 if need_space is not True and not need_space[1]:
925 yield (need_space[0],
926 "E225 missing whitespace around operator")
927 need_space = False
928 elif (
929 # def f(a, /, b):
930 # ^
931 # def f(a, b, /):
932 # ^
933 # f = lambda a, /:
934 # ^
935 prev_text == '/' and text in {',', ')', ':'} or
936 # def f(a, b, /):
937 # ^
938 prev_text == ')' and text == ':'
939 ):
940 # Tolerate the "/" operator in function definition
941 # For more info see PEP570
942 pass
943 else:
944 if need_space is True or need_space[1]:
945 # A needed trailing space was not found
946 yield prev_end, "E225 missing whitespace around operator"
947 elif prev_text != '**':
948 code, optype = 'E226', 'arithmetic'
949 if prev_text == '%':
950 code, optype = 'E228', 'modulo'
951 elif prev_text not in ARITHMETIC_OP:
952 code, optype = 'E227', 'bitwise or shift'
953 yield (need_space[0], "%s missing whitespace "
954 "around %s operator" % (code, optype))
955 need_space = False
956 elif token_type in operator_types and prev_end is not None:
957 if (
958 text == '=' and (
959 # allow lambda default args: lambda x=None: None
960 brace_stack[-1:] == ['l'] or
961 # allow keyword args or defaults: foo(bar=None).
962 brace_stack[-1:] == ['('] or
963 # allow python 3.8 fstring repr specifier
964 brace_stack[-2:] == ['f', '{'] or
965 # allow python 3.8 fstring repr specifier
966 brace_stack[-2:] == ['t', '{']
967 )
968 ):
969 pass
970 elif text in WS_NEEDED_OPERATORS:
971 need_space = True
972 elif text in UNARY_OPERATORS:
973 # Check if the operator is used as a binary operator
974 # Allow unary operators: -123, -x, +1.
975 # Allow argument unpacking: foo(*args, **kwargs).
976 if prev_type == tokenize.OP and prev_text in '}])' or (
977 prev_type != tokenize.OP and
978 prev_text not in KEYWORDS and
979 not keyword.issoftkeyword(prev_text)
980 ):
981 need_space = None
982 elif text in WS_OPTIONAL_OPERATORS:
983 need_space = None
985 if need_space is None:
986 # Surrounding space is optional, but ensure that
987 # trailing space matches opening space
988 need_space = (prev_end, start != prev_end)
989 elif need_space and start == prev_end:
990 # A needed opening space was not found
991 yield prev_end, "E225 missing whitespace around operator"
992 need_space = False
993 prev_type = token_type
994 prev_text = text
995 prev_end = end
998@register_check
999def whitespace_around_comma(logical_line):
1000 r"""Avoid extraneous whitespace after a comma or a colon.
1002 Note: these checks are disabled by default
1004 Okay: a = (1, 2)
1005 E241: a = (1, 2)
1006 E242: a = (1,\t2)
1007 """
1008 line = logical_line
1009 for m in WHITESPACE_AFTER_COMMA_REGEX.finditer(line):
1010 found = m.start() + 1
1011 if '\t' in m.group():
1012 yield found, "E242 tab after '%s'" % m.group()[0]
1013 else:
1014 yield found, "E241 multiple spaces after '%s'" % m.group()[0]
1017@register_check
1018def whitespace_around_named_parameter_equals(logical_line, tokens):
1019 r"""Don't use spaces around the '=' sign in function arguments.
1021 Don't use spaces around the '=' sign when used to indicate a
1022 keyword argument or a default parameter value, except when
1023 using a type annotation.
1025 Okay: def complex(real, imag=0.0):
1026 Okay: return magic(r=real, i=imag)
1027 Okay: boolean(a == b)
1028 Okay: boolean(a != b)
1029 Okay: boolean(a <= b)
1030 Okay: boolean(a >= b)
1031 Okay: def foo(arg: int = 42):
1032 Okay: async def foo(arg: int = 42):
1034 E251: def complex(real, imag = 0.0):
1035 E251: return magic(r = real, i = imag)
1036 E252: def complex(real, image: float=0.0):
1037 """
1038 paren_stack = []
1039 no_space = False
1040 require_space = False
1041 prev_end = None
1042 annotated_func_arg = False
1043 in_def = bool(STARTSWITH_DEF_REGEX.match(logical_line))
1044 in_generic = bool(STARTSWITH_GENERIC_REGEX.match(logical_line))
1046 message = "E251 unexpected spaces around keyword / parameter equals"
1047 missing_message = "E252 missing whitespace around parameter equals"
1049 for token_type, text, start, end, line in tokens:
1050 if token_type == tokenize.NL:
1051 continue
1052 if no_space:
1053 no_space = False
1054 if start != prev_end:
1055 yield (prev_end, message)
1056 if require_space:
1057 require_space = False
1058 if start == prev_end:
1059 yield (prev_end, missing_message)
1060 if token_type == tokenize.OP:
1061 if text in '([':
1062 paren_stack.append(text)
1063 elif text in ')]' and paren_stack:
1064 paren_stack.pop()
1065 # def f(arg: tp = default): ...
1066 elif text == ':' and in_def and paren_stack == ['(']:
1067 annotated_func_arg = True
1068 elif len(paren_stack) == 1 and text == ',':
1069 annotated_func_arg = False
1070 elif paren_stack and text == '=':
1071 if (
1072 # PEP 696 defaults always use spaced-style `=`
1073 # type A[T = default] = ...
1074 # def f[T = default](): ...
1075 # class C[T = default](): ...
1076 (in_generic and paren_stack == ['[']) or
1077 (annotated_func_arg and paren_stack == ['('])
1078 ):
1079 require_space = True
1080 if start == prev_end:
1081 yield (prev_end, missing_message)
1082 else:
1083 no_space = True
1084 if start != prev_end:
1085 yield (prev_end, message)
1086 if not paren_stack:
1087 annotated_func_arg = False
1089 prev_end = end
1092@register_check
1093def whitespace_before_comment(logical_line, tokens):
1094 """Separate inline comments by at least two spaces.
1096 An inline comment is a comment on the same line as a statement.
1097 Inline comments should be separated by at least two spaces from the
1098 statement. They should start with a # and a single space.
1100 Each line of a block comment starts with a # and one or multiple
1101 spaces as there can be indented text inside the comment.
1103 Okay: x = x + 1 # Increment x
1104 Okay: x = x + 1 # Increment x
1105 Okay: # Block comments:
1106 Okay: # - Block comment list
1107 Okay: # \xa0- Block comment list
1108 E261: x = x + 1 # Increment x
1109 E262: x = x + 1 #Increment x
1110 E262: x = x + 1 # Increment x
1111 E262: x = x + 1 # \xa0Increment x
1112 E265: #Block comment
1113 E266: ### Block comment
1114 """
1115 prev_end = (0, 0)
1116 for token_type, text, start, end, line in tokens:
1117 if token_type == tokenize.COMMENT:
1118 inline_comment = line[:start[1]].strip()
1119 if inline_comment:
1120 if prev_end[0] == start[0] and start[1] < prev_end[1] + 2:
1121 yield (prev_end,
1122 "E261 at least two spaces before inline comment")
1123 symbol, sp, comment = text.partition(' ')
1124 bad_prefix = symbol not in '#:' and (symbol.lstrip('#')[:1] or '#')
1125 if inline_comment:
1126 if bad_prefix or comment[:1] in WHITESPACE:
1127 yield start, "E262 inline comment should start with '# '"
1128 elif bad_prefix and (bad_prefix != '!' or start[0] > 1):
1129 if bad_prefix != '#':
1130 yield start, "E265 block comment should start with '# '"
1131 elif comment:
1132 yield start, "E266 too many leading '#' for block comment"
1133 elif token_type != tokenize.NL:
1134 prev_end = end
1137@register_check
1138def imports_on_separate_lines(logical_line):
1139 r"""Place imports on separate lines.
1141 Okay: import os\nimport sys
1142 E401: import sys, os
1144 Okay: from subprocess import Popen, PIPE
1145 Okay: from myclas import MyClass
1146 Okay: from foo.bar.yourclass import YourClass
1147 Okay: import myclass
1148 Okay: import foo.bar.yourclass
1149 """
1150 line = logical_line
1151 if line.startswith('import '):
1152 found = line.find(',')
1153 if -1 < found and ';' not in line[:found]:
1154 yield found, "E401 multiple imports on one line"
1157_STRING_PREFIXES = frozenset(('u', 'U', 'b', 'B', 'r', 'R'))
1160def _is_string_literal(line):
1161 if line:
1162 first_char = line[0]
1163 if first_char in _STRING_PREFIXES:
1164 first_char = line[1]
1165 return first_char == '"' or first_char == "'"
1166 return False
1169_ALLOWED_KEYWORDS_IN_IMPORTS = (
1170 'try', 'except', 'else', 'finally', 'with', 'if', 'elif')
1173@register_check
1174def module_imports_on_top_of_file(
1175 logical_line, indent_level, checker_state, noqa):
1176 r"""Place imports at the top of the file.
1178 Always put imports at the top of the file, just after any module
1179 comments and docstrings, and before module globals and constants.
1181 Okay: import os
1182 Okay: # this is a comment\nimport os
1183 Okay: '''this is a module docstring'''\nimport os
1184 Okay: r'''this is a module docstring'''\nimport os
1185 E402: a=1\nimport os
1186 E402: 'One string'\n"Two string"\nimport os
1187 E402: a=1\nfrom sys import x
1189 Okay: if x:\n import os
1190 """ # noqa
1192 if indent_level: # Allow imports in conditional statement/function
1193 return
1194 if not logical_line: # Allow empty lines or comments
1195 return
1196 if noqa:
1197 return
1198 if logical_line.startswith((
1199 'import ', 'from ',
1200 'lazy import ', 'lazy from ',
1201 )):
1202 if checker_state.get('seen_non_imports', False):
1203 yield 0, "E402 module level import not at top of file"
1204 elif not checker_state.get('seen_non_imports', False):
1205 if DUNDER_REGEX.match(logical_line):
1206 return
1207 elif logical_line.startswith(_ALLOWED_KEYWORDS_IN_IMPORTS):
1208 # Allow certain keywords intermixed with imports in order to
1209 # support conditional or filtered importing
1210 return
1211 elif _is_string_literal(logical_line):
1212 # The first literal is a docstring, allow it. Otherwise,
1213 # report error.
1214 if checker_state.get('seen_docstring', False):
1215 checker_state['seen_non_imports'] = True
1216 else:
1217 checker_state['seen_docstring'] = True
1218 else:
1219 checker_state['seen_non_imports'] = True
1222@register_check
1223def compound_statements(logical_line):
1224 r"""Compound statements (on the same line) are generally
1225 discouraged.
1227 While sometimes it's okay to put an if/for/while with a small body
1228 on the same line, never do this for multi-clause statements.
1229 Also avoid folding such long lines!
1231 Always use a def statement instead of an assignment statement that
1232 binds a lambda expression directly to a name.
1234 Okay: if foo == 'blah':\n do_blah_thing()
1235 Okay: do_one()
1236 Okay: do_two()
1237 Okay: do_three()
1239 E701: if foo == 'blah': do_blah_thing()
1240 E701: for x in lst: total += x
1241 E701: while t < 10: t = delay()
1242 E701: if foo == 'blah': do_blah_thing()
1243 E701: else: do_non_blah_thing()
1244 E701: try: something()
1245 E701: finally: cleanup()
1246 E701: if foo == 'blah': one(); two(); three()
1247 E702: do_one(); do_two(); do_three()
1248 E703: do_four(); # useless semicolon
1249 E704: def f(x): return 2*x
1250 E731: f = lambda x: 2*x
1251 """
1252 line = logical_line
1253 last_char = len(line) - 1
1254 found = line.find(':')
1255 prev_found = 0
1256 counts = {char: 0 for char in '{}[]()'}
1257 while -1 < found < last_char:
1258 update_counts(line[prev_found:found], counts)
1259 if (
1260 counts['{'] <= counts['}'] and # {'a': 1} (dict)
1261 counts['['] <= counts[']'] and # [1:2] (slice)
1262 counts['('] <= counts[')'] and # (annotation)
1263 line[found + 1] != '=' # assignment expression
1264 ):
1265 lambda_kw = LAMBDA_REGEX.search(line, 0, found)
1266 if lambda_kw:
1267 before = line[:lambda_kw.start()].rstrip()
1268 if before[-1:] == '=' and before[:-1].strip().isidentifier():
1269 yield 0, ("E731 do not assign a lambda expression, use a "
1270 "def")
1271 break
1272 if STARTSWITH_DEF_REGEX.match(line):
1273 yield 0, "E704 multiple statements on one line (def)"
1274 elif STARTSWITH_INDENT_STATEMENT_REGEX.match(line):
1275 yield found, "E701 multiple statements on one line (colon)"
1276 prev_found = found
1277 found = line.find(':', found + 1)
1278 found = line.find(';')
1279 while -1 < found:
1280 if found < last_char:
1281 yield found, "E702 multiple statements on one line (semicolon)"
1282 else:
1283 yield found, "E703 statement ends with a semicolon"
1284 found = line.find(';', found + 1)
1287@register_check
1288def explicit_line_join(logical_line, tokens):
1289 r"""Avoid explicit line join between brackets.
1291 The preferred way of wrapping long lines is by using Python's
1292 implied line continuation inside parentheses, brackets and braces.
1293 Long lines can be broken over multiple lines by wrapping expressions
1294 in parentheses. These should be used in preference to using a
1295 backslash for line continuation.
1297 E502: aaa = [123, \\n 123]
1298 E502: aaa = ("bbb " \\n "ccc")
1300 Okay: aaa = [123,\n 123]
1301 Okay: aaa = ("bbb "\n "ccc")
1302 Okay: aaa = "bbb " \\n "ccc"
1303 Okay: aaa = 123 # \\
1304 """
1305 prev_start = prev_end = parens = 0
1306 comment = False
1307 backslash = None
1308 for token_type, text, start, end, line in tokens:
1309 if token_type == tokenize.COMMENT:
1310 comment = True
1311 if start[0] != prev_start and parens and backslash and not comment:
1312 yield backslash, "E502 the backslash is redundant between brackets"
1313 if start[0] != prev_start:
1314 comment = False # Reset comment flag on newline
1315 if end[0] != prev_end:
1316 if line.rstrip('\r\n').endswith('\\'):
1317 backslash = (end[0], len(line.splitlines()[-1]) - 1)
1318 else:
1319 backslash = None
1320 prev_start = prev_end = end[0]
1321 else:
1322 prev_start = start[0]
1323 if token_type == tokenize.OP:
1324 if text in '([{':
1325 parens += 1
1326 elif text in ')]}':
1327 parens -= 1
1330# The % character is strictly speaking a binary operator, but the
1331# common usage seems to be to put it next to the format parameters,
1332# after a line break.
1333_SYMBOLIC_OPS = frozenset("()[]{},:.;@=%~") | frozenset(("...",))
1336def _is_binary_operator(token_type, text):
1337 return (
1338 token_type == tokenize.OP or
1339 text in {'and', 'or'}
1340 ) and (
1341 text not in _SYMBOLIC_OPS
1342 )
1345def _break_around_binary_operators(tokens):
1346 """Private function to reduce duplication.
1348 This factors out the shared details between
1349 :func:`break_before_binary_operator` and
1350 :func:`break_after_binary_operator`.
1351 """
1352 line_break = False
1353 unary_context = True
1354 # Previous non-newline token types and text
1355 previous_token_type = None
1356 previous_text = None
1357 for token_type, text, start, end, line in tokens:
1358 if token_type == tokenize.COMMENT:
1359 continue
1360 if ('\n' in text or '\r' in text) and token_type != tokenize.STRING:
1361 line_break = True
1362 else:
1363 yield (token_type, text, previous_token_type, previous_text,
1364 line_break, unary_context, start)
1365 unary_context = text in '([{,;'
1366 line_break = False
1367 previous_token_type = token_type
1368 previous_text = text
1371@register_check
1372def break_before_binary_operator(logical_line, tokens):
1373 r"""
1374 Avoid breaks before binary operators.
1376 The preferred place to break around a binary operator is after the
1377 operator, not before it.
1379 W503: (width == 0\n + height == 0)
1380 W503: (width == 0\n and height == 0)
1381 W503: var = (1\n & ~2)
1382 W503: var = (1\n / -2)
1383 W503: var = (1\n + -1\n + -2)
1385 Okay: foo(\n -x)
1386 Okay: foo(x\n [])
1387 Okay: x = '''\n''' + ''
1388 Okay: foo(x,\n -y)
1389 Okay: foo(x, # comment\n -y)
1390 """
1391 for context in _break_around_binary_operators(tokens):
1392 (token_type, text, previous_token_type, previous_text,
1393 line_break, unary_context, start) = context
1394 if (_is_binary_operator(token_type, text) and line_break and
1395 not unary_context and
1396 not _is_binary_operator(previous_token_type,
1397 previous_text)):
1398 yield start, "W503 line break before binary operator"
1401@register_check
1402def break_after_binary_operator(logical_line, tokens):
1403 r"""
1404 Avoid breaks after binary operators.
1406 The preferred place to break around a binary operator is before the
1407 operator, not after it.
1409 W504: (width == 0 +\n height == 0)
1410 W504: (width == 0 and\n height == 0)
1411 W504: var = (1 &\n ~2)
1413 Okay: foo(\n -x)
1414 Okay: foo(x\n [])
1415 Okay: x = '''\n''' + ''
1416 Okay: x = '' + '''\n'''
1417 Okay: foo(x,\n -y)
1418 Okay: foo(x, # comment\n -y)
1420 The following should be W504 but unary_context is tricky with these
1421 Okay: var = (1 /\n -2)
1422 Okay: var = (1 +\n -1 +\n -2)
1423 """
1424 prev_start = None
1425 for context in _break_around_binary_operators(tokens):
1426 (token_type, text, previous_token_type, previous_text,
1427 line_break, unary_context, start) = context
1428 if (_is_binary_operator(previous_token_type, previous_text) and
1429 line_break and
1430 not unary_context and
1431 not _is_binary_operator(token_type, text)):
1432 yield prev_start, "W504 line break after binary operator"
1433 prev_start = start
1436@register_check
1437def comparison_to_singleton(logical_line, noqa):
1438 r"""Comparison to singletons should use "is" or "is not".
1440 Comparisons to singletons like None should always be done
1441 with "is" or "is not", never the equality operators.
1443 Okay: if arg is not None:
1444 E711: if arg != None:
1445 E711: if None == arg:
1446 E712: if arg == True:
1447 E712: if False == arg:
1449 Also, beware of writing if x when you really mean if x is not None
1450 -- e.g. when testing whether a variable or argument that defaults to
1451 None was set to some other value. The other value might have a type
1452 (such as a container) that could be false in a boolean context!
1453 """
1454 if noqa:
1455 return
1457 for match in COMPARE_SINGLETON_REGEX.finditer(logical_line):
1458 singleton = match.group(1) or match.group(3)
1459 same = (match.group(2) == '==')
1461 msg = "'if cond is %s:'" % (('' if same else 'not ') + singleton)
1462 if singleton in ('None',):
1463 code = 'E711'
1464 else:
1465 code = 'E712'
1466 nonzero = ((singleton == 'True' and same) or
1467 (singleton == 'False' and not same))
1468 msg += " or 'if %scond:'" % ('' if nonzero else 'not ')
1469 yield match.start(2), ("%s comparison to %s should be %s" %
1470 (code, singleton, msg))
1473@register_check
1474def comparison_negative(logical_line):
1475 r"""Negative comparison should be done using "not in" and "is not".
1477 Okay: if x not in y:\n pass
1478 Okay: assert (X in Y or X is Z)
1479 Okay: if not (X in Y):\n pass
1480 Okay: zz = x is not y
1481 E713: Z = not X in Y
1482 E713: if not X.B in Y:\n pass
1483 E714: if not X is Y:\n pass
1484 E714: Z = not X.B is Y
1485 """
1486 match = COMPARE_NEGATIVE_REGEX.search(logical_line)
1487 if match:
1488 pos = match.start(1)
1489 if match.group(2) == 'in':
1490 yield pos, "E713 test for membership should be 'not in'"
1491 else:
1492 yield pos, "E714 test for object identity should be 'is not'"
1495@register_check
1496def comparison_type(logical_line, noqa):
1497 r"""Object type comparisons should `is` / `is not` / `isinstance()`.
1499 Do not compare types directly.
1501 Okay: if isinstance(obj, int):
1502 Okay: if type(obj) is int:
1503 E721: if type(obj) == type(1):
1504 """
1505 match = COMPARE_TYPE_REGEX.search(logical_line)
1506 if match and not noqa:
1507 inst = match.group(1)
1508 if inst and inst.isidentifier() and inst not in SINGLETONS:
1509 return # Allow comparison for types which are not obvious
1510 yield (
1511 match.start(),
1512 "E721 do not compare types, for exact checks use `is` / `is not`, "
1513 "for instance checks use `isinstance()`",
1514 )
1517@register_check
1518def bare_except(logical_line, noqa):
1519 r"""When catching exceptions, mention specific exceptions when
1520 possible.
1522 Okay: except Exception:
1523 Okay: except BaseException:
1524 E722: except:
1525 """
1526 if noqa:
1527 return
1529 match = BLANK_EXCEPT_REGEX.match(logical_line)
1530 if match:
1531 yield match.start(), "E722 do not use bare 'except'"
1534@register_check
1535def ambiguous_identifier(logical_line, tokens):
1536 r"""Never use the characters 'l', 'O', or 'I' as variable names.
1538 In some fonts, these characters are indistinguishable from the
1539 numerals one and zero. When tempted to use 'l', use 'L' instead.
1541 Okay: L = 0
1542 Okay: o = 123
1543 Okay: i = 42
1544 E741: l = 0
1545 E741: O = 123
1546 E741: I = 42
1548 Variables can be bound in several other contexts, including class
1549 and function definitions, lambda functions, 'global' and 'nonlocal'
1550 statements, exception handlers, and 'with' and 'for' statements.
1551 In addition, we have a special handling for function parameters.
1553 Okay: except AttributeError as o:
1554 Okay: with lock as L:
1555 Okay: foo(l=12)
1556 Okay: foo(l=I)
1557 Okay: for a in foo(l=12):
1558 Okay: lambda arg: arg * l
1559 Okay: lambda a=l[I:5]: None
1560 Okay: lambda x=a.I: None
1561 Okay: if l >= 12:
1562 E741: except AttributeError as O:
1563 E741: with lock as l:
1564 E741: global I
1565 E741: nonlocal l
1566 E741: def foo(l):
1567 E741: def foo(l=12):
1568 E741: l = foo(l=12)
1569 E741: for l in range(10):
1570 E741: [l for l in lines if l]
1571 E741: lambda l: None
1572 E741: lambda a=x[1:5], l: None
1573 E741: lambda **l:
1574 E741: def f(**l):
1575 E742: class I(object):
1576 E743: def l(x):
1577 """
1578 func_depth = None # set to brace depth if 'def' or 'lambda' is found
1579 seen_colon = False # set to true if we're done with function parameters
1580 brace_depth = 0
1581 idents_to_avoid = ('l', 'O', 'I')
1582 prev_type, prev_text, prev_start, prev_end, __ = tokens[0]
1583 for index in range(1, len(tokens)):
1584 token_type, text, start, end, line = tokens[index]
1585 ident = pos = None
1586 # find function definitions
1587 if prev_text in {'def', 'lambda'}:
1588 func_depth = brace_depth
1589 seen_colon = False
1590 elif (
1591 func_depth is not None and
1592 text == ':' and
1593 brace_depth == func_depth
1594 ):
1595 seen_colon = True
1596 # update parameter parentheses level
1597 if text in '([{':
1598 brace_depth += 1
1599 elif text in ')]}':
1600 brace_depth -= 1
1601 # identifiers on the lhs of an assignment operator
1602 if text == ':=' or (text == '=' and brace_depth == 0):
1603 if prev_text in idents_to_avoid:
1604 ident = prev_text
1605 pos = prev_start
1606 # identifiers bound to values with 'as', 'for',
1607 # 'global', or 'nonlocal'
1608 if prev_text in ('as', 'for', 'global', 'nonlocal'):
1609 if text in idents_to_avoid:
1610 ident = text
1611 pos = start
1612 # function / lambda parameter definitions
1613 if (
1614 func_depth is not None and
1615 not seen_colon and
1616 index < len(tokens) - 1 and tokens[index + 1][1] in ':,=)' and
1617 prev_text in {'lambda', ',', '*', '**', '('} and
1618 text in idents_to_avoid
1619 ):
1620 ident = text
1621 pos = start
1622 if prev_text == 'class':
1623 if text in idents_to_avoid:
1624 yield start, "E742 ambiguous class definition '%s'" % text
1625 if prev_text == 'def':
1626 if text in idents_to_avoid:
1627 yield start, "E743 ambiguous function definition '%s'" % text
1628 if ident:
1629 yield pos, "E741 ambiguous variable name '%s'" % ident
1630 prev_text = text
1631 prev_start = start
1634# https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals
1635_PYTHON_3000_VALID_ESC = frozenset([
1636 '\n',
1637 '\\',
1638 '\'',
1639 '"',
1640 'a',
1641 'b',
1642 'f',
1643 'n',
1644 'r',
1645 't',
1646 'v',
1647 '0', '1', '2', '3', '4', '5', '6', '7',
1648 'x',
1650 # Escape sequences only recognized in string literals
1651 'N',
1652 'u',
1653 'U',
1654])
1657@register_check
1658def python_3000_invalid_escape_sequence(logical_line, tokens, noqa):
1659 r"""Invalid escape sequences are deprecated in Python 3.6.
1661 Okay: regex = r'\.png$'
1662 W605: regex = '\.png$'
1663 """
1664 if noqa:
1665 return
1667 prefixes = []
1668 for token_type, text, start, _, _ in tokens:
1669 if (
1670 token_type == tokenize.STRING or
1671 token_type == FSTRING_START or
1672 token_type == TSTRING_START
1673 ):
1674 # Extract string modifiers (e.g. u or r)
1675 prefixes.append(text[:text.index(text[-1])].lower())
1677 if (
1678 token_type == tokenize.STRING or
1679 token_type == FSTRING_MIDDLE or
1680 token_type == TSTRING_MIDDLE
1681 ):
1682 if 'r' not in prefixes[-1]:
1683 start_line, start_col = start
1684 pos = text.find('\\')
1685 while pos >= 0:
1686 pos += 1
1687 if text[pos] not in _PYTHON_3000_VALID_ESC:
1688 line = start_line + text.count('\n', 0, pos)
1689 if line == start_line:
1690 col = start_col + pos
1691 else:
1692 col = pos - text.rfind('\n', 0, pos) - 1
1693 yield (
1694 (line, col - 1),
1695 f"W605 invalid escape sequence '\\{text[pos]}'"
1696 )
1697 pos = text.find('\\', pos + 1)
1699 if (
1700 token_type == tokenize.STRING or
1701 token_type == FSTRING_END or
1702 token_type == TSTRING_END
1703 ):
1704 prefixes.pop()
1707########################################################################
1708@register_check
1709def maximum_doc_length(logical_line, max_doc_length, noqa, tokens):
1710 r"""Limit all doc lines to a maximum of 72 characters.
1712 For flowing long blocks of text (docstrings or comments), limiting
1713 the length to 72 characters is recommended.
1715 Reports warning W505
1716 """
1717 if max_doc_length is None or noqa:
1718 return
1720 prev_token = None
1721 skip_lines = set()
1722 # Skip lines that
1723 for token_type, text, start, end, line in tokens:
1724 if token_type not in SKIP_COMMENTS.union([tokenize.STRING]):
1725 skip_lines.add(line)
1727 for token_type, text, start, end, line in tokens:
1728 # Skip lines that aren't pure strings
1729 if token_type == tokenize.STRING and skip_lines:
1730 continue
1731 if token_type in (tokenize.STRING, tokenize.COMMENT):
1732 # Only check comment-only lines
1733 if prev_token is None or prev_token in SKIP_TOKENS:
1734 lines = line.splitlines()
1735 for line_num, physical_line in enumerate(lines):
1736 if start[0] + line_num == 1 and line.startswith('#!'):
1737 return
1738 length = len(physical_line)
1739 chunks = physical_line.split()
1740 if token_type == tokenize.COMMENT:
1741 if (len(chunks) == 2 and
1742 length - len(chunks[-1]) < MAX_DOC_LENGTH):
1743 continue
1744 if len(chunks) == 1 and line_num + 1 < len(lines):
1745 if (len(chunks) == 1 and
1746 length - len(chunks[-1]) < MAX_DOC_LENGTH):
1747 continue
1748 if length > max_doc_length:
1749 doc_error = (start[0] + line_num, max_doc_length)
1750 yield (doc_error, "W505 doc line too long "
1751 "(%d > %d characters)"
1752 % (length, max_doc_length))
1753 prev_token = token_type
1756########################################################################
1757# Helper functions
1758########################################################################
1761def readlines(filename):
1762 """Read the source code."""
1763 try:
1764 with tokenize.open(filename) as f:
1765 return f.readlines()
1766 except (LookupError, SyntaxError, UnicodeError):
1767 # Fall back if file encoding is improperly declared
1768 with open(filename, encoding='latin-1') as f:
1769 return f.readlines()
1772def stdin_get_value():
1773 """Read the value from stdin."""
1774 return io.TextIOWrapper(sys.stdin.buffer, errors='ignore').read()
1777noqa = lru_cache(512)(re.compile(r'# no(?:qa|pep8)\b', re.I).search)
1780def expand_indent(line):
1781 r"""Return the amount of indentation.
1783 Tabs are expanded to the next multiple of 8.
1784 """
1785 line = line.rstrip('\n\r')
1786 if '\t' not in line:
1787 return len(line) - len(line.lstrip())
1788 result = 0
1789 for char in line:
1790 if char == '\t':
1791 result = result // 8 * 8 + 8
1792 elif char == ' ':
1793 result += 1
1794 else:
1795 break
1796 return result
1799def mute_string(text):
1800 """Replace contents with 'xxx' to prevent syntax matching."""
1801 # String modifiers (e.g. u or r)
1802 start = text.index(text[-1]) + 1
1803 end = len(text) - 1
1804 # Triple quotes
1805 if text[-3:] in ('"""', "'''"):
1806 start += 2
1807 end -= 2
1808 return text[:start] + 'x' * (end - start) + text[end:]
1811def parse_udiff(diff, patterns=None, parent='.'):
1812 """Return a dictionary of matching lines."""
1813 # For each file of the diff, the entry key is the filename,
1814 # and the value is a set of row numbers to consider.
1815 rv = {}
1816 path = nrows = None
1817 for line in diff.splitlines():
1818 if nrows:
1819 if line[:1] != '-':
1820 nrows -= 1
1821 continue
1822 if line[:3] == '@@ ':
1823 hunk_match = HUNK_REGEX.match(line)
1824 (row, nrows) = (int(g or '1') for g in hunk_match.groups())
1825 rv[path].update(range(row, row + nrows))
1826 elif line[:3] == '+++':
1827 path = line[4:].split('\t', 1)[0]
1828 # Git diff will use (i)ndex, (w)ork tree, (c)ommit and
1829 # (o)bject instead of a/b/c/d as prefixes for patches
1830 if path[:2] in ('b/', 'w/', 'i/'):
1831 path = path[2:]
1832 rv[path] = set()
1833 return {
1834 os.path.join(parent, filepath): rows
1835 for (filepath, rows) in rv.items()
1836 if rows and filename_match(filepath, patterns)
1837 }
1840def normalize_paths(value, parent=os.curdir):
1841 """Parse a comma-separated list of paths.
1843 Return a list of absolute paths.
1844 """
1845 if not value:
1846 return []
1847 if isinstance(value, list):
1848 return value
1849 paths = []
1850 for path in value.split(','):
1851 path = path.strip()
1852 if '/' in path:
1853 path = os.path.abspath(os.path.join(parent, path))
1854 paths.append(path.rstrip('/'))
1855 return paths
1858def filename_match(filename, patterns, default=True):
1859 """Check if patterns contains a pattern that matches filename.
1861 If patterns is unspecified, this always returns True.
1862 """
1863 if not patterns:
1864 return default
1865 return any(fnmatch(filename, pattern) for pattern in patterns)
1868def update_counts(s, counts):
1869 r"""Adds one to the counts of each appearance of characters in s,
1870 for characters in counts"""
1871 for char in s:
1872 if char in counts:
1873 counts[char] += 1
1876def _is_eol_token(token):
1877 return token[0] in NEWLINE or token[4][token[3][1]:].lstrip() == '\\\n'
1880########################################################################
1881# Framework to run all checks
1882########################################################################
1885class Checker:
1886 """Load a Python source file, tokenize it, check coding style."""
1888 def __init__(self, filename=None, lines=None,
1889 options=None, report=None, **kwargs):
1890 if options is None:
1891 options = StyleGuide(kwargs).options
1892 else:
1893 assert not kwargs
1894 self._io_error = None
1895 self._physical_checks = options.physical_checks
1896 self._logical_checks = options.logical_checks
1897 self._ast_checks = options.ast_checks
1898 self.max_line_length = options.max_line_length
1899 self.max_doc_length = options.max_doc_length
1900 self.indent_size = options.indent_size
1901 self.fstring_start = self.tstring_start = 0
1902 self.multiline = False # in a multiline string?
1903 self.hang_closing = options.hang_closing
1904 self.indent_size = options.indent_size
1905 self.verbose = options.verbose
1906 self.filename = filename
1907 # Dictionary where a checker can store its custom state.
1908 self._checker_states = {}
1909 if filename is None:
1910 self.filename = 'stdin'
1911 self.lines = lines or []
1912 elif filename == '-':
1913 self.filename = 'stdin'
1914 self.lines = stdin_get_value().splitlines(True)
1915 elif lines is None:
1916 try:
1917 self.lines = readlines(filename)
1918 except OSError:
1919 (exc_type, exc) = sys.exc_info()[:2]
1920 self._io_error = f'{exc_type.__name__}: {exc}'
1921 self.lines = []
1922 else:
1923 self.lines = lines
1924 if self.lines:
1925 ord0 = ord(self.lines[0][0])
1926 if ord0 in (0xef, 0xfeff): # Strip the UTF-8 BOM
1927 if ord0 == 0xfeff:
1928 self.lines[0] = self.lines[0][1:]
1929 elif self.lines[0][:3] == '\xef\xbb\xbf':
1930 self.lines[0] = self.lines[0][3:]
1931 self.report = report or options.report
1932 self.report_error = self.report.error
1933 self.noqa = False
1935 def report_invalid_syntax(self):
1936 """Check if the syntax is valid."""
1937 (exc_type, exc) = sys.exc_info()[:2]
1938 if len(exc.args) > 1:
1939 offset = exc.args[1]
1940 if len(offset) > 2:
1941 offset = offset[1:3]
1942 else:
1943 offset = (1, 0)
1944 self.report_error(offset[0], offset[1] or 0,
1945 f'E901 {exc_type.__name__}: {exc.args[0]}',
1946 self.report_invalid_syntax)
1948 def readline(self):
1949 """Get the next line from the input buffer."""
1950 if self.line_number >= self.total_lines:
1951 return ''
1952 line = self.lines[self.line_number]
1953 self.line_number += 1
1954 if self.indent_char is None and line[:1] in WHITESPACE:
1955 self.indent_char = line[0]
1956 return line
1958 def run_check(self, check, argument_names):
1959 """Run a check plugin."""
1960 arguments = [getattr(self, name) for name in argument_names]
1961 return check(*arguments)
1963 def init_checker_state(self, name, argument_names):
1964 """Prepare custom state for the specific checker plugin."""
1965 if 'checker_state' in argument_names:
1966 self.checker_state = self._checker_states.setdefault(name, {})
1968 def check_physical(self, line):
1969 """Run all physical checks on a raw input line."""
1970 self.physical_line = line
1971 for name, check, argument_names in self._physical_checks:
1972 self.init_checker_state(name, argument_names)
1973 result = self.run_check(check, argument_names)
1974 if result is not None:
1975 (offset, text) = result
1976 self.report_error(self.line_number, offset, text, check)
1977 if text[:4] == 'E101':
1978 self.indent_char = line[0]
1980 def build_tokens_line(self):
1981 """Build a logical line from tokens."""
1982 logical = []
1983 comments = []
1984 length = 0
1985 prev_row = prev_col = mapping = None
1986 for token_type, text, start, end, line in self.tokens:
1987 if token_type in SKIP_TOKENS:
1988 continue
1989 if not mapping:
1990 mapping = [(0, start)]
1991 if token_type == tokenize.COMMENT:
1992 comments.append(text)
1993 continue
1994 if token_type == tokenize.STRING:
1995 text = mute_string(text)
1996 elif token_type in {FSTRING_MIDDLE, TSTRING_MIDDLE}: # pragma: >=3.12 cover # noqa: E501
1997 # fstring tokens are "unescaped" braces -- re-escape!
1998 brace_count = text.count('{') + text.count('}')
1999 text = 'x' * (len(text) + brace_count)
2000 end = (end[0], end[1] + brace_count)
2001 if prev_row:
2002 (start_row, start_col) = start
2003 if prev_row != start_row: # different row
2004 prev_text = self.lines[prev_row - 1][prev_col - 1]
2005 if prev_text == ',' or (prev_text not in '{[(' and
2006 text not in '}])'):
2007 text = ' ' + text
2008 elif prev_col != start_col: # different column
2009 text = line[prev_col:start_col] + text
2010 logical.append(text)
2011 length += len(text)
2012 mapping.append((length, end))
2013 (prev_row, prev_col) = end
2014 self.logical_line = ''.join(logical)
2015 self.noqa = comments and noqa(''.join(comments))
2016 return mapping
2018 def check_logical(self):
2019 """Build a line from tokens and run all logical checks on it."""
2020 self.report.increment_logical_line()
2021 mapping = self.build_tokens_line()
2022 if not mapping:
2023 return
2025 mapping_offsets = [offset for offset, _ in mapping]
2026 (start_row, start_col) = mapping[0][1]
2027 start_line = self.lines[start_row - 1]
2028 self.indent_level = expand_indent(start_line[:start_col])
2029 if self.blank_before < self.blank_lines:
2030 self.blank_before = self.blank_lines
2031 if self.verbose >= 2:
2032 print(self.logical_line[:80].rstrip())
2033 for name, check, argument_names in self._logical_checks:
2034 if self.verbose >= 4:
2035 print(' ' + name)
2036 self.init_checker_state(name, argument_names)
2037 for offset, text in self.run_check(check, argument_names) or ():
2038 if not isinstance(offset, tuple):
2039 # As mappings are ordered, bisecting is a fast way
2040 # to find a given offset in them.
2041 token_offset, pos = mapping[bisect.bisect_left(
2042 mapping_offsets, offset)]
2043 offset = (pos[0], pos[1] + offset - token_offset)
2044 self.report_error(offset[0], offset[1], text, check)
2045 if self.logical_line:
2046 self.previous_indent_level = self.indent_level
2047 self.previous_logical = self.logical_line
2048 if not self.indent_level:
2049 self.previous_unindented_logical_line = self.logical_line
2050 self.blank_lines = 0
2051 self.tokens = []
2053 def check_ast(self):
2054 """Build the file's AST and run all AST checks."""
2055 try:
2056 tree = compile(''.join(self.lines), '', 'exec', PyCF_ONLY_AST)
2057 except (ValueError, SyntaxError, TypeError):
2058 return self.report_invalid_syntax()
2059 for name, cls, __ in self._ast_checks:
2060 checker = cls(tree, self.filename)
2061 for lineno, offset, text, check in checker.run():
2062 if not self.lines or not noqa(self.lines[lineno - 1]):
2063 self.report_error(lineno, offset, text, check)
2065 def generate_tokens(self):
2066 """Tokenize file, run physical line checks and yield tokens."""
2067 if self._io_error:
2068 self.report_error(1, 0, 'E902 %s' % self._io_error, readlines)
2069 tokengen = tokenize.generate_tokens(self.readline)
2070 try:
2071 prev_physical = ''
2072 for token in tokengen:
2073 if token[2][0] > self.total_lines:
2074 return
2075 self.noqa = token[4] and noqa(token[4])
2076 self.maybe_check_physical(token, prev_physical)
2077 yield token
2078 prev_physical = token[4]
2079 except (SyntaxError, tokenize.TokenError):
2080 self.report_invalid_syntax()
2082 def maybe_check_physical(self, token, prev_physical):
2083 """If appropriate for token, check current physical line(s)."""
2084 # Called after every token, but act only on end of line.
2086 if token.type == FSTRING_START: # pragma: >=3.12 cover
2087 self.fstring_start = token.start[0]
2088 elif token.type == TSTRING_START: # pragma: >=3.14 cover
2089 self.tstring_start = token.start[0]
2090 # a newline token ends a single physical line.
2091 elif _is_eol_token(token):
2092 # if the file does not end with a newline, the NEWLINE
2093 # token is inserted by the parser, but it does not contain
2094 # the previous physical line in `token[4]`
2095 if token.line == '':
2096 self.check_physical(prev_physical)
2097 else:
2098 self.check_physical(token.line)
2099 elif (
2100 token.type == tokenize.STRING and '\n' in token.string or
2101 token.type == FSTRING_END or
2102 token.type == TSTRING_END
2103 ):
2104 # Less obviously, a string that contains newlines is a
2105 # multiline string, either triple-quoted or with internal
2106 # newlines backslash-escaped. Check every physical line in
2107 # the string *except* for the last one: its newline is
2108 # outside of the multiline string, so we consider it a
2109 # regular physical line, and will check it like any other
2110 # physical line.
2111 #
2112 # Subtleties:
2113 # - we don't *completely* ignore the last line; if it
2114 # contains the magical "# noqa" comment, we disable all
2115 # physical checks for the entire multiline string
2116 # - have to wind self.line_number back because initially it
2117 # points to the last line of the string, and we want
2118 # check_physical() to give accurate feedback
2119 if noqa(token.line):
2120 return
2121 if token.type == FSTRING_END: # pragma: >=3.12 cover
2122 start = self.fstring_start
2123 elif token.type == TSTRING_END: # pragma: >=3.12 cover
2124 start = self.tstring_start
2125 else:
2126 start = token.start[0]
2127 end = token.end[0]
2129 self.multiline = True
2130 self.line_number = start
2131 for line_number in range(start, end):
2132 self.check_physical(self.lines[line_number - 1] + '\n')
2133 self.line_number += 1
2134 self.multiline = False
2136 def check_all(self, expected=None, line_offset=0):
2137 """Run all checks on the input file."""
2138 self.report.init_file(self.filename, self.lines, expected, line_offset)
2139 self.total_lines = len(self.lines)
2140 if self._ast_checks:
2141 self.check_ast()
2142 self.line_number = 0
2143 self.indent_char = None
2144 self.indent_level = self.previous_indent_level = 0
2145 self.previous_logical = ''
2146 self.previous_unindented_logical_line = ''
2147 self.tokens = []
2148 self.blank_lines = self.blank_before = 0
2149 parens = 0
2150 for token in self.generate_tokens():
2151 self.tokens.append(token)
2152 token_type, text = token[0:2]
2153 if self.verbose >= 3:
2154 if token[2][0] == token[3][0]:
2155 pos = '[{}:{}]'.format(token[2][1] or '', token[3][1])
2156 else:
2157 pos = 'l.%s' % token[3][0]
2158 print('l.%s\t%s\t%s\t%r' %
2159 (token[2][0], pos, tokenize.tok_name[token[0]], text))
2160 if token_type == tokenize.OP:
2161 if text in '([{':
2162 parens += 1
2163 elif text in '}])':
2164 parens -= 1
2165 elif not parens:
2166 if token_type in NEWLINE:
2167 if token_type == tokenize.NEWLINE:
2168 self.check_logical()
2169 self.blank_before = 0
2170 elif len(self.tokens) == 1:
2171 # The physical line contains only this token.
2172 self.blank_lines += 1
2173 del self.tokens[0]
2174 else:
2175 self.check_logical()
2176 if self.tokens:
2177 self.check_physical(self.lines[-1])
2178 self.check_logical()
2179 return self.report.get_file_results()
2182class BaseReport:
2183 """Collect the results of the checks."""
2185 print_filename = False
2187 def __init__(self, options):
2188 self._benchmark_keys = options.benchmark_keys
2189 self._ignore_code = options.ignore_code
2190 # Results
2191 self.elapsed = 0
2192 self.total_errors = 0
2193 self.counters = dict.fromkeys(self._benchmark_keys, 0)
2194 self.messages = {}
2196 def start(self):
2197 """Start the timer."""
2198 self._start_time = time.time()
2200 def stop(self):
2201 """Stop the timer."""
2202 self.elapsed = time.time() - self._start_time
2204 def init_file(self, filename, lines, expected, line_offset):
2205 """Signal a new file."""
2206 self.filename = filename
2207 self.lines = lines
2208 self.expected = expected or ()
2209 self.line_offset = line_offset
2210 self.file_errors = 0
2211 self.counters['files'] += 1
2212 self.counters['physical lines'] += len(lines)
2214 def increment_logical_line(self):
2215 """Signal a new logical line."""
2216 self.counters['logical lines'] += 1
2218 def error(self, line_number, offset, text, check):
2219 """Report an error, according to options."""
2220 code = text[:4]
2221 if self._ignore_code(code):
2222 return
2223 if code in self.counters:
2224 self.counters[code] += 1
2225 else:
2226 self.counters[code] = 1
2227 self.messages[code] = text[5:]
2228 # Don't care about expected errors or warnings
2229 if code in self.expected:
2230 return
2231 if self.print_filename and not self.file_errors:
2232 print(self.filename)
2233 self.file_errors += 1
2234 self.total_errors += 1
2235 return code
2237 def get_file_results(self):
2238 """Return the count of errors and warnings for this file."""
2239 return self.file_errors
2241 def get_count(self, prefix=''):
2242 """Return the total count of errors and warnings."""
2243 return sum(self.counters[key]
2244 for key in self.messages if key.startswith(prefix))
2246 def get_statistics(self, prefix=''):
2247 """Get statistics for message codes that start with the prefix.
2249 prefix='' matches all errors and warnings
2250 prefix='E' matches all errors
2251 prefix='W' matches all warnings
2252 prefix='E4' matches all errors that have to do with imports
2253 """
2254 return ['%-7s %s %s' % (self.counters[key], key, self.messages[key])
2255 for key in sorted(self.messages) if key.startswith(prefix)]
2257 def print_statistics(self, prefix=''):
2258 """Print overall statistics (number of errors and warnings)."""
2259 for line in self.get_statistics(prefix):
2260 print(line)
2262 def print_benchmark(self):
2263 """Print benchmark numbers."""
2264 print('{:<7.2f} {}'.format(self.elapsed, 'seconds elapsed'))
2265 if self.elapsed:
2266 for key in self._benchmark_keys:
2267 print('%-7d %s per second (%d total)' %
2268 (self.counters[key] / self.elapsed, key,
2269 self.counters[key]))
2272class FileReport(BaseReport):
2273 """Collect the results of the checks and print the filenames."""
2275 print_filename = True
2278class StandardReport(BaseReport):
2279 """Collect and print the results of the checks."""
2281 def __init__(self, options):
2282 super().__init__(options)
2283 self._fmt = REPORT_FORMAT.get(options.format.lower(),
2284 options.format)
2285 self._repeat = options.repeat
2286 self._show_source = options.show_source
2287 self._show_pep8 = options.show_pep8
2289 def init_file(self, filename, lines, expected, line_offset):
2290 """Signal a new file."""
2291 self._deferred_print = []
2292 return super().init_file(
2293 filename, lines, expected, line_offset)
2295 def error(self, line_number, offset, text, check):
2296 """Report an error, according to options."""
2297 code = super().error(line_number, offset, text, check)
2298 if code and (self.counters[code] == 1 or self._repeat):
2299 self._deferred_print.append(
2300 (line_number, offset, code, text[5:], check.__doc__))
2301 return code
2303 def get_file_results(self):
2304 """Print results and return the overall count for this file."""
2305 self._deferred_print.sort()
2306 for line_number, offset, code, text, doc in self._deferred_print:
2307 print(self._fmt % {
2308 'path': self.filename,
2309 'row': self.line_offset + line_number, 'col': offset + 1,
2310 'code': code, 'text': text,
2311 })
2312 if self._show_source:
2313 if line_number > len(self.lines):
2314 line = ''
2315 else:
2316 line = self.lines[line_number - 1]
2317 print(line.rstrip())
2318 print(re.sub(r'\S', ' ', line[:offset]) + '^')
2319 if self._show_pep8 and doc:
2320 print(' ' + doc.strip())
2322 # stdout is block buffered when not stdout.isatty().
2323 # line can be broken where buffer boundary since other
2324 # processes write to same file.
2325 # flush() after print() to avoid buffer boundary.
2326 # Typical buffer size is 8192. line written safely when
2327 # len(line) < 8192.
2328 sys.stdout.flush()
2329 return self.file_errors
2332class DiffReport(StandardReport):
2333 """Collect and print the results for the changed lines only."""
2335 def __init__(self, options):
2336 super().__init__(options)
2337 self._selected = options.selected_lines
2339 def error(self, line_number, offset, text, check):
2340 if line_number not in self._selected[self.filename]:
2341 return
2342 return super().error(line_number, offset, text, check)
2345class StyleGuide:
2346 """Initialize a PEP-8 instance with few options."""
2348 def __init__(self, *args, **kwargs):
2349 # build options from the command line
2350 self.checker_class = kwargs.pop('checker_class', Checker)
2351 parse_argv = kwargs.pop('parse_argv', False)
2352 config_file = kwargs.pop('config_file', False)
2353 parser = kwargs.pop('parser', None)
2354 # build options from dict
2355 options_dict = dict(*args, **kwargs)
2356 arglist = None if parse_argv else options_dict.get('paths', None)
2357 verbose = options_dict.get('verbose', None)
2358 options, self.paths = process_options(
2359 arglist, parse_argv, config_file, parser, verbose)
2360 if options_dict:
2361 options.__dict__.update(options_dict)
2362 if 'paths' in options_dict:
2363 self.paths = options_dict['paths']
2365 self.runner = self.input_file
2366 self.options = options
2368 if not options.reporter:
2369 options.reporter = BaseReport if options.quiet else StandardReport
2371 options.select = tuple(options.select or ())
2372 if not (options.select or options.ignore) and DEFAULT_IGNORE:
2373 # The default choice: ignore controversial checks
2374 options.ignore = tuple(DEFAULT_IGNORE.split(','))
2375 else:
2376 # Ignore all checks which are not explicitly selected
2377 options.ignore = ('',) if options.select else tuple(options.ignore)
2378 options.benchmark_keys = BENCHMARK_KEYS[:]
2379 options.ignore_code = self.ignore_code
2380 options.physical_checks = self.get_checks('physical_line')
2381 options.logical_checks = self.get_checks('logical_line')
2382 options.ast_checks = self.get_checks('tree')
2383 self.init_report()
2385 def init_report(self, reporter=None):
2386 """Initialize the report instance."""
2387 self.options.report = (reporter or self.options.reporter)(self.options)
2388 return self.options.report
2390 def check_files(self, paths=None):
2391 """Run all checks on the paths."""
2392 if paths is None:
2393 paths = self.paths
2394 report = self.options.report
2395 runner = self.runner
2396 report.start()
2397 try:
2398 for path in paths:
2399 if os.path.isdir(path):
2400 self.input_dir(path)
2401 elif not self.excluded(path):
2402 runner(path)
2403 except KeyboardInterrupt:
2404 print('... stopped')
2405 report.stop()
2406 return report
2408 def input_file(self, filename, lines=None, expected=None, line_offset=0):
2409 """Run all checks on a Python source file."""
2410 if self.options.verbose:
2411 print('checking %s' % filename)
2412 fchecker = self.checker_class(
2413 filename, lines=lines, options=self.options)
2414 return fchecker.check_all(expected=expected, line_offset=line_offset)
2416 def input_dir(self, dirname):
2417 """Check all files in this directory and all subdirectories."""
2418 dirname = dirname.rstrip('/')
2419 if self.excluded(dirname):
2420 return 0
2421 counters = self.options.report.counters
2422 verbose = self.options.verbose
2423 filepatterns = self.options.filename
2424 runner = self.runner
2425 for root, dirs, files in os.walk(dirname):
2426 if verbose:
2427 print('directory ' + root)
2428 counters['directories'] += 1
2429 for subdir in sorted(dirs):
2430 if self.excluded(subdir, root):
2431 dirs.remove(subdir)
2432 for filename in sorted(files):
2433 # contain a pattern that matches?
2434 if (
2435 filename_match(filename, filepatterns) and
2436 not self.excluded(filename, root)
2437 ):
2438 runner(os.path.join(root, filename))
2440 def excluded(self, filename, parent=None):
2441 """Check if the file should be excluded.
2443 Check if 'options.exclude' contains a pattern matching filename.
2444 """
2445 if not self.options.exclude:
2446 return False
2447 basename = os.path.basename(filename)
2448 if filename_match(basename, self.options.exclude):
2449 return True
2450 if parent:
2451 filename = os.path.join(parent, filename)
2452 filename = os.path.abspath(filename)
2453 return filename_match(filename, self.options.exclude)
2455 def ignore_code(self, code):
2456 """Check if the error code should be ignored.
2458 If 'options.select' contains a prefix of the error code,
2459 return False. Else, if 'options.ignore' contains a prefix of
2460 the error code, return True.
2461 """
2462 if len(code) < 4 and any(s.startswith(code)
2463 for s in self.options.select):
2464 return False
2465 return (code.startswith(self.options.ignore) and
2466 not code.startswith(self.options.select))
2468 def get_checks(self, argument_name):
2469 """Get all the checks for this category.
2471 Find all globally visible functions where the first argument
2472 name starts with argument_name and which contain selected tests.
2473 """
2474 checks = []
2475 for check, attrs in _checks[argument_name].items():
2476 (codes, args) = attrs
2477 if any(not (code and self.ignore_code(code)) for code in codes):
2478 checks.append((check.__name__, check, args))
2479 return sorted(checks)
2482def get_parser(prog='pycodestyle', version=__version__):
2483 """Create the parser for the program."""
2484 parser = OptionParser(prog=prog, version=version,
2485 usage="%prog [options] input ...")
2486 parser.config_options = [
2487 'exclude', 'filename', 'select', 'ignore', 'max-line-length',
2488 'max-doc-length', 'indent-size', 'hang-closing', 'count', 'format',
2489 'quiet', 'show-pep8', 'show-source', 'statistics', 'verbose']
2490 parser.add_option('-v', '--verbose', default=0, action='count',
2491 help="print status messages, or debug with -vv")
2492 parser.add_option('-q', '--quiet', default=0, action='count',
2493 help="report only file names, or nothing with -qq")
2494 parser.add_option('-r', '--repeat', default=True, action='store_true',
2495 help="(obsolete) show all occurrences of the same error")
2496 parser.add_option('--first', action='store_false', dest='repeat',
2497 help="show first occurrence of each error")
2498 parser.add_option('--exclude', metavar='patterns', default=DEFAULT_EXCLUDE,
2499 help="exclude files or directories which match these "
2500 "comma separated patterns (default: %default)")
2501 parser.add_option('--filename', metavar='patterns', default='*.py',
2502 help="when parsing directories, only check filenames "
2503 "matching these comma separated patterns "
2504 "(default: %default)")
2505 parser.add_option('--select', metavar='errors', default='',
2506 help="select errors and warnings (e.g. E,W6)")
2507 parser.add_option('--ignore', metavar='errors', default='',
2508 help="skip errors and warnings (e.g. E4,W) "
2509 "(default: %s)" % DEFAULT_IGNORE)
2510 parser.add_option('--show-source', action='store_true',
2511 help="show source code for each error")
2512 parser.add_option('--show-pep8', action='store_true',
2513 help="show text of PEP 8 for each error "
2514 "(implies --first)")
2515 parser.add_option('--statistics', action='store_true',
2516 help="count errors and warnings")
2517 parser.add_option('--count', action='store_true',
2518 help="print total number of errors and warnings "
2519 "to standard error and set exit code to 1 if "
2520 "total is not null")
2521 parser.add_option('--max-line-length', type='int', metavar='n',
2522 default=MAX_LINE_LENGTH,
2523 help="set maximum allowed line length "
2524 "(default: %default)")
2525 parser.add_option('--max-doc-length', type='int', metavar='n',
2526 default=None,
2527 help="set maximum allowed doc line length and perform "
2528 "these checks (unchecked if not set)")
2529 parser.add_option('--indent-size', type='int', metavar='n',
2530 default=INDENT_SIZE,
2531 help="set how many spaces make up an indent "
2532 "(default: %default)")
2533 parser.add_option('--hang-closing', action='store_true',
2534 help="hang closing bracket instead of matching "
2535 "indentation of opening bracket's line")
2536 parser.add_option('--format', metavar='format', default='default',
2537 help="set the error format [default|pylint|<custom>]")
2538 parser.add_option('--diff', action='store_true',
2539 help="report changes only within line number ranges in "
2540 "the unified diff received on STDIN")
2541 group = parser.add_option_group("Testing Options")
2542 group.add_option('--benchmark', action='store_true',
2543 help="measure processing speed")
2544 return parser
2547def read_config(options, args, arglist, parser):
2548 """Read and parse configurations.
2550 If a config file is specified on the command line with the
2551 "--config" option, then only it is used for configuration.
2553 Otherwise, the user configuration (~/.config/pycodestyle) and any
2554 local configurations in the current directory or above will be
2555 merged together (in that order) using the read method of
2556 ConfigParser.
2557 """
2558 config = configparser.RawConfigParser()
2560 cli_conf = options.config
2562 local_dir = os.curdir
2564 if USER_CONFIG and os.path.isfile(USER_CONFIG):
2565 if options.verbose:
2566 print('user configuration: %s' % USER_CONFIG)
2567 config.read(USER_CONFIG)
2569 parent = tail = args and os.path.abspath(os.path.commonpath(args))
2570 while tail:
2571 if config.read(os.path.join(parent, fn) for fn in PROJECT_CONFIG):
2572 local_dir = parent
2573 if options.verbose:
2574 print('local configuration: in %s' % parent)
2575 break
2576 (parent, tail) = os.path.split(parent)
2578 if cli_conf and os.path.isfile(cli_conf):
2579 if options.verbose:
2580 print('cli configuration: %s' % cli_conf)
2581 config.read(cli_conf)
2583 pycodestyle_section = None
2584 if config.has_section(parser.prog):
2585 pycodestyle_section = parser.prog
2586 elif config.has_section('pep8'):
2587 pycodestyle_section = 'pep8' # Deprecated
2588 warnings.warn('[pep8] section is deprecated. Use [pycodestyle].')
2590 if pycodestyle_section:
2591 option_list = {o.dest: o.type or o.action for o in parser.option_list}
2593 # First, read the default values
2594 (new_options, __) = parser.parse_args([])
2596 # Second, parse the configuration
2597 for opt in config.options(pycodestyle_section):
2598 if opt.replace('_', '-') not in parser.config_options:
2599 print(" unknown option '%s' ignored" % opt)
2600 continue
2601 if options.verbose > 1:
2602 print(" {} = {}".format(opt,
2603 config.get(pycodestyle_section, opt)))
2604 normalized_opt = opt.replace('-', '_')
2605 opt_type = option_list[normalized_opt]
2606 if opt_type in ('int', 'count'):
2607 value = config.getint(pycodestyle_section, opt)
2608 elif opt_type in ('store_true', 'store_false'):
2609 value = config.getboolean(pycodestyle_section, opt)
2610 else:
2611 value = config.get(pycodestyle_section, opt)
2612 if normalized_opt == 'exclude':
2613 value = normalize_paths(value, local_dir)
2614 setattr(new_options, normalized_opt, value)
2616 # Third, overwrite with the command-line options
2617 (options, __) = parser.parse_args(arglist, values=new_options)
2618 return options
2621def process_options(arglist=None, parse_argv=False, config_file=None,
2622 parser=None, verbose=None):
2623 """Process options passed either via arglist or command line args.
2625 Passing in the ``config_file`` parameter allows other tools, such as
2626 flake8 to specify their own options to be processed in pycodestyle.
2627 """
2628 if not parser:
2629 parser = get_parser()
2630 if not parser.has_option('--config'):
2631 group = parser.add_option_group("Configuration", description=(
2632 "The project options are read from the [%s] section of the "
2633 "tox.ini file or the setup.cfg file located in any parent folder "
2634 "of the path(s) being processed. Allowed options are: %s." %
2635 (parser.prog, ', '.join(parser.config_options))))
2636 group.add_option('--config', metavar='path', default=config_file,
2637 help="user config file location")
2638 # Don't read the command line if the module is used as a library.
2639 if not arglist and not parse_argv:
2640 arglist = []
2641 # If parse_argv is True and arglist is None, arguments are
2642 # parsed from the command line (sys.argv)
2643 (options, args) = parser.parse_args(arglist)
2644 options.reporter = None
2646 # If explicitly specified verbosity, override any `-v` CLI flag
2647 if verbose is not None:
2648 options.verbose = verbose
2650 if parse_argv and not args:
2651 if options.diff or any(os.path.exists(name)
2652 for name in PROJECT_CONFIG):
2653 args = ['.']
2654 else:
2655 parser.error('input not specified')
2656 options = read_config(options, args, arglist, parser)
2657 options.reporter = parse_argv and options.quiet == 1 and FileReport
2659 options.filename = _parse_multi_options(options.filename)
2660 options.exclude = normalize_paths(options.exclude)
2661 options.select = _parse_multi_options(options.select)
2662 options.ignore = _parse_multi_options(options.ignore)
2664 if options.diff:
2665 options.reporter = DiffReport
2666 stdin = stdin_get_value()
2667 options.selected_lines = parse_udiff(stdin, options.filename, args[0])
2668 args = sorted(options.selected_lines)
2670 return options, args
2673def _parse_multi_options(options, split_token=','):
2674 r"""Split and strip and discard empties.
2676 Turns the following:
2678 A,
2679 B,
2681 into ["A", "B"]
2682 """
2683 if options:
2684 return [o.strip() for o in options.split(split_token) if o.strip()]
2685 else:
2686 return options
2689def _main():
2690 """Parse options and run checks on Python source."""
2691 import signal
2693 # Handle "Broken pipe" gracefully
2694 try:
2695 signal.signal(signal.SIGPIPE, lambda signum, frame: sys.exit(1))
2696 except AttributeError:
2697 pass # not supported on Windows
2699 style_guide = StyleGuide(parse_argv=True)
2700 options = style_guide.options
2702 report = style_guide.check_files()
2704 if options.statistics:
2705 report.print_statistics()
2707 if options.benchmark:
2708 report.print_benchmark()
2710 if report.total_errors:
2711 if options.count:
2712 sys.stderr.write(str(report.total_errors) + '\n')
2713 sys.exit(1)
2716if __name__ == '__main__':
2717 _main()