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