Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pycodestyle.py: 69%

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

1364 statements  

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. 

30 

31For usage and a list of options, try this: 

32$ python pycodestyle.py -h 

33 

34This program and its regression test suite live here: 

35https://github.com/pycqa/pycodestyle 

36 

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 

63 

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 

70 

71__version__ = '2.14.0' 

72 

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 

85 

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} 

101 

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'] 

118 

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*:") 

153 

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 

160 

161if sys.version_info >= (3, 14): # pragma: >=3.14 cover 

162 TSTRING_START = tokenize.TSTRING_START 

163 TSTRING_MIDDLE = tokenize.TSTRING_MIDDLE 

164 TSTRING_END = tokenize.TSTRING_END 

165else: # pragma: <3.14 cover 

166 TSTRING_START = TSTRING_MIDDLE = TSTRING_END = -1 

167 

168_checks = {'physical_line': {}, 'logical_line': {}, 'tree': {}} 

169 

170 

171def _get_parameters(function): 

172 return [parameter.name 

173 for parameter 

174 in inspect.signature(function).parameters.values() 

175 if parameter.kind == parameter.POSITIONAL_OR_KEYWORD] 

176 

177 

178def register_check(check, codes=None): 

179 """Register a new check object.""" 

180 def _add_check(check, kind, codes, args): 

181 if check in _checks[kind]: 

182 _checks[kind][check][0].extend(codes or []) 

183 else: 

184 _checks[kind][check] = (codes or [''], args) 

185 if inspect.isfunction(check): 

186 args = _get_parameters(check) 

187 if args and args[0] in ('physical_line', 'logical_line'): 

188 if codes is None: 

189 codes = ERRORCODE_REGEX.findall(check.__doc__ or '') 

190 _add_check(check, args[0], codes, args) 

191 elif inspect.isclass(check): 

192 if _get_parameters(check.__init__)[:2] == ['self', 'tree']: 

193 _add_check(check, 'tree', codes, None) 

194 return check 

195 

196 

197######################################################################## 

198# Plugins (check functions) for physical lines 

199######################################################################## 

200 

201@register_check 

202def tabs_or_spaces(physical_line, indent_char): 

203 r"""Never mix tabs and spaces. 

204 

205 The most popular way of indenting Python is with spaces only. The 

206 second-most popular way is with tabs only. Code indented with a 

207 mixture of tabs and spaces should be converted to using spaces 

208 exclusively. When invoking the Python command line interpreter with 

209 the -t option, it issues warnings about code that illegally mixes 

210 tabs and spaces. When using -tt these warnings become errors. 

211 These options are highly recommended! 

212 

213 Okay: if a == 0:\n a = 1\n b = 1 

214 """ 

215 indent = INDENT_REGEX.match(physical_line).group(1) 

216 for offset, char in enumerate(indent): 

217 if char != indent_char: 

218 return offset, "E101 indentation contains mixed spaces and tabs" 

219 

220 

221@register_check 

222def tabs_obsolete(physical_line): 

223 r"""On new projects, spaces-only are strongly recommended over tabs. 

224 

225 Okay: if True:\n return 

226 W191: if True:\n\treturn 

227 """ 

228 indent = INDENT_REGEX.match(physical_line).group(1) 

229 if '\t' in indent: 

230 return indent.index('\t'), "W191 indentation contains tabs" 

231 

232 

233@register_check 

234def trailing_whitespace(physical_line): 

235 r"""Trailing whitespace is superfluous. 

236 

237 The warning returned varies on whether the line itself is blank, 

238 for easier filtering for those who want to indent their blank lines. 

239 

240 Okay: spam(1)\n# 

241 W291: spam(1) \n# 

242 W293: class Foo(object):\n \n bang = 12 

243 """ 

244 # Strip these trailing characters: 

245 # - chr(10), newline 

246 # - chr(13), carriage return 

247 # - chr(12), form feed, ^L 

248 physical_line = physical_line.rstrip('\n\r\x0c') 

249 stripped = physical_line.rstrip(' \t\v') 

250 if physical_line != stripped: 

251 if stripped: 

252 return len(stripped), "W291 trailing whitespace" 

253 else: 

254 return 0, "W293 blank line contains whitespace" 

255 

256 

257@register_check 

258def trailing_blank_lines(physical_line, lines, line_number, total_lines): 

259 r"""Trailing blank lines are superfluous. 

260 

261 Okay: spam(1) 

262 W391: spam(1)\n 

263 

264 However the last line should end with a new line (warning W292). 

265 """ 

266 if line_number == total_lines: 

267 stripped_last_line = physical_line.rstrip('\r\n') 

268 if physical_line and not stripped_last_line: 

269 return 0, "W391 blank line at end of file" 

270 if stripped_last_line == physical_line: 

271 return len(lines[-1]), "W292 no newline at end of file" 

272 

273 

274@register_check 

275def maximum_line_length(physical_line, max_line_length, multiline, 

276 line_number, noqa): 

277 r"""Limit all lines to a maximum of 79 characters. 

278 

279 There are still many devices around that are limited to 80 character 

280 lines; plus, limiting windows to 80 characters makes it possible to 

281 have several windows side-by-side. The default wrapping on such 

282 devices looks ugly. Therefore, please limit all lines to a maximum 

283 of 79 characters. For flowing long blocks of text (docstrings or 

284 comments), limiting the length to 72 characters is recommended. 

285 

286 Reports error E501. 

287 """ 

288 line = physical_line.rstrip() 

289 length = len(line) 

290 if length > max_line_length and not noqa: 

291 # Special case: ignore long shebang lines. 

292 if line_number == 1 and line.startswith('#!'): 

293 return 

294 # Special case for long URLs in multi-line docstrings or 

295 # comments, but still report the error when the 72 first chars 

296 # are whitespaces. 

297 chunks = line.split() 

298 if ((len(chunks) == 1 and multiline) or 

299 (len(chunks) == 2 and chunks[0] == '#')) and \ 

300 len(line) - len(chunks[-1]) < max_line_length - 7: 

301 return 

302 if length > max_line_length: 

303 return (max_line_length, "E501 line too long " 

304 "(%d > %d characters)" % (length, max_line_length)) 

305 

306 

307######################################################################## 

308# Plugins (check functions) for logical lines 

309######################################################################## 

310 

311 

312def _is_one_liner(logical_line, indent_level, lines, line_number): 

313 if not STARTSWITH_TOP_LEVEL_REGEX.match(logical_line): 

314 return False 

315 

316 line_idx = line_number - 1 

317 

318 if line_idx < 1: 

319 prev_indent = 0 

320 else: 

321 prev_indent = expand_indent(lines[line_idx - 1]) 

322 

323 if prev_indent > indent_level: 

324 return False 

325 

326 while line_idx < len(lines): 

327 line = lines[line_idx].strip() 

328 if not line.startswith('@') and STARTSWITH_TOP_LEVEL_REGEX.match(line): 

329 break 

330 else: 

331 line_idx += 1 

332 else: 

333 return False # invalid syntax: EOF while searching for def/class 

334 

335 next_idx = line_idx + 1 

336 while next_idx < len(lines): 

337 if lines[next_idx].strip(): 

338 break 

339 else: 

340 next_idx += 1 

341 else: 

342 return True # line is last in the file 

343 

344 return expand_indent(lines[next_idx]) <= indent_level 

345 

346 

347@register_check 

348def blank_lines(logical_line, blank_lines, indent_level, line_number, 

349 blank_before, previous_logical, 

350 previous_unindented_logical_line, previous_indent_level, 

351 lines): 

352 r"""Separate top-level function and class definitions with two blank 

353 lines. 

354 

355 Method definitions inside a class are separated by a single blank 

356 line. 

357 

358 Extra blank lines may be used (sparingly) to separate groups of 

359 related functions. Blank lines may be omitted between a bunch of 

360 related one-liners (e.g. a set of dummy implementations). 

361 

362 Use blank lines in functions, sparingly, to indicate logical 

363 sections. 

364 

365 Okay: def a():\n pass\n\n\ndef b():\n pass 

366 Okay: def a():\n pass\n\n\nasync def b():\n pass 

367 Okay: def a():\n pass\n\n\n# Foo\n# Bar\n\ndef b():\n pass 

368 Okay: default = 1\nfoo = 1 

369 Okay: classify = 1\nfoo = 1 

370 

371 E301: class Foo:\n b = 0\n def bar():\n pass 

372 E302: def a():\n pass\n\ndef b(n):\n pass 

373 E302: def a():\n pass\n\nasync def b(n):\n pass 

374 E303: def a():\n pass\n\n\n\ndef b(n):\n pass 

375 E303: def a():\n\n\n\n pass 

376 E304: @decorator\n\ndef a():\n pass 

377 E305: def a():\n pass\na() 

378 E306: def a():\n def b():\n pass\n def c():\n pass 

379 """ # noqa 

380 top_level_lines = BLANK_LINES_CONFIG['top_level'] 

381 method_lines = BLANK_LINES_CONFIG['method'] 

382 

383 if not previous_logical and blank_before < top_level_lines: 

384 return # Don't expect blank lines before the first line 

385 if previous_logical.startswith('@'): 

386 if blank_lines: 

387 yield 0, "E304 blank lines found after function decorator" 

388 elif (blank_lines > top_level_lines or 

389 (indent_level and blank_lines == method_lines + 1) 

390 ): 

391 yield 0, "E303 too many blank lines (%d)" % blank_lines 

392 elif STARTSWITH_TOP_LEVEL_REGEX.match(logical_line): 

393 # allow a group of one-liners 

394 if ( 

395 _is_one_liner(logical_line, indent_level, lines, line_number) and 

396 blank_before == 0 

397 ): 

398 return 

399 if indent_level: 

400 if not (blank_before == method_lines or 

401 previous_indent_level < indent_level or 

402 DOCSTRING_REGEX.match(previous_logical) 

403 ): 

404 ancestor_level = indent_level 

405 nested = False 

406 # Search backwards for a def ancestor or tree root 

407 # (top level). 

408 for line in lines[line_number - top_level_lines::-1]: 

409 if line.strip() and expand_indent(line) < ancestor_level: 

410 ancestor_level = expand_indent(line) 

411 nested = STARTSWITH_DEF_REGEX.match(line.lstrip()) 

412 if nested or ancestor_level == 0: 

413 break 

414 if nested: 

415 yield 0, "E306 expected %s blank line before a " \ 

416 "nested definition, found 0" % (method_lines,) 

417 else: 

418 yield 0, "E301 expected {} blank line, found 0".format( 

419 method_lines) 

420 elif blank_before != top_level_lines: 

421 yield 0, "E302 expected %s blank lines, found %d" % ( 

422 top_level_lines, blank_before) 

423 elif (logical_line and 

424 not indent_level and 

425 blank_before != top_level_lines and 

426 previous_unindented_logical_line.startswith(('def ', 'class ')) 

427 ): 

428 yield 0, "E305 expected %s blank lines after " \ 

429 "class or function definition, found %d" % ( 

430 top_level_lines, blank_before) 

431 

432 

433@register_check 

434def extraneous_whitespace(logical_line): 

435 r"""Avoid extraneous whitespace. 

436 

437 Avoid extraneous whitespace in these situations: 

438 - Immediately inside parentheses, brackets or braces. 

439 - Immediately before a comma, semicolon, or colon. 

440 

441 Okay: spam(ham[1], {eggs: 2}) 

442 E201: spam( ham[1], {eggs: 2}) 

443 E201: spam(ham[ 1], {eggs: 2}) 

444 E201: spam(ham[1], { eggs: 2}) 

445 E202: spam(ham[1], {eggs: 2} ) 

446 E202: spam(ham[1 ], {eggs: 2}) 

447 E202: spam(ham[1], {eggs: 2 }) 

448 

449 E203: if x == 4: print x, y; x, y = y , x 

450 E203: if x == 4: print x, y ; x, y = y, x 

451 E203: if x == 4 : print x, y; x, y = y, x 

452 

453 Okay: @decorator 

454 E204: @ decorator 

455 """ 

456 line = logical_line 

457 for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line): 

458 text = match.group() 

459 char = text.strip() 

460 found = match.start() 

461 if text[-1].isspace(): 

462 # assert char in '([{' 

463 yield found + 1, "E201 whitespace after '%s'" % char 

464 elif line[found - 1] != ',': 

465 code = ('E202' if char in '}])' else 'E203') # if char in ',;:' 

466 yield found, f"{code} whitespace before '{char}'" 

467 

468 if WHITESPACE_AFTER_DECORATOR_REGEX.match(logical_line): 

