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