469 yield 1, "E204 whitespace after decorator '@'" 

470 

471 

472@register_check 

473def whitespace_around_keywords(logical_line): 

474 r"""Avoid extraneous whitespace around keywords. 

475 

476 Okay: True and False 

477 E271: True and False 

478 E272: True and False 

479 E273: True and\tFalse 

480 E274: True\tand False 

481 """ 

482 for match in KEYWORD_REGEX.finditer(logical_line): 

483 before, after = match.groups() 

484 

485 if '\t' in before: 

486 yield match.start(1), "E274 tab before keyword" 

487 elif len(before) > 1: 

488 yield match.start(1), "E272 multiple spaces before keyword" 

489 

490 if '\t' in after: 

491 yield match.start(2), "E273 tab after keyword" 

492 elif len(after) > 1: 

493 yield match.start(2), "E271 multiple spaces after keyword" 

494 

495 

496@register_check 

497def missing_whitespace_after_keyword(logical_line, tokens): 

498 r"""Keywords should be followed by whitespace. 

499 

500 Okay: from foo import (bar, baz) 

501 E275: from foo import(bar, baz) 

502 E275: from importable.module import(bar, baz) 

503 E275: if(foo): bar 

504 """ 

505 for tok0, tok1 in zip(tokens, tokens[1:]): 

506 # This must exclude the True/False/None singletons, which can 

507 # appear e.g. as "if x is None:", and async/await, which were 

508 # valid identifier names in old Python versions. 

509 if (tok0.end == tok1.start and 

510 tok0.type == tokenize.NAME and 

511 keyword.iskeyword(tok0.string) and 

512 tok0.string not in SINGLETONS and 

513 not (tok0.string == 'except' and tok1.string == '*') and 

514 not (tok0.string == 'yield' and tok1.string == ')') and 

515 tok1.string not in ':\n'): 

516 yield tok0.end, "E275 missing whitespace after keyword" 

517 

518 

519@register_check 

520def indentation(logical_line, previous_logical, indent_char, 

521 indent_level, previous_indent_level, 

522 indent_size): 

523 r"""Use indent_size (PEP8 says 4) spaces per indentation level. 

524 

525 For really old code that you don't want to mess up, you can continue 

526 to use 8-space tabs. 

527 

528 Okay: a = 1 

529 Okay: if a == 0:\n a = 1 

530 E111: a = 1 

531 E114: # a = 1 

532 

533 Okay: for item in items:\n pass 

534 E112: for item in items:\npass 

535 E115: for item in items:\n# Hi\n pass 

536 

537 Okay: a = 1\nb = 2 

538 E113: a = 1\n b = 2 

539 E116: a = 1\n # b = 2 

540 """ 

541 c = 0 if logical_line else 3 

542 tmpl = "E11%d %s" if logical_line else "E11%d %s (comment)" 

543 if indent_level % indent_size: 

544 yield 0, tmpl % ( 

545 1 + c, 

546 "indentation is not a multiple of " + str(indent_size), 

547 ) 

548 indent_expect = previous_logical.endswith(':') 

549 if indent_expect and indent_level <= previous_indent_level: 

550 yield 0, tmpl % (2 + c, "expected an indented block") 

551 elif not indent_expect and indent_level > previous_indent_level: 

552 yield 0, tmpl % (3 + c, "unexpected indentation") 

553 

554 if indent_expect: 

555 expected_indent_amount = 8 if indent_char == '\t' else 4 

556 expected_indent_level = previous_indent_level + expected_indent_amount 

557 if indent_level > expected_indent_level: 

558 yield 0, tmpl % (7, 'over-indented') 

559 

560 

561@register_check 

562def continued_indentation(logical_line, tokens, indent_level, hang_closing, 

563 indent_char, indent_size, noqa, verbose): 

564 r"""Continuation lines indentation. 

565 

566 Continuation lines should align wrapped elements either vertically 

567 using Python's implicit line joining inside parentheses, brackets 

568 and braces, or using a hanging indent. 

569 

570 When using a hanging indent these considerations should be applied: 

571 - there should be no arguments on the first line, and 

572 - further indentation should be used to clearly distinguish itself 

573 as a continuation line. 

574 

575 Okay: a = (\n) 

576 E123: a = (\n ) 

577 

578 Okay: a = (\n 42) 

579 E121: a = (\n 42) 

580 E122: a = (\n42) 

581 E123: a = (\n 42\n ) 

582 E124: a = (24,\n 42\n) 

583 E125: if (\n b):\n pass 

584 E126: a = (\n 42) 

585 E127: a = (24,\n 42) 

586 E128: a = (24,\n 42) 

587 E129: if (a or\n b):\n pass 

588 E131: a = (\n 42\n 24) 

589 """ 

590 first_row = tokens[0][2][0] 

591 nrows = 1 + tokens[-1][2][0] - first_row 

592 if noqa or nrows == 1: 

593 return 

594 

595 # indent_next tells us whether the next block is indented; assuming 

596 # that it is indented by 4 spaces, then we should not allow 4-space 

597 # indents on the final continuation line; in turn, some other 

598 # indents are allowed to have an extra 4 spaces. 

599 indent_next = logical_line.endswith(':') 

600 

601 row = depth = 0 

602 valid_hangs = (indent_size,) if indent_char != '\t' \ 

603 else (indent_size, indent_size * 2) 

604 # remember how many brackets were opened on each line 

605 parens = [0] * nrows 

606 # relative indents of physical lines 

607 rel_indent = [0] * nrows 

608 # for each depth, collect a list of opening rows 

609 open_rows = [[0]] 

610 # for each depth, memorize the hanging indentation 

611 hangs = [None] 

612 # visual indents 

613 indent_chances = {} 

614 last_indent = tokens[0][2] 

615 visual_indent = None 

616 last_token_multiline = False 

617 # for each depth, memorize the visual indent column 

618 indent = [last_indent[1]] 

619 if verbose >= 3: 

620 print(">>> " + tokens[0][4].rstrip()) 

621 

622 for token_type, text, start, end, line in tokens: 

623 

624 newline = row < start[0] - first_row 

625 if newline: 

626 row = start[0] - first_row 

627 newline = not last_token_multiline and token_type not in NEWLINE 

628 

629 if newline: 

630 # this is the beginning of a continuation line. 

631 last_indent = start 

632 if verbose >= 3: 

633 print("... " + line.rstrip()) 

634 

635 # record the initial indent. 

636 rel_indent[row] = expand_indent(line) - indent_level 

637 

638 # identify closing bracket 

639 close_bracket = (token_type == tokenize.OP and text in ']})') 

640 

641 # is the indent relative to an opening bracket line? 

642 for open_row in reversed(open_rows[depth]): 

643 hang = rel_indent[row] - rel_indent[open_row] 

644 hanging_indent = hang in valid_hangs 

645 if hanging_indent: 

646 break 

647 if hangs[depth]: 

648 hanging_indent = (hang == hangs[depth]) 

649 # is there any chance of visual indent? 

650 visual_indent = (not close_bracket and hang > 0 and 

651 indent_chances.get(start[1])) 

652 

653 if close_bracket and indent[depth]: 

654 # closing bracket for visual indent 

655 if start[1] != indent[depth]: 

656 yield (start, "E124 closing bracket does not match " 

657 "visual indentation") 

658 elif close_bracket and not hang: 

659 # closing bracket matches indentation of opening 

660 # bracket's line 

661 if hang_closing: 

662 yield start, "E133 closing bracket is missing indentation" 

663 elif indent[depth] and start[1] < indent[depth]: 

664 if visual_indent is not True: 

665 # visual indent is broken 

666 yield (start, "E128 continuation line " 

667 "under-indented for visual indent") 

668 elif hanging_indent or (indent_next and 

669 rel_indent[row] == 2 * indent_size): 

670 # hanging indent is verified 

671 if close_bracket and not hang_closing: 

672 yield (start, "E123 closing bracket does not match " 

673 "indentation of opening bracket's line") 

674 hangs[depth] = hang 

675 elif visual_indent is True: 

676 # visual indent is verified 

677 indent[depth] = start[1] 

678 elif visual_indent in (text, str): 

679 # ignore token lined up with matching one from a 

680 # previous line 

681 pass 

682 else: 

683 # indent is broken 

684 if hang <= 0: 

685 error = "E122", "missing indentation or outdented" 

686 elif indent[depth]: 

687 error = "E127", "over-indented for visual indent" 

688 elif not close_bracket and hangs[depth]: 

689 error = "E131", "unaligned for hanging indent" 

690 else: 

691 hangs[depth] = hang 

692 if hang > indent_size: 

693 error = "E126", "over-indented for hanging indent" 

694 else: 

695 error = "E121", "under-indented for hanging indent" 

696 yield start, "%s continuation line %s" % error 

697 

698 # look for visual indenting 

699 if (parens[row] and 

700 token_type not in (tokenize.NL, tokenize.COMMENT) and 

701 not indent[depth]): 

702 indent[depth] = start[1] 

703 indent_chances[start[1]] = True 

704 if verbose >= 4: 

705 print(f"bracket depth {depth} indent to {start[1]}") 

706 # deal with implicit string concatenation 

707 elif token_type in { 

708 tokenize.STRING, 

709 tokenize.COMMENT, 

710 FSTRING_START, 

711 TSTRING_START 

712 }: 

713 indent_chances[start[1]] = str 

714 # visual indent after assert/raise/with 

715 elif not row and not depth and text in ["assert", "raise", "with"]: 

716 indent_chances[end[1] + 1] = True 

717 # special case for the "if" statement because len("if (") == 4 

718 elif not indent_chances and not row and not depth and text == 'if': 

719 indent_chances[end[1] + 1] = True 

720 elif text == ':' and line[end[1]:].isspace(): 

721 open_rows[depth].append(row) 

722 

723 # keep track of bracket depth 

724 if token_type == tokenize.OP: 

725 if text in '([{': 

726 depth += 1 

727 indent.append(0) 

728 hangs.append(None) 

729 if len(open_rows) == depth: 

730 open_rows.append([]) 

731 open_rows[depth].append(row) 

732 parens[row] += 1 

733 if verbose >= 4: 

734 print("bracket depth %s seen, col %s, visual min = %s" % 

735 (depth, start[1], indent[depth])) 

736 elif text in ')]}' and depth > 0: 

737 # parent indents should not be more than this one 

738 prev_indent = indent.pop() or last_indent[1] 

739 hangs.pop() 

740 for d in range(depth): 

741 if indent[d] > prev_indent: 

742 indent[d] = 0 

743 for ind in list(indent_chances): 

744 if ind >= prev_indent: 

745 del indent_chances[ind] 

746 del open_rows[depth + 1:] 

747 depth -= 1 

748 if depth: 

749 indent_chances[indent[depth]] = True 

750 for idx in range(row, -1, -1): 

751 if parens[idx]: 

752 parens[idx] -= 1 

753 break 

754 assert len(indent) == depth + 1 

755 if start[1] not in indent_chances: 

756 # allow lining up tokens 

757 indent_chances[start[1]] = text 

758 

759 last_token_multiline = (start[0] != end[0]) 

760 if last_token_multiline: 

761 rel_indent[end[0] - first_row] = rel_indent[row] 

762 

763 if indent_next and expand_indent(line) == indent_level + indent_size: 

764 pos = (start[0], indent[0] + indent_size) 

765 if visual_indent: 

766 code = "E129 visually indented line" 

767 else: 

768 code = "E125 continuation line" 

769 yield pos, "%s with same indent as next logical line" % code 

770 

771 

772@register_check 

773def whitespace_before_parameters(logical_line, tokens): 

774 r"""Avoid extraneous whitespace. 

775 

776 Avoid extraneous whitespace in the following situations: 

777 - before the open parenthesis that starts the argument list of a 

778 function call. 

779 - before the open parenthesis that starts an indexing or slicing. 

780 

781 Okay: spam(1) 

782 E211: spam (1) 

783 

784 Okay: dict['key'] = list[index] 

785 E211: dict ['key'] = list[index] 

786 E211: dict['key'] = list [index] 

787 """ 

788 prev_type, prev_text, __, prev_end, __ = tokens[0] 

789 for index in range(1, len(tokens)): 

790 token_type, text, start, end, __ = tokens[index] 

791 if ( 

792 token_type == tokenize.OP and 

793 text in '([' and 

794 start != prev_end and 

795 (prev_type == tokenize.NAME or prev_text in '}])') and 

796 # Syntax "class A (B):" is allowed, but avoid it 

797 (index < 2 or tokens[index - 2][1] != 'class') and 

798 # Allow "return (a.foo for a in range(5))" 

799 not keyword.iskeyword(prev_text) and 

800 ( 

801 # 3.12+: type is a soft keyword but no braces after 

802 prev_text == 'type' or 

803 not keyword.issoftkeyword(prev_text) 

804 ) 

805 ): 

806 yield prev_end, "E211 whitespace before '%s'" % text 

807 prev_type = token_type 

808 prev_text = text 

809 prev_end = end 

810 

811 

812@register_check 

813def whitespace_around_operator(logical_line): 

814 r"""Avoid extraneous whitespace around an operator. 

815 

816 Okay: a = 12 + 3 

817 E221: a = 4 + 5 

818 E222: a = 4 + 5 

819 E223: a = 4\t+ 5 

820 E224: a = 4 +\t5 

821 """ 

822 for match in OPERATOR_REGEX.finditer(logical_line): 

823 before, after = match.groups() 

824 

825 if '\t' in before: 

826 yield match.start(1), "E223 tab before operator" 

827 elif len(before) > 1: 

828 yield match.start(1), "E221 multiple spaces before operator" 

829 

830 if '\t' in after: 

831 yield match.start(2), "E224 tab after operator" 

832 elif len(after) > 1: 

833 yield match.start(2), "E222 multiple spaces after operator" 

834 

835 

836@register_check 

837def missing_whitespace(logical_line, tokens): 

838 r"""Surround operators with the correct amount of whitespace. 

839 

840 - Always surround these binary operators with a single space on 

841 either side: assignment (=), augmented assignment (+=, -= etc.), 

842 comparisons (==, <, >, !=, <=, >=, in, not in, is, is not), 

843 Booleans (and, or, not). 

844 

845 - Each comma, semicolon or colon should be followed by whitespace. 

846 

847 - If operators with different priorities are used, consider adding 

848 whitespace around the operators with the lowest priorities. 

849 

850 Okay: i = i + 1 

851 Okay: submitted += 1 

852 Okay: x = x * 2 - 1 

853 Okay: hypot2 = x * x + y * y 

854 Okay: c = (a + b) * (a - b) 

855 Okay: foo(bar, key='word', *args, **kwargs) 

856 Okay: alpha[:-i] 

857 Okay: [a, b] 

858 Okay: (3,) 

859 Okay: a[3,] = 1 

860 Okay: a[1:4] 

861 Okay: a[:4] 

862 Okay: a[1:] 

863 Okay: a[1:4:2] 

864 

865 E225: i=i+1 

866 E225: submitted +=1 

867 E225: x = x /2 - 1 

868 E225: z = x **y 

869 E225: z = 1and 1 

870 E226: c = (a+b) * (a-b) 

871 E226: hypot2 = x*x + y*y 

872 E227: c = a|b 

873 E228: msg = fmt%(errno, errmsg) 

874 E231: ['a','b'] 

875 E231: foo(bar,baz) 

876 E231: [{'a':'b'}] 

877 """ 

878 need_space = False 

879 prev_type = tokenize.OP 

880 prev_text = prev_end = None 

881 operator_types = (tokenize.OP, tokenize.NAME) 

882 brace_stack = [] 

883 for token_type, text, start, end, line in tokens: 

884 if token_type == tokenize.OP and text in {'[', '(', '{'}: 

885 brace_stack.append(text) 

886 elif token_type == FSTRING_START: # pragma: >=3.12 cover 

887 brace_stack.append('f') 

888 elif token_type == TSTRING_START: # pragma: >=3.14 cover 

889 brace_stack.append('t') 

890 elif token_type == tokenize.NAME and text == 'lambda': 

891 brace_stack.append('l') 

892 elif brace_stack: 

893 if token_type == tokenize.OP and text in {']', ')', '}'}: 

894 brace_stack.pop() 

895 elif token_type == FSTRING_END: # pragma: >=3.12 cover 

896 brace_stack.pop() 

897 elif token_type == TSTRING_END: # pragma: >=3.14 cover 

898 brace_stack.pop() 

899 elif ( 

900 brace_stack[-1] == 'l' and 

901 token_type == tokenize.OP and 

902 text == ':' 

903 ): 

904 brace_stack.pop() 

905 

906 if token_type in SKIP_COMMENTS: 

907 continue 

908 

909 if token_type == tokenize.OP and text in {',', ';', ':'}: 

910 next_char = line[end[1]:end[1] + 1] 

911 if next_char not in WHITESPACE and next_char not in '\r\n': 

912 # slice 

913 if text == ':' and brace_stack[-1:] == ['[']: 

914 pass 

915 # 3.12+ fstring format specifier 

916 elif text == ':' and brace_stack[-2:] == ['f', '{']: # pragma: >=3.12 cover # noqa: E501 

917 pass 

918 # 3.14+ tstring format specifier 

919 elif text == ':' and brace_stack[-2:] == ['t', '{']: # pragma: >=3.14 cover # noqa: E501 

920 pass 

921 # tuple (and list for some reason?) 

922 elif text == ',' and next_char in ')]': 

923 pass 

924 else: 

925 yield start, f'E231 missing whitespace after {text!r}' 

926 

927 if need_space: 

928 if start != prev_end: 

929 # Found a (probably) needed space 

930 if need_space is not True and not need_space[1]: 

931 yield (need_space[0], 

932 "E225 missing whitespace around operator") 

933 need_space = False 

934 elif ( 

935 # def f(a, /, b): 

936 # ^ 

937 # def f(a, b, /): 

938 # ^ 

939 # f = lambda a, /: 

940 # ^ 

941 prev_text == '/' and text in {',', ')', ':'} or 

942 # def f(a, b, /): 

943 # ^ 

944 prev_text == ')' and text == ':' 

945 ): 

946 # Tolerate the "/" operator in function definition 

947 # For more info see PEP570 

948 pass 

949 else: 

950 if need_space is True or need_space[1]: 

951 # A needed trailing space was not found 

952 yield prev_end, "E225 missing whitespace around operator" 

953 elif prev_text != '**': 

954 code, optype = 'E226', 'arithmetic' 

955 if prev_text == '%': 

956 code, optype = 'E228', 'modulo' 

957 elif prev_text not in ARITHMETIC_OP: 

958 code, optype = 'E227', 'bitwise or shift' 

959 yield (need_space[0], "%s missing whitespace " 

960 "around %s operator" % (code, optype)) 

961 need_space = False 

962 elif token_type in operator_types and prev_end is not None: 

963 if ( 

964 text == '=' and ( 

965 # allow lambda default args: lambda x=None: None 

966 brace_stack[-1:] == ['l'] or 

967 # allow keyword args or defaults: foo(bar=None). 

968 brace_stack[-1:] == ['('] or 

969 # allow python 3.8 fstring repr specifier 

970 brace_stack[-2:] == ['f', '{'] or 

971 # allow python 3.8 fstring repr specifier 

972 brace_stack[-2:] == ['t', '{'] 

973 ) 

974 ): 

975 pass 

976 elif text in WS_NEEDED_OPERATORS: 

977 need_space = True 

978 elif text in UNARY_OPERATORS: 

979 # Check if the operator is used as a binary operator 

980 # Allow unary operators: -123, -x, +1. 

981 # Allow argument unpacking: foo(*args, **kwargs). 

982 if prev_type == tokenize.OP and prev_text in '}])' or ( 

983 prev_type != tokenize.OP and 

984 prev_text not in KEYWORDS and 

985 not keyword.issoftkeyword(prev_text) 

986 ): 

987 need_space = None 

988 elif text in WS_OPTIONAL_OPERATORS: 

989 need_space = None 

990 

991 if need_space is None: 

992 # Surrounding space is optional, but ensure that 

993 # trailing space matches opening space 

994 need_space = (prev_end, start != prev_end) 

995 elif need_space and start == prev_end: 

996 # A needed opening space was not found 

997 yield prev_end, "E225 missing whitespace around operator" 

998 need_space = False 

999 prev_type = token_type 

1000 prev_text = text 

1001 prev_end = end 

1002 

1003 

1004@register_check 

1005def whitespace_around_comma(logical_line): 

1006 r"""Avoid extraneous whitespace after a comma or a colon. 

1007 

1008 Note: these checks are disabled by default 

1009 

1010 Okay: a = (1, 2) 

1011 E241: a = (1, 2) 

1012 E242: a = (1,\t2) 

1013 """ 

1014 line = logical_line 

1015 for m in WHITESPACE_AFTER_COMMA_REGEX.finditer(line): 

1016 found = m.start() + 1 

1017 if '\t' in m.group(): 

1018 yield found, "E242 tab after '%s'" % m.group()[0] 

1019 else: 

1020 yield found, "E241 multiple spaces after '%s'" % m.group()[0] 

1021 

1022 

1023@register_check 

1024def whitespace_around_named_parameter_equals(logical_line, tokens): 

1025 r"""Don't use spaces around the '=' sign in function arguments. 

1026 

1027 Don't use spaces around the '=' sign when used to indicate a 

1028 keyword argument or a default parameter value, except when 

1029 using a type annotation. 

1030 

1031 Okay: def complex(real, imag=0.0): 

1032 Okay: return magic(r=real, i=imag) 

1033 Okay: boolean(a == b) 

1034 Okay: boolean(a != b) 

1035 Okay: boolean(a <= b) 

1036 Okay: boolean(a >= b) 

1037 Okay: def foo(arg: int = 42): 

1038 Okay: async def foo(arg: int = 42): 

1039 

1040 E251: def complex(real, imag = 0.0): 

1041 E251: return magic(r = real, i = imag) 

1042 E252: def complex(real, image: float=0.0): 

1043 """ 

1044 paren_stack = [] 

1045 no_space = False 

1046 require_space = False 

1047 prev_end = None 

1048 annotated_func_arg = False 

1049 in_def = bool(STARTSWITH_DEF_REGEX.match(logical_line)) 

1050 in_generic = bool(STARTSWITH_GENERIC_REGEX.match(logical_line)) 

1051 

1052 message = "E251 unexpected spaces around keyword / parameter equals" 

1053 missing_message = "E252 missing whitespace around parameter equals" 

1054 

1055 for token_type, text, start, end, line in tokens: 

1056 if token_type == tokenize.NL: 

1057 continue 

1058 if no_space: 

1059 no_space = False 

1060 if start != prev_end: 

1061 yield (prev_end, message) 

1062 if require_space: 

1063 require_space = False 

1064 if start == prev_end: 

1065 yield (prev_end, missing_message) 

1066 if token_type == tokenize.OP: 

1067 if text in '([': 

1068 paren_stack.append(text) 

1069 elif text in ')]' and paren_stack: 

1070 paren_stack.pop() 

1071 # def f(arg: tp = default): ... 

1072 elif text == ':' and in_def and paren_stack == ['(']: 

1073 annotated_func_arg = True 

1074 elif len(paren_stack) == 1 and text == ',': 

1075 annotated_func_arg = False 

1076 elif paren_stack and text == '=': 

1077 if ( 

1078 # PEP 696 defaults always use spaced-style `=` 

1079 # type A[T = default] = ... 

1080 # def f[T = default](): ... 

1081 # class C[T = default](): ... 

1082 (in_generic and paren_stack == ['[']) or 

1083 (annotated_func_arg and paren_stack == ['(']) 

1084 ): 

1085 require_space = True 

1086 if start == prev_end: 

1087 yield (prev_end, missing_message) 

1088 else: 

1089 no_space = True 

1090 if start != prev_end: 

1091 yield (prev_end, message) 

1092 if not paren_stack: 

1093 annotated_func_arg = False 

1094 

1095 prev_end = end 

1096 

1097 

1098@register_check 

1099def whitespace_before_comment(logical_line, tokens): 

1100 """Separate inline comments by at least two spaces. 

1101 

1102 An inline comment is a comment on the same line as a statement. 

1103 Inline comments should be separated by at least two spaces from the 

1104 statement. They should start with a # and a single space. 

1105 

1106 Each line of a block comment starts with a # and one or multiple 

1107 spaces as there can be indented text inside the comment. 

1108 

1109 Okay: x = x + 1 # Increment x 

1110 Okay: x = x + 1 # Increment x 

1111 Okay: # Block comments: 

1112 Okay: # - Block comment list 

1113 Okay: # \xa0- Block comment list 

1114 E261: x = x + 1 # Increment x 

1115 E262: x = x + 1 #Increment x 

1116 E262: x = x + 1 # Increment x 

1117 E262: x = x + 1 # \xa0Increment x 

1118 E265: #Block comment 

1119 E266: ### Block comment 

1120 """ 

1121 prev_end = (0, 0) 

1122 for token_type, text, start, end, line in tokens: 

1123 if token_type == tokenize.COMMENT: 

1124 inline_comment = line[:start[1]].strip() 

1125 if inline_comment: 

1126 if prev_end[0] == start[0] and start[1] < prev_end[1] + 2: 

1127 yield (prev_end, 

1128 "E261 at least two spaces before inline comment") 

1129 symbol, sp, comment = text.partition(' ') 

1130 bad_prefix = symbol not in '#:' and (symbol.lstrip('#')[:1] or '#') 

1131 if inline_comment: 

1132 if bad_prefix or comment[:1] in WHITESPACE: 

1133 yield start, "E262 inline comment should start with '# '" 

1134 elif bad_prefix and (bad_prefix != '!' or start[0] > 1): 

1135 if bad_prefix != '#': 

1136 yield start, "E265 block comment should start with '# '" 

1137 elif comment: 

1138 yield start, "E266 too many leading '#' for block comment" 

1139 elif token_type != tokenize.NL: 

1140 prev_end = end 

1141 

1142 

1143@register_check 

1144def imports_on_separate_lines(logical_line): 

1145 r"""Place imports on separate lines. 

1146 

1147 Okay: import os\nimport sys 

1148 E401: import sys, os 

1149 

1150 Okay: from subprocess import Popen, PIPE 

1151 Okay: from myclas import MyClass 

1152 Okay: from foo.bar.yourclass import YourClass 

1153 Okay: import myclass 

1154 Okay: import foo.bar.yourclass 

1155 """ 

1156 line = logical_line 

1157 if line.startswith('import '): 

1158 found = line.find(',') 

1159 if -1 < found and ';' not in line[:found]: 

1160 yield found, "E401 multiple imports on one line" 

1161 

1162 

1163@register_check 

1164def module_imports_on_top_of_file( 

1165 logical_line, indent_level, checker_state, noqa): 

1166 r"""Place imports at the top of the file. 

1167 

1168 Always put imports at the top of the file, just after any module 

1169 comments and docstrings, and before module globals and constants. 

1170 

1171 Okay: import os 

1172 Okay: # this is a comment\nimport os 

1173 Okay: '''this is a module docstring'''\nimport os 

1174 Okay: r'''this is a module docstring'''\nimport os 

1175 E402: a=1\nimport os 

1176 E402: 'One string'\n"Two string"\nimport os 

1177 E402: a=1\nfrom sys import x 

1178 

1179 Okay: if x:\n import os 

1180 """ # noqa 

1181 def is_string_literal(line): 

1182 if line[0] in 'uUbB': 

1183 line = line[1:] 

1184 if line and line[0] in 'rR': 

1185 line = line[1:] 

1186 return line and (line[0] == '"' or line[0] == "'") 

1187 

1188 allowed_keywords = ( 

1189 'try', 'except', 'else', 'finally', 'with', 'if', 'elif') 

1190 

1191 if indent_level: # Allow imports in conditional statement/function 

1192 return 

1193 if not logical_line: # Allow empty lines or comments 

1194 return 

1195 if noqa: 

1196 return 

1197 line = logical_line 

1198 if line.startswith('import ') or line.startswith('from '): 

1199 if checker_state.get('seen_non_imports', False): 

1200 yield 0, "E402 module level import not at top of file" 

1201 elif re.match(DUNDER_REGEX, line): 

1202 return 

1203 elif any(line.startswith(kw) for kw in allowed_keywords): 

1204 # Allow certain keywords intermixed with imports in order to 

1205 # support conditional or filtered importing 

1206 return 

1207 elif is_string_literal(line): 

1208 # The first literal is a docstring, allow it. Otherwise, report 

1209 # error. 

1210 if checker_state.get('seen_docstring', False): 

1211 checker_state['seen_non_imports'] = True 

1212 else: 

1213 checker_state['seen_docstring'] = True 

1214 else: 

1215 checker_state['seen_non_imports'] = True 

1216 

1217 

1218@register_check 

1219def compound_statements(logical_line): 

1220 r"""Compound statements (on the same line) are generally 

1221 discouraged. 

1222 

1223 While sometimes it's okay to put an if/for/while with a small body 

1224 on the same line, never do this for multi-clause statements. 

1225 Also avoid folding such long lines! 

1226 

1227 Always use a def statement instead of an assignment statement that 

1228 binds a lambda expression directly to a name. 

1229 

1230 Okay: if foo == 'blah':\n do_blah_thing() 

1231 Okay: do_one() 

1232 Okay: do_two() 

1233 Okay: do_three() 

1234 

1235 E701: if foo == 'blah': do_blah_thing() 

1236 E701: for x in lst: total += x 

1237 E701: while t < 10: t = delay() 

1238 E701: if foo == 'blah': do_blah_thing() 

1239 E701: else: do_non_blah_thing() 

1240 E701: try: something() 

1241 E701: finally: cleanup() 

1242 E701: if foo == 'blah': one(); two(); three() 

1243 E702: do_one(); do_two(); do_three() 

1244 E703: do_four(); # useless semicolon 

1245 E704: def f(x): return 2*x 

1246 E731: f = lambda x: 2*x 

1247 """ 

1248 line = logical_line 

1249 last_char = len(line) - 1 

1250 found = line.find(':') 

1251 prev_found = 0 

1252 counts = {char: 0 for char in '{}[]()'} 

1253 while -1 < found < last_char: 

1254 update_counts(line[prev_found:found], counts) 

1255 if ( 

1256 counts['{'] <= counts['}'] and # {'a': 1} (dict) 

1257 counts['['] <= counts[']'] and # [1:2] (slice) 

1258 counts['('] <= counts[')'] and # (annotation) 

1259 line[found + 1] != '=' # assignment expression 

1260 ): 

1261 lambda_kw = LAMBDA_REGEX.search(line, 0, found) 

1262 if lambda_kw: 

1263 before = line[:lambda_kw.start()].rstrip() 

1264 if before[-1:] == '=' and before[:-1].strip().isidentifier(): 

1265 yield 0, ("E731 do not assign a lambda expression, use a " 

1266 "def") 

1267 break 

1268 if STARTSWITH_DEF_REGEX.match(line): 

1269 yield 0, "E704 multiple statements on one line (def)" 

1270 elif STARTSWITH_INDENT_STATEMENT_REGEX.match(line): 

1271 yield found, "E701 multiple statements on one line (colon)" 

1272 prev_found = found 

1273 found = line.find(':', found + 1) 

1274 found = line.find(';') 

1275 while -1 < found: 

1276 if found < last_char: 

1277 yield found, "E702 multiple statements on one line (semicolon)" 

1278 else: 

1279 yield found, "E703 statement ends with a semicolon" 

1280 found = line.find(';', found + 1) 

1281 

1282 

1283@register_check 

1284def explicit_line_join(logical_line, tokens): 

1285 r"""Avoid explicit line join between brackets. 

1286 

1287 The preferred way of wrapping long lines is by using Python's 

1288 implied line continuation inside parentheses, brackets and braces. 

1289 Long lines can be broken over multiple lines by wrapping expressions 

1290 in parentheses. These should be used in preference to using a 

1291 backslash for line continuation. 

1292 

1293 E502: aaa = [123, \\n 123] 

1294 E502: aaa = ("bbb " \\n "ccc") 

1295 

1296 Okay: aaa = [123,\n 123] 

1297 Okay: aaa = ("bbb "\n "ccc") 

1298 Okay: aaa = "bbb " \\n "ccc" 

1299 Okay: aaa = 123 # \\ 

1300 """ 

1301 prev_start = prev_end = parens = 0 

1302 comment = False 

1303 backslash = None 

1304 for token_type, text, start, end, line in tokens: 

1305 if token_type == tokenize.COMMENT: 

1306 comment = True 

1307 if start[0] != prev_start and parens and backslash and not comment: 

1308 yield backslash, "E502 the backslash is redundant between brackets" 

1309 if start[0] != prev_start: 

1310 comment = False # Reset comment flag on newline 

1311 if end[0] != prev_end: 

1312 if line.rstrip('\r\n').endswith('\\'): 

1313 backslash = (end[0], len(line.splitlines()[-1]) - 1) 

1314 else: 

1315 backslash = None 

1316 prev_start = prev_end = end[0] 

1317 else: 

1318 prev_start = start[0] 

1319 if token_type == tokenize.OP: 

1320 if text in '([{': 

1321 parens += 1 

1322 elif text in ')]}': 

1323 parens -= 1 

1324 

1325 

1326# The % character is strictly speaking a binary operator, but the 

1327# common usage seems to be to put it next to the format parameters, 

1328# after a line break. 

1329_SYMBOLIC_OPS = frozenset("()[]{},:.;@=%~") | frozenset(("...",)) 

1330 

1331 

1332def _is_binary_operator(token_type, text): 

1333 return ( 

1334 token_type == tokenize.OP or 

1335 text in {'and', 'or'} 

1336 ) and ( 

1337 text not in _SYMBOLIC_OPS 

1338 ) 

1339 

1340 

1341def _break_around_binary_operators(tokens): 

1342 """Private function to reduce duplication. 

1343 

1344 This factors out the shared details between 

1345 :func:`break_before_binary_operator` and 

1346 :func:`break_after_binary_operator`. 

1347 """ 

1348 line_break = False 

1349 unary_context = True 

1350 # Previous non-newline token types and text 

1351 previous_token_type = None 

1352 previous_text = None 

1353 for token_type, text, start, end, line in tokens: 

1354 if token_type == tokenize.COMMENT: 

1355 continue 

1356 if ('\n' in text or '\r' in text) and token_type != tokenize.STRING: 

1357 line_break = True 

1358 else: 

1359 yield (token_type, text, previous_token_type, previous_text, 

1360 line_break, unary_context, start) 

1361 unary_context = text in '([{,;' 

1362 line_break = False 

1363 previous_token_type = token_type 

1364 previous_text = text 

1365 

1366 

1367@register_check 

1368def break_before_binary_operator(logical_line, tokens): 

1369 r""" 

1370 Avoid breaks before binary operators. 

1371 

1372 The preferred place to break around a binary operator is after the 

1373 operator, not before it. 

1374 

1375 W503: (width == 0\n + height == 0) 

1376 W503: (width == 0\n and height == 0) 

1377 W503: var = (1\n & ~2) 

1378 W503: var = (1\n / -2) 

1379 W503: var = (1\n + -1\n + -2) 

1380 

1381 Okay: foo(\n -x) 

1382 Okay: foo(x\n []) 

1383 Okay: x = '''\n''' + '' 

1384 Okay: foo(x,\n -y) 

1385 Okay: foo(x, # comment\n -y) 

1386 """ 

1387 for context in _break_around_binary_operators(tokens): 

1388 (token_type, text, previous_token_type, previous_text, 

1389 line_break, unary_context, start) = context 

1390 if (_is_binary_operator(token_type, text) and line_break and 

1391 not unary_context and 

1392 not _is_binary_operator(previous_token_type, 

1393 previous_text)): 

1394 yield start, "W503 line break before binary operator" 

1395 

1396 

1397@register_check 

1398def break_after_binary_operator(logical_line, tokens): 

1399 r""" 

1400 Avoid breaks after binary operators. 

1401 

1402 The preferred place to break around a binary operator is before the 

1403 operator, not after it. 

1404 

1405 W504: (width == 0 +\n height == 0) 

1406 W504: (width == 0 and\n height == 0) 

1407 W504: var = (1 &\n ~2) 

1408 

1409 Okay: foo(\n -x) 

1410 Okay: foo(x\n []) 

1411 Okay: x = '''\n''' + '' 

1412 Okay: x = '' + '''\n''' 

1413 Okay: foo(x,\n -y) 

1414 Okay: foo(x, # comment\n -y) 

1415 

1416 The following should be W504 but unary_context is tricky with these 

1417 Okay: var = (1 /\n -2) 

1418 Okay: var = (1 +\n -1 +\n -2) 

1419 """ 

1420 prev_start = None 

1421 for context in _break_around_binary_operators(tokens): 

1422 (token_type, text, previous_token_type, previous_text, 

1423 line_break, unary_context, start) = context 

1424 if (_is_binary_operator(previous_token_type, previous_text) and 

1425 line_break and 

1426 not unary_context and 

1427 not _is_binary_operator(token_type, text)): 

1428 yield prev_start, "W504 line break after binary operator" 

1429 prev_start = start 

1430 

1431 

1432@register_check 

1433def comparison_to_singleton(logical_line, noqa): 

1434 r"""Comparison to singletons should use "is" or "is not". 

1435 

1436 Comparisons to singletons like None should always be done 

1437 with "is" or "is not", never the equality operators. 

1438 

1439 Okay: if arg is not None: 

1440 E711: if arg != None: 

1441 E711: if None == arg: 

1442 E712: if arg == True: 

1443 E712: if False == arg: 

1444 

1445 Also, beware of writing if x when you really mean if x is not None 

1446 -- e.g. when testing whether a variable or argument that defaults to 

1447 None was set to some other value. The other value might have a type 

1448 (such as a container) that could be false in a boolean context! 

1449 """ 

1450 if noqa: 

1451 return 

1452 

1453 for match in COMPARE_SINGLETON_REGEX.finditer(logical_line): 

1454 singleton = match.group(1) or match.group(3) 

1455 same = (match.group(2) == '==') 

1456 

1457 msg = "'if cond is %s:'" % (('' if same else 'not ') + singleton) 

1458 if singleton in ('None',): 

1459 code = 'E711' 

1460 else: 

1461 code = 'E712' 

1462 nonzero = ((singleton == 'True' and same) or 

1463 (singleton == 'False' and not same)) 

1464 msg += " or 'if %scond:'" % ('' if nonzero else 'not ') 

1465 yield match.start(2), ("%s comparison to %s should be %s" % 

1466 (code, singleton, msg)) 

1467 

1468 

1469@register_check 

1470def comparison_negative(logical_line): 

1471 r"""Negative comparison should be done using "not in" and "is not". 

1472 

1473 Okay: if x not in y:\n pass 

1474 Okay: assert (X in Y or X is Z) 

1475 Okay: if not (X in Y):\n pass 

1476 Okay: zz = x is not y 

1477 E713: Z = not X in Y 

1478 E713: if not X.B in Y:\n pass 

1479 E714: if not X is Y:\n pass 

1480 E714: Z = not X.B is Y 

1481 """ 

1482 match = COMPARE_NEGATIVE_REGEX.search(logical_line) 

1483 if match: 

1484 pos = match.start(1) 

1485 if match.group(2) == 'in': 

1486 yield pos, "E713 test for membership should be 'not in'" 

1487 else: 

1488 yield pos, "E714 test for object identity should be 'is not'" 

1489 

1490 

1491@register_check 

1492def comparison_type(logical_line, noqa): 

1493 r"""Object type comparisons should `is` / `is not` / `isinstance()`. 

1494 

1495 Do not compare types directly. 

1496 

1497 Okay: if isinstance(obj, int): 

1498 Okay: if type(obj) is int: 

1499 E721: if type(obj) == type(1): 

1500 """ 

1501 match = COMPARE_TYPE_REGEX.search(logical_line) 

1502 if match and not noqa: 

1503 inst = match.group(1) 

1504 if inst and inst.isidentifier() and inst not in SINGLETONS: 

1505 return # Allow comparison for types which are not obvious 

1506 yield ( 

1507 match.start(), 

1508 "E721 do not compare types, for exact checks use `is` / `is not`, " 

1509 "for instance checks use `isinstance()`", 

1510 ) 

1511 

1512 

1513@register_check 

1514def bare_except(logical_line, noqa): 

1515 r"""When catching exceptions, mention specific exceptions when 

1516 possible. 

1517 

1518 Okay: except Exception: 

1519 Okay: except BaseException: 

1520 E722: except: 

1521 """ 

1522 if noqa: 

1523 return 

1524 

1525 match = BLANK_EXCEPT_REGEX.match(logical_line) 

1526 if match: 

1527 yield match.start(), "E722 do not use bare 'except'" 

1528 

1529 

1530@register_check 

1531def ambiguous_identifier(logical_line, tokens): 

1532 r"""Never use the characters 'l', 'O', or 'I' as variable names. 

1533 

1534 In some fonts, these characters are indistinguishable from the 

1535 numerals one and zero. When tempted to use 'l', use 'L' instead. 

1536 

1537 Okay: L = 0 

1538 Okay: o = 123 

1539 Okay: i = 42 

1540 E741: l = 0 

1541 E741: O = 123 

1542 E741: I = 42 

1543 

1544 Variables can be bound in several other contexts, including class 

1545 and function definitions, lambda functions, 'global' and 'nonlocal' 

1546 statements, exception handlers, and 'with' and 'for' statements. 

1547 In addition, we have a special handling for function parameters. 

1548 

1549 Okay: except AttributeError as o: 

1550 Okay: with lock as L: 

1551 Okay: foo(l=12) 

1552 Okay: foo(l=I) 

1553 Okay: for a in foo(l=12): 

1554 Okay: lambda arg: arg * l 

1555 Okay: lambda a=l[I:5]: None 

1556 Okay: lambda x=a.I: None 

1557 Okay: if l >= 12: 

1558 E741: except AttributeError as O: 

1559 E741: with lock as l: 

1560 E741: global I 

1561 E741: nonlocal l 

1562 E741: def foo(l): 

1563 E741: def foo(l=12): 

1564 E741: l = foo(l=12) 

1565 E741: for l in range(10): 

1566 E741: [l for l in lines if l] 

1567 E741: lambda l: None 

1568 E741: lambda a=x[1:5], l: None 

1569 E741: lambda **l: 

1570 E741: def f(**l): 

1571 E742: class I(object): 

1572 E743: def l(x): 

1573 """ 

1574 func_depth = None # set to brace depth if 'def' or 'lambda' is found 

1575 seen_colon = False # set to true if we're done with function parameters 

1576 brace_depth = 0 

1577 idents_to_avoid = ('l', 'O', 'I') 

1578 prev_type, prev_text, prev_start, prev_end, __ = tokens[0] 

1579 for index in range(1, len(tokens)): 

1580 token_type, text, start, end, line = tokens[index] 

1581 ident = pos = None 

1582 # find function definitions 

1583 if prev_text in {'def', 'lambda'}: 

1584 func_depth = brace_depth 

1585 seen_colon = False 

1586 elif ( 

1587 func_depth is not None and 

1588 text == ':' and 

1589 brace_depth == func_depth 

1590 ): 

1591 seen_colon = True 

1592 # update parameter parentheses level 

1593 if text in '([{': 

1594 brace_depth += 1 

1595 elif text in ')]}': 

1596 brace_depth -= 1 

1597 # identifiers on the lhs of an assignment operator 

1598 if text == ':=' or (text == '=' and brace_depth == 0): 

1599 if prev_text in idents_to_avoid: 

1600 ident = prev_text 

1601 pos = prev_start 

1602 # identifiers bound to values with 'as', 'for', 

1603 # 'global', or 'nonlocal' 

1604 if prev_text in ('as', 'for', 'global', 'nonlocal'): 

1605 if text in idents_to_avoid: 

1606 ident = text 

1607 pos = start 

1608 # function / lambda parameter definitions 

1609 if ( 

1610 func_depth is not None and 

1611 not seen_colon and 

1612 index < len(tokens) - 1 and tokens[index + 1][1] in ':,=)' and 

1613 prev_text in {'lambda', ',', '*', '**', '('} and 

1614 text in idents_to_avoid 

1615 ): 

1616 ident = text 

1617 pos = start 

1618 if prev_text == 'class': 

1619 if text in idents_to_avoid: 

1620 yield start, "E742 ambiguous class definition '%s'" % text 

1621 if prev_text == 'def': 

1622 if text in idents_to_avoid: 

1623 yield start, "E743 ambiguous function definition '%s'" % text 

1624 if ident: 

1625 yield pos, "E741 ambiguous variable name '%s'" % ident 

1626 prev_text = text 

1627 prev_start = start 

1628 

1629 

1630@register_check 

1631def python_3000_invalid_escape_sequence(logical_line, tokens, noqa): 

1632 r"""Invalid escape sequences are deprecated in Python 3.6. 

1633 

1634 Okay: regex = r'\.png$' 

1635 W605: regex = '\.png$' 

1636 """ 

1637 if noqa: 

1638 return 

1639 

1640 # https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals 

1641 valid = [ 

1642 '\n', 

1643 '\\', 

1644 '\'', 

1645 '"', 

1646 'a', 

1647 'b', 

1648 'f', 

1649 'n', 

1650 'r', 

1651 't', 

1652 'v', 

1653 '0', '1', '2', '3', '4', '5', '6', '7', 

1654 'x', 

1655 

1656 # Escape sequences only recognized in string literals 

1657 'N', 

1658 'u', 

1659 'U', 

1660 ] 

1661 

1662 prefixes = [] 

1663 for token_type, text, start, _, _ in tokens: 

1664 if token_type in {tokenize.STRING, FSTRING_START, TSTRING_START}: 

1665 # Extract string modifiers (e.g. u or r) 

1666 prefixes.append(text[:text.index(text[-1])].lower()) 

1667 

1668 if token_type in {tokenize.STRING, FSTRING_MIDDLE, TSTRING_MIDDLE}: 

1669 if 'r' not in prefixes[-1]: 

1670 start_line, start_col = start 

1671 pos = text.find('\\') 

1672 while pos >= 0: 

1673 pos += 1 

1674 if text[pos] not in valid: 

1675 line = start_line + text.count('\n', 0, pos) 

1676 if line == start_line: 

1677 col = start_col + pos 

1678 else: 

1679 col = pos - text.rfind('\n', 0, pos) - 1 

1680 yield ( 

1681 (line, col - 1), 

1682 f"W605 invalid escape sequence '\\{text[pos]}'" 

1683 ) 

1684 pos = text.find('\\', pos + 1) 

1685 

1686 if token_type in {tokenize.STRING, FSTRING_END, TSTRING_END}: 

1687 prefixes.pop() 

1688 

1689 

1690######################################################################## 

1691@register_check 

1692def maximum_doc_length(logical_line, max_doc_length, noqa, tokens): 

1693 r"""Limit all doc lines to a maximum of 72 characters. 

1694 

1695 For flowing long blocks of text (docstrings or comments), limiting 

1696 the length to 72 characters is recommended. 

1697 

1698 Reports warning W505 

1699 """ 

1700 if max_doc_length is None or noqa: 

1701 return 

1702 

1703 prev_token = None 

1704 skip_lines = set() 

1705 # Skip lines that 

1706 for token_type, text, start, end, line in tokens: 

1707 if token_type not in SKIP_COMMENTS.union([tokenize.STRING]): 

1708 skip_lines.add(line) 

1709 

1710 for token_type, text, start, end, line in tokens: 

1711 # Skip lines that aren't pure strings 

1712 if token_type == tokenize.STRING and skip_lines: 

1713 continue 

1714 if token_type in (tokenize.STRING, tokenize.COMMENT): 

1715 # Only check comment-only lines 

1716 if prev_token is None or prev_token in SKIP_TOKENS: 

1717 lines = line.splitlines() 

1718 for line_num, physical_line in enumerate(lines): 

1719 if start[0] + line_num == 1 and line.startswith('#!'): 

1720 return 

1721 length = len(physical_line) 

1722 chunks = physical_line.split() 

1723 if token_type == tokenize.COMMENT: 

1724 if (len(chunks) == 2 and 

1725 length - len(chunks[-1]) < MAX_DOC_LENGTH): 

1726 continue 

1727 if len(chunks) == 1 and line_num + 1 < len(lines): 

1728 if (len(chunks) == 1 and 

1729 length - len(chunks[-1]) < MAX_DOC_LENGTH): 

1730 continue 

1731 if length > max_doc_length: 

1732 doc_error = (start[0] + line_num, max_doc_length) 

1733 yield (doc_error, "W505 doc line too long " 

1734 "(%d > %d characters)" 

1735 % (length, max_doc_length)) 

1736 prev_token = token_type 

1737 

1738 

1739######################################################################## 

1740# Helper functions 

1741######################################################################## 

1742 

1743 

1744def readlines(filename): 

1745 """Read the source code.""" 

1746 try: 

1747 with tokenize.open(filename) as f: 

1748 return f.readlines() 

1749 except (LookupError, SyntaxError, UnicodeError): 

1750 # Fall back if file encoding is improperly declared 

1751 with open(filename, encoding='latin-1') as f: 

1752 return f.readlines() 

1753 

1754 

1755def stdin_get_value(): 

1756 """Read the value from stdin.""" 

1757 return io.TextIOWrapper(sys.stdin.buffer, errors='ignore').read() 

1758 

1759 

1760noqa = lru_cache(512)(re.compile(r'# no(?:qa|pep8)\b', re.I).search) 

1761 

1762 

1763def expand_indent(line): 

1764 r"""Return the amount of indentation. 

1765 

1766 Tabs are expanded to the next multiple of 8. 

1767 """ 

1768 line = line.rstrip('\n\r') 

1769 if '\t' not in line: 

1770 return len(line) - len(line.lstrip()) 

1771 result = 0 

1772 for char in line: 

1773 if char == '\t': 

1774 result = result // 8 * 8 + 8 

1775 elif char == ' ': 

1776 result += 1 

1777 else: 

1778 break 

1779 return result 

1780 

1781 

1782def mute_string(text): 

1783 """Replace contents with 'xxx' to prevent syntax matching.""" 

1784 # String modifiers (e.g. u or r) 

1785 start = text.index(text[-1]) + 1 

1786 end = len(text) - 1 

1787 # Triple quotes 

1788 if text[-3:] in ('"""', "'''"): 

1789 start += 2 

1790 end -= 2 

1791 return text[:start] + 'x' * (end - start) + text[end:] 

1792 

1793 

1794def parse_udiff(diff, patterns=None, parent='.'): 

1795 """Return a dictionary of matching lines.""" 

1796 # For each file of the diff, the entry key is the filename, 

1797 # and the value is a set of row numbers to consider. 

1798 rv = {} 

1799 path = nrows = None 

1800 for line in diff.splitlines(): 

1801 if nrows: 

1802 if line[:1] != '-': 

1803 nrows -= 1 

1804 continue 

1805 if line[:3] == '@@ ': 

1806 hunk_match = HUNK_REGEX.match(line) 

1807 (row, nrows) = (int(g or '1') for g in hunk_match.groups()) 

1808 rv[path].update(range(row, row + nrows)) 

1809 elif line[:3] == '+++': 

1810 path = line[4:].split('\t', 1)[0] 

1811 # Git diff will use (i)ndex, (w)ork tree, (c)ommit and 

1812 # (o)bject instead of a/b/c/d as prefixes for patches 

1813 if path[:2] in ('b/', 'w/', 'i/'): 

1814 path = path[2:] 

1815 rv[path] = set() 

1816 return { 

1817 os.path.join(parent, filepath): rows 

1818 for (filepath, rows) in rv.items() 

1819 if rows and filename_match(filepath, patterns) 

1820 } 

1821 

1822 

1823def normalize_paths(value, parent=os.curdir): 

1824 """Parse a comma-separated list of paths. 

1825 

1826 Return a list of absolute paths. 

1827 """ 

1828 if not value: 

1829 return [] 

1830 if isinstance(value, list): 

1831 return value 

1832 paths = [] 

1833 for path in value.split(','): 

1834 path = path.strip() 

1835 if '/' in path: 

1836 path = os.path.abspath(os.path.join(parent, path)) 

1837 paths.append(path.rstrip('/')) 

1838 return paths 

1839 

1840 

1841def filename_match(filename, patterns, default=True): 

1842 """Check if patterns contains a pattern that matches filename. 

1843 

1844 If patterns is unspecified, this always returns True. 

1845 """ 

1846 if not patterns: 

1847 return default 

1848 return any(fnmatch(filename, pattern) for pattern in patterns) 

1849 

1850 

1851def update_counts(s, counts): 

1852 r"""Adds one to the counts of each appearance of characters in s, 

1853 for characters in counts""" 

1854 for char in s: 

1855 if char in counts: 

1856 counts[char] += 1 

1857 

1858 

1859def _is_eol_token(token): 

1860 return token[0] in NEWLINE or token[4][token[3][1]:].lstrip() == '\\\n' 

1861 

1862 

1863######################################################################## 

1864# Framework to run all checks 

1865######################################################################## 

1866 

1867 

1868class Checker: 

1869 """Load a Python source file, tokenize it, check coding style.""" 

1870 

1871 def __init__(self, filename=None, lines=None, 

1872 options=None, report=None, **kwargs): 

1873 if options is None: 

1874 options = StyleGuide(kwargs).options 

1875 else: 

1876 assert not kwargs 

1877 self._io_error = None 

1878 self._physical_checks = options.physical_checks 

1879 self._logical_checks = options.logical_checks 

1880 self._ast_checks = options.ast_checks 

1881 self.max_line_length = options.max_line_length 

1882 self.max_doc_length = options.max_doc_length 

1883 self.indent_size = options.indent_size 

1884 self.fstring_start = self.tstring_start = 0 

1885 self.multiline = False # in a multiline string? 

1886 self.hang_closing = options.hang_closing 

1887 self.indent_size = options.indent_size 

1888 self.verbose = options.verbose 

1889 self.filename = filename 

1890 # Dictionary where a checker can store its custom state. 

1891 self._checker_states = {} 

1892 if filename is None: 

1893 self.filename = 'stdin' 

1894 self.lines = lines or [] 

1895 elif filename == '-': 

1896 self.filename = 'stdin' 

1897 self.lines = stdin_get_value().splitlines(True) 

1898 elif lines is None: 

1899 try: 

1900 self.lines = readlines(filename) 

1901 except OSError: 

1902 (exc_type, exc) = sys.exc_info()[:2] 

1903 self._io_error = f'{exc_type.__name__}: {exc}' 

1904 self.lines = [] 

1905 else: 

1906 self.lines = lines 

1907 if self.lines: 

1908 ord0 = ord(self.lines[0][0]) 

1909 if ord0 in (0xef, 0xfeff): # Strip the UTF-8 BOM 

1910 if ord0 == 0xfeff: 

1911 self.lines[0] = self.lines[0][1:] 

1912 elif self.lines[0][:3] == '\xef\xbb\xbf': 

1913 self.lines[0] = self.lines[0][3:] 

1914 self.report = report or options.report 

1915 self.report_error = self.report.error 

1916 self.noqa = False 

1917 

1918 def report_invalid_syntax(self): 

1919 """Check if the syntax is valid.""" 

1920 (exc_type, exc) = sys.exc_info()[:2] 

1921 if len(exc.args) > 1: 

1922 offset = exc.args[1] 

1923 if len(offset) > 2: 

1924 offset = offset[1:3] 

1925 else: 

1926 offset = (1, 0) 

1927 self.report_error(offset[0], offset[1] or 0, 

1928 f'E901 {exc_type.__name__}: {exc.args[0]}', 

1929 self.report_invalid_syntax) 

1930 

1931 def readline(self): 

1932 """Get the next line from the input buffer.""" 

1933 if self.line_number >= self.total_lines: 

1934 return '' 

1935 line = self.lines[self.line_number] 

1936 self.line_number += 1 

1937 if self.indent_char is None and line[:1] in WHITESPACE: 

1938 self.indent_char = line[0] 

1939 return line 

1940 

1941 def run_check(self, check, argument_names): 

1942 """Run a check plugin.""" 

1943 arguments = [getattr(self, name) for name in argument_names] 

1944 return check(*arguments) 

1945 

1946 def init_checker_state(self, name, argument_names): 

1947 """Prepare custom state for the specific checker plugin.""" 

1948 if 'checker_state' in argument_names: 

1949 self.checker_state = self._checker_states.setdefault(name, {}) 

1950 

1951 def check_physical(self, line): 

1952 """Run all physical checks on a raw input line.""" 

1953 self.physical_line = line 

1954 for name, check, argument_names in self._physical_checks: 

1955 self.init_checker_state(name, argument_names) 

1956 result = self.run_check(check, argument_names) 

1957 if result is not None: 

1958 (offset, text) = result 

1959 self.report_error(self.line_number, offset, text, check) 

1960 if text[:4] == 'E101': 

1961 self.indent_char = line[0] 

1962 

1963 def build_tokens_line(self): 

1964 """Build a logical line from tokens.""" 

1965 logical = [] 

1966 comments = [] 

1967 length = 0 

1968 prev_row = prev_col = mapping = None 

1969 for token_type, text, start, end, line in self.tokens: 

1970 if token_type in SKIP_TOKENS: 

1971 continue 

1972 if not mapping: 

1973 mapping = [(0, start)] 

1974 if token_type == tokenize.COMMENT: 

1975 comments.append(text) 

1976 continue 

1977 if token_type == tokenize.STRING: 

1978 text = mute_string(text) 

1979 elif token_type in {FSTRING_MIDDLE, TSTRING_MIDDLE}: # pragma: >=3.12 cover # noqa: E501 

1980 # fstring tokens are "unescaped" braces -- re-escape! 

1981 brace_count = text.count('{') + text.count('}') 

1982 text = 'x' * (len(text) + brace_count) 

1983 end = (end[0], end[1] + brace_count) 

1984 if prev_row: 

1985 (start_row, start_col) = start 

1986 if prev_row != start_row: # different row 

1987 prev_text = self.lines[prev_row - 1][prev_col - 1] 

1988 if prev_text == ',' or (prev_text not in '{[(' and 

1989 text not in '}])'): 

1990 text = ' ' + text 

1991 elif prev_col != start_col: # different column 

1992 text = line[prev_col:start_col] + text 

1993 logical.append(text) 

1994 length += len(text) 

1995 mapping.append((length, end)) 

1996 (prev_row, prev_col) = end 

1997 self.logical_line = ''.join(logical) 

1998 self.noqa = comments and noqa(''.join(comments)) 

1999 return mapping 

2000 

2001 def check_logical(self): 

2002 """Build a line from tokens and run all logical checks on it.""" 

2003 self.report.increment_logical_line() 

2004 mapping = self.build_tokens_line() 

2005 if not mapping: 

2006 return 

2007 

2008 mapping_offsets = [offset for offset, _ in mapping] 

2009 (start_row, start_col) = mapping[0][1] 

2010 start_line = self.lines[start_row - 1] 

2011 self.indent_level = expand_indent(start_line[:start_col]) 

2012 if self.blank_before < self.blank_lines: 

2013 self.blank_before = self.blank_lines 

2014 if self.verbose >= 2: 

2015 print(self.logical_line[:80].rstrip()) 

2016 for name, check, argument_names in self._logical_checks: 

2017 if self.verbose >= 4: 

2018 print(' ' + name) 

2019 self.init_checker_state(name, argument_names) 

2020 for offset, text in self.run_check(check, argument_names) or (): 

2021 if not isinstance(offset, tuple): 

2022 # As mappings are ordered, bisecting is a fast way 

2023 # to find a given offset in them. 

2024 token_offset, pos = mapping[bisect.bisect_left( 

2025 mapping_offsets, offset)] 

2026 offset = (pos[0], pos[1] + offset - token_offset) 

2027 self.report_error(offset[0], offset[1], text, check) 

2028 if self.logical_line: 

2029 self.previous_indent_level = self.indent_level 

2030 self.previous_logical = self.logical_line 

2031 if not self.indent_level: 

2032 self.previous_unindented_logical_line = self.logical_line 

2033 self.blank_lines = 0 

2034 self.tokens = [] 

2035 

2036 def check_ast(self): 

2037 """Build the file's AST and run all AST checks.""" 

2038 try: 

2039 tree = compile(''.join(self.lines), '', 'exec', PyCF_ONLY_AST) 

2040 except (ValueError, SyntaxError, TypeError): 

2041 return self.report_invalid_syntax() 

2042 for name, cls, __ in self._ast_checks: 

2043 checker = cls(tree, self.filename) 

2044 for lineno, offset, text, check in checker.run(): 

2045 if not self.lines or not noqa(self.lines[lineno - 1]): 

2046 self.report_error(lineno, offset, text, check) 

2047 

2048 def generate_tokens(self): 

2049 """Tokenize file, run physical line checks and yield tokens.""" 

2050 if self._io_error: 

2051 self.report_error(1, 0, 'E902 %s' % self._io_error, readlines) 

2052 tokengen = tokenize.generate_tokens(self.readline) 

2053 try: 

2054 prev_physical = '' 

2055 for token in tokengen: 

2056 if token[2][0] > self.total_lines: 

2057 return 

2058 self.noqa = token[4] and noqa(token[4]) 

2059 self.maybe_check_physical(token, prev_physical) 

2060 yield token 

2061 prev_physical = token[4] 

2062 except (SyntaxError, tokenize.TokenError): 

2063 self.report_invalid_syntax() 

2064 

2065 def maybe_check_physical(self, token, prev_physical): 

2066 """If appropriate for token, check current physical line(s).""" 

2067 # Called after every token, but act only on end of line. 

2068 

2069 if token.type == FSTRING_START: # pragma: >=3.12 cover 

2070 self.fstring_start = token.start[0] 

2071 elif token.type == TSTRING_START: # pragma: >=3.14 cover 

2072 self.tstring_start = token.start[0] 

2073 # a newline token ends a single physical line. 

2074 elif _is_eol_token(token): 

2075 # if the file does not end with a newline, the NEWLINE 

2076 # token is inserted by the parser, but it does not contain 

2077 # the previous physical line in `token[4]` 

2078 if token.line == '': 

2079 self.check_physical(prev_physical) 

2080 else: 

2081 self.check_physical(token.line) 

2082 elif ( 

2083 token.type == tokenize.STRING and '\n' in token.string or 

2084 token.type == FSTRING_END or 

2085 token.type == TSTRING_END 

2086 ): 

2087 # Less obviously, a string that contains newlines is a 

2088 # multiline string, either triple-quoted or with internal 

2089 # newlines backslash-escaped. Check every physical line in 

2090 # the string *except* for the last one: its newline is 

2091 # outside of the multiline string, so we consider it a 

2092 # regular physical line, and will check it like any other 

2093 # physical line. 

2094 # 

2095 # Subtleties: 

2096 # - we don't *completely* ignore the last line; if it 

2097 # contains the magical "# noqa" comment, we disable all 

2098 # physical checks for the entire multiline string 

2099 # - have to wind self.line_number back because initially it 

2100 # points to the last line of the string, and we want 

2101 # check_physical() to give accurate feedback 

2102 if noqa(token.line): 

2103 return 

2104 if token.type == FSTRING_END: # pragma: >=3.12 cover 

2105 start = self.fstring_start 

2106 elif token.type == TSTRING_END: # pragma: >=3.12 cover 

2107 start = self.tstring_start 

2108 else: 

2109 start = token.start[0] 

2110 end = token.end[0] 

2111 

2112 self.multiline = True 

2113 self.line_number = start 

2114 for line_number in range(start, end): 

2115 self.check_physical(self.lines[line_number - 1] + '\n') 

2116 self.line_number += 1 

2117 self.multiline = False 

2118 

2119 def check_all(self, expected=None, line_offset=0): 

2120 """Run all checks on the input file.""" 

2121 self.report.init_file(self.filename, self.lines, expected, line_offset) 

2122 self.total_lines = len(self.lines) 

2123 if self._ast_checks: 

2124 self.check_ast() 

2125 self.line_number = 0 

2126 self.indent_char = None 

2127 self.indent_level = self.previous_indent_level = 0 

2128 self.previous_logical = '' 

2129 self.previous_unindented_logical_line = '' 

2130 self.tokens = [] 

2131 self.blank_lines = self.blank_before = 0 

2132 parens = 0 

2133 for token in self.generate_tokens(): 

2134 self.tokens.append(token) 

2135 token_type, text = token[0:2] 

2136 if self.verbose >= 3: 

2137 if token[2][0] == token[3][0]: 

2138 pos = '[{}:{}]'.format(token[2][1] or '', token[3][1]) 

2139 else: 

2140 pos = 'l.%s' % token[3][0] 

2141 print('l.%s\t%s\t%s\t%r' % 

2142 (token[2][0], pos, tokenize.tok_name[token[0]], text)) 

2143 if token_type == tokenize.OP: 

2144 if text in '([{': 

2145 parens += 1 

2146 elif text in '}])': 

2147 parens -= 1 

2148 elif not parens: 

2149 if token_type in NEWLINE: 

2150 if token_type == tokenize.NEWLINE: 

2151 self.check_logical() 

2152 self.blank_before = 0 

2153 elif len(self.tokens) == 1: 

2154 # The physical line contains only this token. 

2155 self.blank_lines += 1 

2156 del self.tokens[0] 

2157 else: 

2158 self.check_logical() 

2159 if self.tokens: 

2160 self.check_physical(self.lines[-1]) 

2161 self.check_logical() 

2162 return self.report.get_file_results() 

2163 

2164 

2165class BaseReport: 

2166 """Collect the results of the checks.""" 

2167 

2168 print_filename = False 

2169 

2170 def __init__(self, options): 

2171 self._benchmark_keys = options.benchmark_keys 

2172 self._ignore_code = options.ignore_code 

2173 # Results 

2174 self.elapsed = 0 

2175 self.total_errors = 0 

2176 self.counters = dict.fromkeys(self._benchmark_keys, 0) 

2177 self.messages = {} 

2178 

2179 def start(self): 

2180 """Start the timer.""" 

2181 self._start_time = time.time() 

2182 

2183 def stop(self): 

2184 """Stop the timer.""" 

2185 self.elapsed = time.time() - self._start_time 

2186 

2187 def init_file(self, filename, lines, expected, line_offset): 

2188 """Signal a new file.""" 

2189 self.filename = filename 

2190 self.lines = lines 

2191 self.expected = expected or () 

2192 self.line_offset = line_offset 

2193 self.file_errors = 0 

2194 self.counters['files'] += 1 

2195 self.counters['physical lines'] += len(lines) 

2196 

2197 def increment_logical_line(self): 

2198 """Signal a new logical line.""" 

2199 self.counters['logical lines'] += 1 

2200 

2201 def error(self, line_number, offset, text, check): 

2202 """Report an error, according to options.""" 

2203 code = text[:4] 

2204 if self._ignore_code(code): 

2205 return 

2206 if code in self.counters: 

2207 self.counters[code] += 1 

2208 else: 

2209 self.counters[code] = 1 

2210 self.messages[code] = text[5:] 

2211 # Don't care about expected errors or warnings 

2212 if code in self.expected: 

2213 return 

2214 if self.print_filename and not self.file_errors: 

2215 print(self.filename) 

2216 self.file_errors += 1 

2217 self.total_errors += 1 

2218 return code 

2219 

2220 def get_file_results(self): 

2221 """Return the count of errors and warnings for this file.""" 

2222 return self.file_errors 

2223 

2224 def get_count(self, prefix=''): 

2225 """Return the total count of errors and warnings.""" 

2226 return sum(self.counters[key] 

2227 for key in self.messages if key.startswith(prefix)) 

2228 

2229 def get_statistics(self, prefix=''): 

2230 """Get statistics for message codes that start with the prefix. 

2231 

2232 prefix='' matches all errors and warnings 

2233 prefix='E' matches all errors 

2234 prefix='W' matches all warnings 

2235 prefix='E4' matches all errors that have to do with imports 

2236 """ 

2237 return ['%-7s %s %s' % (self.counters[key], key, self.messages[key]) 

2238 for key in sorted(self.messages) if key.startswith(prefix)] 

2239 

2240 def print_statistics(self, prefix=''): 

2241 """Print overall statistics (number of errors and warnings).""" 

2242 for line in self.get_statistics(prefix): 

2243 print(line) 

2244 

2245 def print_benchmark(self): 

2246 """Print benchmark numbers.""" 

2247 print('{:<7.2f} {}'.format(self.elapsed, 'seconds elapsed')) 

2248 if self.elapsed: 

2249 for key in self._benchmark_keys: 

2250 print('%-7d %s per second (%d total)' % 

2251 (self.counters[key] / self.elapsed, key, 

2252 self.counters[key])) 

2253 

2254 

2255class FileReport(BaseReport): 

2256 """Collect the results of the checks and print the filenames.""" 

2257 

2258 print_filename = True 

2259 

2260 

2261class StandardReport(BaseReport): 

2262 """Collect and print the results of the checks.""" 

2263 

2264 def __init__(self, options): 

2265 super().__init__(options) 

2266 self._fmt = REPORT_FORMAT.get(options.format.lower(), 

2267 options.format) 

2268 self._repeat = options.repeat 

2269 self._show_source = options.show_source 

2270 self._show_pep8 = options.show_pep8 

2271 

2272 def init_file(self, filename, lines, expected, line_offset): 

2273 """Signal a new file.""" 

2274 self._deferred_print = [] 

2275 return super().init_file( 

2276 filename, lines, expected, line_offset) 

2277 

2278 def error(self, line_number, offset, text, check): 

2279 """Report an error, according to options.""" 

2280 code = super().error(line_number, offset, text, check) 

2281 if code and (self.counters[code] == 1 or self._repeat): 

2282 self._deferred_print.append( 

2283 (line_number, offset, code, text[5:], check.__doc__)) 

2284 return code 

2285 

2286 def get_file_results(self): 

2287 """Print results and return the overall count for this file.""" 

2288 self._deferred_print.sort() 

2289 for line_number, offset, code, text, doc in self._deferred_print: 

2290 print(self._fmt % { 

2291 'path': self.filename, 

2292 'row': self.line_offset + line_number, 'col': offset + 1, 

2293 'code': code, 'text': text, 

2294 }) 

2295 if self._show_source: 

2296 if line_number > len(self.lines): 

2297 line = '' 

2298 else: 

2299 line = self.lines[line_number - 1] 

2300 print(line.rstrip()) 

2301 print(re.sub(r'\S', ' ', line[:offset]) + '^') 

2302 if self._show_pep8 and doc: 

2303 print(' ' + doc.strip()) 

2304 

2305 # stdout is block buffered when not stdout.isatty(). 

2306 # line can be broken where buffer boundary since other 

2307 # processes write to same file. 

2308 # flush() after print() to avoid buffer boundary. 

2309 # Typical buffer size is 8192. line written safely when 

2310 # len(line) < 8192. 

2311 sys.stdout.flush() 

2312 return self.file_errors 

2313 

2314 

2315class DiffReport(StandardReport): 

2316 """Collect and print the results for the changed lines only.""" 

2317 

2318 def __init__(self, options): 

2319 super().__init__(options) 

2320 self._selected = options.selected_lines 

2321 

2322 def error(self, line_number, offset, text, check): 

2323 if line_number not in self._selected[self.filename]: 

2324 return 

2325 return super().error(line_number, offset, text, check) 

2326 

2327 

2328class StyleGuide: 

2329 """Initialize a PEP-8 instance with few options.""" 

2330 

2331 def __init__(self, *args, **kwargs): 

2332 # build options from the command line 

2333 self.checker_class = kwargs.pop('checker_class', Checker) 

2334 parse_argv = kwargs.pop('parse_argv', False) 

2335 config_file = kwargs.pop('config_file', False) 

2336 parser = kwargs.pop('parser', None) 

2337 # build options from dict 

2338 options_dict = dict(*args, **kwargs) 

2339 arglist = None if parse_argv else options_dict.get('paths', None) 

2340 verbose = options_dict.get('verbose', None) 

2341 options, self.paths = process_options( 

2342 arglist, parse_argv, config_file, parser, verbose) 

2343 if options_dict: 

2344 options.__dict__.update(options_dict) 

2345 if 'paths' in options_dict: 

2346 self.paths = options_dict['paths'] 

2347 

2348 self.runner = self.input_file 

2349 self.options = options 

2350 

2351 if not options.reporter: 

2352 options.reporter = BaseReport if options.quiet else StandardReport 

2353 

2354 options.select = tuple(options.select or ()) 

2355 if not (options.select or options.ignore) and DEFAULT_IGNORE: 

2356 # The default choice: ignore controversial checks 

2357 options.ignore = tuple(DEFAULT_IGNORE.split(',')) 

2358 else: 

2359 # Ignore all checks which are not explicitly selected 

2360 options.ignore = ('',) if options.select else tuple(options.ignore) 

2361 options.benchmark_keys = BENCHMARK_KEYS[:] 

2362 options.ignore_code = self.ignore_code 

2363 options.physical_checks = self.get_checks('physical_line') 

2364 options.logical_checks = self.get_checks('logical_line') 

2365 options.ast_checks = self.get_checks('tree') 

2366 self.init_report() 

2367 

2368 def init_report(self, reporter=None): 

2369 """Initialize the report instance.""" 

2370 self.options.report = (reporter or self.options.reporter)(self.options) 

2371 return self.options.report 

2372 

2373 def check_files(self, paths=None): 

2374 """Run all checks on the paths.""" 

2375 if paths is None: 

2376 paths = self.paths 

2377 report = self.options.report 

2378 runner = self.runner 

2379 report.start() 

2380 try: 

2381 for path in paths: 

2382 if os.path.isdir(path): 

2383 self.input_dir(path) 

2384 elif not self.excluded(path): 

2385 runner(path) 

2386 except KeyboardInterrupt: 

2387 print('... stopped') 

2388 report.stop() 

2389 return report 

2390 

2391 def input_file(self, filename, lines=None, expected=None, line_offset=0): 

2392 """Run all checks on a Python source file.""" 

2393 if self.options.verbose: 

2394 print('checking %s' % filename) 

2395 fchecker = self.checker_class( 

2396 filename, lines=lines, options=self.options) 

2397 return fchecker.check_all(expected=expected, line_offset=line_offset) 

2398 

2399 def input_dir(self, dirname): 

2400 """Check all files in this directory and all subdirectories.""" 

2401 dirname = dirname.rstrip('/') 

2402 if self.excluded(dirname): 

2403 return 0 

2404 counters = self.options.report.counters 

2405 verbose = self.options.verbose 

2406 filepatterns = self.options.filename 

2407 runner = self.runner 

2408 for root, dirs, files in os.walk(dirname): 

2409 if verbose: 

2410 print('directory ' + root) 

2411 counters['directories'] += 1 

2412 for subdir in sorted(dirs): 

2413 if self.excluded(subdir, root): 

2414 dirs.remove(subdir) 

2415 for filename in sorted(files): 

2416 # contain a pattern that matches? 

2417 if ( 

2418 filename_match(filename, filepatterns) and 

2419 not self.excluded(filename, root) 

2420 ): 

2421 runner(os.path.join(root, filename)) 

2422 

2423 def excluded(self, filename, parent=None): 

2424 """Check if the file should be excluded. 

2425 

2426 Check if 'options.exclude' contains a pattern matching filename. 

2427 """ 

2428 if not self.options.exclude: 

2429 return False 

2430 basename = os.path.basename(filename) 

2431 if filename_match(basename, self.options.exclude): 

2432 return True 

2433 if parent: 

2434 filename = os.path.join(parent, filename) 

2435 filename = os.path.abspath(filename) 

2436 return filename_match(filename, self.options.exclude) 

2437 

2438 def ignore_code(self, code): 

2439 """Check if the error code should be ignored. 

2440 

2441 If 'options.select' contains a prefix of the error code, 

2442 return False. Else, if 'options.ignore' contains a prefix of 

2443 the error code, return True. 

2444 """ 

2445 if len(code) < 4 and any(s.startswith(code) 

2446 for s in self.options.select): 

2447 return False 

2448 return (code.startswith(self.options.ignore) and 

2449 not code.startswith(self.options.select)) 

2450 

2451 def get_checks(self, argument_name): 

2452 """Get all the checks for this category. 

2453 

2454 Find all globally visible functions where the first argument 

2455 name starts with argument_name and which contain selected tests. 

2456 """ 

2457 checks = [] 

2458 for check, attrs in _checks[argument_name].items(): 

2459 (codes, args) = attrs 

2460 if any(not (code and self.ignore_code(code)) for code in codes): 

2461 checks.append((check.__name__, check, args)) 

2462 return sorted(checks) 

2463 

2464 

2465def get_parser(prog='pycodestyle', version=__version__): 

2466 """Create the parser for the program.""" 

2467 parser = OptionParser(prog=prog, version=version, 

2468 usage="%prog [options] input ...") 

2469 parser.config_options = [ 

2470 'exclude', 'filename', 'select', 'ignore', 'max-line-length', 

2471 'max-doc-length', 'indent-size', 'hang-closing', 'count', 'format', 

2472 'quiet', 'show-pep8', 'show-source', 'statistics', 'verbose'] 

2473 parser.add_option('-v', '--verbose', default=0, action='count', 

2474 help="print status messages, or debug with -vv") 

2475 parser.add_option('-q', '--quiet', default=0, action='count', 

2476 help="report only file names, or nothing with -qq") 

2477 parser.add_option('-r', '--repeat', default=True, action='store_true', 

2478 help="(obsolete) show all occurrences of the same error") 

2479 parser.add_option('--first', action='store_false', dest='repeat', 

2480 help="show first occurrence of each error") 

2481 parser.add_option('--exclude', metavar='patterns', default=DEFAULT_EXCLUDE, 

2482 help="exclude files or directories which match these " 

2483 "comma separated patterns (default: %default)") 

2484 parser.add_option('--filename', metavar='patterns', default='*.py', 

2485 help="when parsing directories, only check filenames " 

2486 "matching these comma separated patterns " 

2487 "(default: %default)") 

2488 parser.add_option('--select', metavar='errors', default='', 

2489 help="select errors and warnings (e.g. E,W6)") 

2490 parser.add_option('--ignore', metavar='errors', default='', 

2491 help="skip errors and warnings (e.g. E4,W) " 

2492 "(default: %s)" % DEFAULT_IGNORE) 

2493 parser.add_option('--show-source', action='store_true', 

2494 help="show source code for each error") 

2495 parser.add_option('--show-pep8', action='store_true', 

2496 help="show text of PEP 8 for each error " 

2497 "(implies --first)") 

2498 parser.add_option('--statistics', action='store_true', 

2499 help="count errors and warnings") 

2500 parser.add_option('--count', action='store_true', 

2501 help="print total number of errors and warnings " 

2502 "to standard error and set exit code to 1 if " 

2503 "total is not null") 

2504 parser.add_option('--max-line-length', type='int', metavar='n', 

2505 default=MAX_LINE_LENGTH, 

2506 help="set maximum allowed line length " 

2507 "(default: %default)") 

2508 parser.add_option('--max-doc-length', type='int', metavar='n', 

2509 default=None, 

2510 help="set maximum allowed doc line length and perform " 

2511 "these checks (unchecked if not set)") 

2512 parser.add_option('--indent-size', type='int', metavar='n', 

2513 default=INDENT_SIZE, 

2514 help="set how many spaces make up an indent " 

2515 "(default: %default)") 

2516 parser.add_option('--hang-closing', action='store_true', 

2517 help="hang closing bracket instead of matching " 

2518 "indentation of opening bracket's line") 

2519 parser.add_option('--format', metavar='format', default='default', 

2520 help="set the error format [default|pylint|<custom>]") 

2521 parser.add_option('--diff', action='store_true', 

2522 help="report changes only within line number ranges in " 

2523 "the unified diff received on STDIN") 

2524 group = parser.add_option_group("Testing Options") 

2525 group.add_option('--benchmark', action='store_true', 

2526 help="measure processing speed") 

2527 return parser 

2528 

2529 

2530def read_config(options, args, arglist, parser): 

2531 """Read and parse configurations. 

2532 

2533 If a config file is specified on the command line with the 

2534 "--config" option, then only it is used for configuration. 

2535 

2536 Otherwise, the user configuration (~/.config/pycodestyle) and any 

2537 local configurations in the current directory or above will be 

2538 merged together (in that order) using the read method of 

2539 ConfigParser. 

2540 """ 

2541 config = configparser.RawConfigParser() 

2542 

2543 cli_conf = options.config 

2544 

2545 local_dir = os.curdir 

2546 

2547 if USER_CONFIG and os.path.isfile(USER_CONFIG): 

2548 if options.verbose: 

2549 print('user configuration: %s' % USER_CONFIG) 

2550 config.read(USER_CONFIG) 

2551 

2552 parent = tail = args and os.path.abspath(os.path.commonprefix(args)) 

2553 while tail: 

2554 if config.read(os.path.join(parent, fn) for fn in PROJECT_CONFIG): 

2555 local_dir = parent 

2556 if options.verbose: 

2557 print('local configuration: in %s' % parent) 

2558 break 

2559 (parent, tail) = os.path.split(parent) 

2560 

2561 if cli_conf and os.path.isfile(cli_conf): 

2562 if options.verbose: 

2563 print('cli configuration: %s' % cli_conf) 

2564 config.read(cli_conf) 

2565 

2566 pycodestyle_section = None 

2567 if config.has_section(parser.prog): 

2568 pycodestyle_section = parser.prog 

2569 elif config.has_section('pep8'): 

2570 pycodestyle_section = 'pep8' # Deprecated 

2571 warnings.warn('[pep8] section is deprecated. Use [pycodestyle].') 

2572 

2573 if pycodestyle_section: 

2574 option_list = {o.dest: o.type or o.action for o in parser.option_list} 

2575 

2576 # First, read the default values 

2577 (new_options, __) = parser.parse_args([]) 

2578 

2579 # Second, parse the configuration 

2580 for opt in config.options(pycodestyle_section): 

2581 if opt.replace('_', '-') not in parser.config_options: 

2582 print(" unknown option '%s' ignored" % opt) 

2583 continue 

2584 if options.verbose > 1: 

2585 print(" {} = {}".format(opt, 

2586 config.get(pycodestyle_section, opt))) 

2587 normalized_opt = opt.replace('-', '_') 

2588 opt_type = option_list[normalized_opt] 

2589 if opt_type in ('int', 'count'): 

2590 value = config.getint(pycodestyle_section, opt) 

2591 elif opt_type in ('store_true', 'store_false'): 

2592 value = config.getboolean(pycodestyle_section, opt) 

2593 else: 

2594 value = config.get(pycodestyle_section, opt) 

2595 if normalized_opt == 'exclude': 

2596 value = normalize_paths(value, local_dir) 

2597 setattr(new_options, normalized_opt, value) 

2598 

2599 # Third, overwrite with the command-line options 

2600 (options, __) = parser.parse_args(arglist, values=new_options) 

2601 return options 

2602 

2603 

2604def process_options(arglist=None, parse_argv=False, config_file=None, 

2605 parser=None, verbose=None): 

2606 """Process options passed either via arglist or command line args. 

2607 

2608 Passing in the ``config_file`` parameter allows other tools, such as 

2609 flake8 to specify their own options to be processed in pycodestyle. 

2610 """ 

2611 if not parser: 

2612 parser = get_parser() 

2613 if not parser.has_option('--config'): 

2614 group = parser.add_option_group("Configuration", description=( 

2615 "The project options are read from the [%s] section of the " 

2616 "tox.ini file or the setup.cfg file located in any parent folder " 

2617 "of the path(s) being processed. Allowed options are: %s." % 

2618 (parser.prog, ', '.join(parser.config_options)))) 

2619 group.add_option('--config', metavar='path', default=config_file, 

2620 help="user config file location") 

2621 # Don't read the command line if the module is used as a library. 

2622 if not arglist and not parse_argv: 

2623 arglist = [] 

2624 # If parse_argv is True and arglist is None, arguments are 

2625 # parsed from the command line (sys.argv) 

2626 (options, args) = parser.parse_args(arglist) 

2627 options.reporter = None 

2628 

2629 # If explicitly specified verbosity, override any `-v` CLI flag 

2630 if verbose is not None: 

2631 options.verbose = verbose 

2632 

2633 if parse_argv and not args: 

2634 if options.diff or any(os.path.exists(name) 

2635 for name in PROJECT_CONFIG): 

2636 args = ['.'] 

2637 else: 

2638 parser.error('input not specified') 

2639 options = read_config(options, args, arglist, parser) 

2640 options.reporter = parse_argv and options.quiet == 1 and FileReport 

2641 

2642 options.filename = _parse_multi_options(options.filename) 

2643 options.exclude = normalize_paths(options.exclude) 

2644 options.select = _parse_multi_options(options.select) 

2645 options.ignore = _parse_multi_options(options.ignore) 

2646 

2647 if options.diff: 

2648 options.reporter = DiffReport 

2649 stdin = stdin_get_value() 

2650 options.selected_lines = parse_udiff(stdin, options.filename, args[0]) 

2651 args = sorted(options.selected_lines) 

2652 

2653 return options, args 

2654 

2655 

2656def _parse_multi_options(options, split_token=','): 

2657 r"""Split and strip and discard empties. 

2658 

2659 Turns the following: 

2660 

2661 A, 

2662 B, 

2663 

2664 into ["A", "B"] 

2665 """ 

2666 if options: 

2667 return [o.strip() for o in options.split(split_token) if o.strip()] 

2668 else: 

2669 return options 

2670 

2671 

2672def _main(): 

2673 """Parse options and run checks on Python source.""" 

2674 import signal 

2675 

2676 # Handle "Broken pipe" gracefully 

2677 try: 

2678 signal.signal(signal.SIGPIPE, lambda signum, frame: sys.exit(1)) 

2679 except AttributeError: 

2680 pass # not supported on Windows 

2681 

2682 style_guide = StyleGuide(parse_argv=True) 

2683 options = style_guide.options 

2684 

2685 report = style_guide.check_files() 

2686 

2687 if options.statistics: 

2688 report.print_statistics() 

2689 

2690 if options.benchmark: 

2691 report.print_benchmark() 

2692 

2693 if report.total_errors: 

2694 if options.count: 

2695 sys.stderr.write(str(report.total_errors) + '\n') 

2696 sys.exit(1) 

2697 

2698 

2699if __name__ == '__main__': 

2700 _main()