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

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1350 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.13.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 

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

162 

163 

164def _get_parameters(function): 

165 return [parameter.name 

166 for parameter 

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

168 if parameter.kind == parameter.POSITIONAL_OR_KEYWORD] 

169 

170 

171def register_check(check, codes=None): 

172 """Register a new check object.""" 

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

174 if check in _checks[kind]: 

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

176 else: 

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

178 if inspect.isfunction(check): 

179 args = _get_parameters(check) 

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

181 if codes is None: 

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

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

184 elif inspect.isclass(check): 

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

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

187 return check 

188 

189 

190######################################################################## 

191# Plugins (check functions) for physical lines 

192######################################################################## 

193 

194@register_check 

195def tabs_or_spaces(physical_line, indent_char): 

196 r"""Never mix tabs and spaces. 

197 

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

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

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

201 exclusively. When invoking the Python command line interpreter with 

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

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

204 These options are highly recommended! 

205 

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

207 """ 

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

209 for offset, char in enumerate(indent): 

210 if char != indent_char: 

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

212 

213 

214@register_check 

215def tabs_obsolete(physical_line): 

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

217 

218 Okay: if True:\n return 

219 W191: if True:\n\treturn 

220 """ 

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

222 if '\t' in indent: 

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

224 

225 

226@register_check 

227def trailing_whitespace(physical_line): 

228 r"""Trailing whitespace is superfluous. 

229 

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

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

232 

233 Okay: spam(1)\n# 

234 W291: spam(1) \n# 

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

236 """ 

237 # Strip these trailing characters: 

238 # - chr(10), newline 

239 # - chr(13), carriage return 

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

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

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

243 if physical_line != stripped: 

244 if stripped: 

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

246 else: 

247 return 0, "W293 blank line contains whitespace" 

248 

249 

250@register_check 

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

252 r"""Trailing blank lines are superfluous. 

253 

254 Okay: spam(1) 

255 W391: spam(1)\n 

256 

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

258 """ 

259 if line_number == total_lines: 

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

261 if physical_line and not stripped_last_line: 

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

263 if stripped_last_line == physical_line: 

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

265 

266 

267@register_check 

268def maximum_line_length(physical_line, max_line_length, multiline, 

269 line_number, noqa): 

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

271 

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

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

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

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

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

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

278 

279 Reports error E501. 

280 """ 

281 line = physical_line.rstrip() 

282 length = len(line) 

283 if length > max_line_length and not noqa: 

284 # Special case: ignore long shebang lines. 

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

286 return 

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

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

289 # are whitespaces. 

290 chunks = line.split() 

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

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

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

294 return 

295 if length > max_line_length: 

296 return (max_line_length, "E501 line too long " 

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

298 

299 

300######################################################################## 

301# Plugins (check functions) for logical lines 

302######################################################################## 

303 

304 

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

306 if not STARTSWITH_TOP_LEVEL_REGEX.match(logical_line): 

307 return False 

308 

309 line_idx = line_number - 1 

310 

311 if line_idx < 1: 

312 prev_indent = 0 

313 else: 

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

315 

316 if prev_indent > indent_level: 

317 return False 

318 

319 while line_idx < len(lines): 

320 line = lines[line_idx].strip() 

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

322 break 

323 else: 

324 line_idx += 1 

325 else: 

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

327 

328 next_idx = line_idx + 1 

329 while next_idx < len(lines): 

330 if lines[next_idx].strip(): 

331 break 

332 else: 

333 next_idx += 1 

334 else: 

335 return True # line is last in the file 

336 

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

338 

339 

340@register_check 

341def blank_lines(logical_line, blank_lines, indent_level, line_number, 

342 blank_before, previous_logical, 

343 previous_unindented_logical_line, previous_indent_level, 

344 lines): 

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

346 lines. 

347 

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

349 line. 

350 

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

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

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

354 

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

356 sections. 

357 

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

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

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

361 Okay: default = 1\nfoo = 1 

362 Okay: classify = 1\nfoo = 1 

363 

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

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

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

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

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

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

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

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

372 """ # noqa 

373 top_level_lines = BLANK_LINES_CONFIG['top_level'] 

374 method_lines = BLANK_LINES_CONFIG['method'] 

375 

376 if not previous_logical and blank_before < top_level_lines: 

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

378 if previous_logical.startswith('@'): 

379 if blank_lines: 

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

381 elif (blank_lines > top_level_lines or 

382 (indent_level and blank_lines == method_lines + 1) 

383 ): 

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

385 elif STARTSWITH_TOP_LEVEL_REGEX.match(logical_line): 

386 # allow a group of one-liners 

387 if ( 

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

389 blank_before == 0 

390 ): 

391 return 

392 if indent_level: 

393 if not (blank_before == method_lines or 

394 previous_indent_level < indent_level or 

395 DOCSTRING_REGEX.match(previous_logical) 

396 ): 

397 ancestor_level = indent_level 

398 nested = False 

399 # Search backwards for a def ancestor or tree root 

400 # (top level). 

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

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

403 ancestor_level = expand_indent(line) 

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

405 if nested or ancestor_level == 0: 

406 break 

407 if nested: 

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

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

410 else: 

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

412 method_lines) 

413 elif blank_before != top_level_lines: 

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

415 top_level_lines, blank_before) 

416 elif (logical_line and 

417 not indent_level and 

418 blank_before != top_level_lines and 

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

420 ): 

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

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

423 top_level_lines, blank_before) 

424 

425 

426@register_check 

427def extraneous_whitespace(logical_line): 

428 r"""Avoid extraneous whitespace. 

429 

430 Avoid extraneous whitespace in these situations: 

431 - Immediately inside parentheses, brackets or braces. 

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

433 

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

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

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

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

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

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

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

441 

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

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

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

445 

446 Okay: @decorator 

447 E204: @ decorator 

448 """ 

449 line = logical_line 

450 for match in EXTRANEOUS_WHITESPACE_REGEX.finditer(line): 

451 text = match.group() 

452 char = text.strip() 

453 found = match.start() 

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

455 # assert char in '([{' 

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

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

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

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

460 

461 if WHITESPACE_AFTER_DECORATOR_REGEX.match(logical_line): 

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

463 

464 

465@register_check 

466def whitespace_around_keywords(logical_line): 

467 r"""Avoid extraneous whitespace around keywords. 

468 

469 Okay: True and False 

470 E271: True and False 

471 E272: True and False 

472 E273: True and\tFalse 

473 E274: True\tand False 

474 """ 

475 for match in KEYWORD_REGEX.finditer(logical_line): 

476 before, after = match.groups() 

477 

478 if '\t' in before: 

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

480 elif len(before) > 1: 

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

482 

483 if '\t' in after: 

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

485 elif len(after) > 1: 

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

487 

488 

489@register_check 

490def missing_whitespace_after_keyword(logical_line, tokens): 

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

492 

493 Okay: from foo import (bar, baz) 

494 E275: from foo import(bar, baz) 

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

496 E275: if(foo): bar 

497 """ 

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

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

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

501 # valid identifier names in old Python versions. 

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

503 tok0.type == tokenize.NAME and 

504 keyword.iskeyword(tok0.string) and 

505 tok0.string not in SINGLETONS and 

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

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

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

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

510 

511 

512@register_check 

513def indentation(logical_line, previous_logical, indent_char, 

514 indent_level, previous_indent_level, 

515 indent_size): 

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

517 

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

519 to use 8-space tabs. 

520 

521 Okay: a = 1 

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

523 E111: a = 1 

524 E114: # a = 1 

525 

526 Okay: for item in items:\n pass 

527 E112: for item in items:\npass 

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

529 

530 Okay: a = 1\nb = 2 

531 E113: a = 1\n b = 2 

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

533 """ 

534 c = 0 if logical_line else 3 

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

536 if indent_level % indent_size: 

537 yield 0, tmpl % ( 

538 1 + c, 

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

540 ) 

541 indent_expect = previous_logical.endswith(':') 

542 if indent_expect and indent_level <= previous_indent_level: 

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

544 elif not indent_expect and indent_level > previous_indent_level: 

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

546 

547 if indent_expect: 

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

549 expected_indent_level = previous_indent_level + expected_indent_amount 

550 if indent_level > expected_indent_level: 

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

552 

553 

554@register_check 

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

556 indent_char, indent_size, noqa, verbose): 

557 r"""Continuation lines indentation. 

558 

559 Continuation lines should align wrapped elements either vertically 

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

561 and braces, or using a hanging indent. 

562 

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

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

565 - further indentation should be used to clearly distinguish itself 

566 as a continuation line. 

567 

568 Okay: a = (\n) 

569 E123: a = (\n ) 

570 

571 Okay: a = (\n 42) 

572 E121: a = (\n 42) 

573 E122: a = (\n42) 

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

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

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

577 E126: a = (\n 42) 

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

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

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

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

582 """ 

583 first_row = tokens[0][2][0] 

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

585 if noqa or nrows == 1: 

586 return 

587 

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

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

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

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

592 indent_next = logical_line.endswith(':') 

593 

594 row = depth = 0 

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

596 else (indent_size, indent_size * 2) 

597 # remember how many brackets were opened on each line 

598 parens = [0] * nrows 

599 # relative indents of physical lines 

600 rel_indent = [0] * nrows 

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

602 open_rows = [[0]] 

603 # for each depth, memorize the hanging indentation 

604 hangs = [None] 

605 # visual indents 

606 indent_chances = {} 

607 last_indent = tokens[0][2] 

608 visual_indent = None 

609 last_token_multiline = False 

610 # for each depth, memorize the visual indent column 

611 indent = [last_indent[1]] 

612 if verbose >= 3: 

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

614 

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

616 

617 newline = row < start[0] - first_row 

618 if newline: 

619 row = start[0] - first_row 

620 newline = not last_token_multiline and token_type not in NEWLINE 

621 

622 if newline: 

623 # this is the beginning of a continuation line. 

624 last_indent = start 

625 if verbose >= 3: 

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

627 

628 # record the initial indent. 

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

630 

631 # identify closing bracket 

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

633 

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

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

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

637 hanging_indent = hang in valid_hangs 

638 if hanging_indent: 

639 break 

640 if hangs[depth]: 

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

642 # is there any chance of visual indent? 

643 visual_indent = (not close_bracket and hang > 0 and 

644 indent_chances.get(start[1])) 

645 

646 if close_bracket and indent[depth]: 

647 # closing bracket for visual indent 

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

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

650 "visual indentation") 

651 elif close_bracket and not hang: 

652 # closing bracket matches indentation of opening 

653 # bracket's line 

654 if hang_closing: 

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

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

657 if visual_indent is not True: 

658 # visual indent is broken 

659 yield (start, "E128 continuation line " 

660 "under-indented for visual indent") 

661 elif hanging_indent or (indent_next and 

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

663 # hanging indent is verified 

664 if close_bracket and not hang_closing: 

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

666 "indentation of opening bracket's line") 

667 hangs[depth] = hang 

668 elif visual_indent is True: 

669 # visual indent is verified 

670 indent[depth] = start[1] 

671 elif visual_indent in (text, str): 

672 # ignore token lined up with matching one from a 

673 # previous line 

674 pass 

675 else: 

676 # indent is broken 

677 if hang <= 0: 

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

679 elif indent[depth]: 

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

681 elif not close_bracket and hangs[depth]: 

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

683 else: 

684 hangs[depth] = hang 

685 if hang > indent_size: 

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

687 else: 

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

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

690 

691 # look for visual indenting 

692 if (parens[row] and 

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

694 not indent[depth]): 

695 indent[depth] = start[1] 

696 indent_chances[start[1]] = True 

697 if verbose >= 4: 

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

699 # deal with implicit string concatenation 

700 elif token_type in (tokenize.STRING, tokenize.COMMENT, FSTRING_START): 

701 indent_chances[start[1]] = str 

702 # visual indent after assert/raise/with 

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

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

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

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

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

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

709 open_rows[depth].append(row) 

710 

711 # keep track of bracket depth 

712 if token_type == tokenize.OP: 

713 if text in '([{': 

714 depth += 1 

715 indent.append(0) 

716 hangs.append(None) 

717 if len(open_rows) == depth: 

718 open_rows.append([]) 

719 open_rows[depth].append(row) 

720 parens[row] += 1 

721 if verbose >= 4: 

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

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

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

725 # parent indents should not be more than this one 

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

727 hangs.pop() 

728 for d in range(depth): 

729 if indent[d] > prev_indent: 

730 indent[d] = 0 

731 for ind in list(indent_chances): 

732 if ind >= prev_indent: 

733 del indent_chances[ind] 

734 del open_rows[depth + 1:] 

735 depth -= 1 

736 if depth: 

737 indent_chances[indent[depth]] = True 

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

739 if parens[idx]: 

740 parens[idx] -= 1 

741 break 

742 assert len(indent) == depth + 1 

743 if start[1] not in indent_chances: 

744 # allow lining up tokens 

745 indent_chances[start[1]] = text 

746 

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

748 if last_token_multiline: 

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

750 

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

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

753 if visual_indent: 

754 code = "E129 visually indented line" 

755 else: 

756 code = "E125 continuation line" 

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

758 

759 

760@register_check 

761def whitespace_before_parameters(logical_line, tokens): 

762 r"""Avoid extraneous whitespace. 

763 

764 Avoid extraneous whitespace in the following situations: 

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

766 function call. 

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

768 

769 Okay: spam(1) 

770 E211: spam (1) 

771 

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

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

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

775 """ 

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

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

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

779 if ( 

780 token_type == tokenize.OP and 

781 text in '([' and 

782 start != prev_end and 

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

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

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

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

787 not keyword.iskeyword(prev_text) and 

788 ( 

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

790 prev_text == 'type' or 

791 not keyword.issoftkeyword(prev_text) 

792 ) 

793 ): 

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

795 prev_type = token_type 

796 prev_text = text 

797 prev_end = end 

798 

799 

800@register_check 

801def whitespace_around_operator(logical_line): 

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

803 

804 Okay: a = 12 + 3 

805 E221: a = 4 + 5 

806 E222: a = 4 + 5 

807 E223: a = 4\t+ 5 

808 E224: a = 4 +\t5 

809 """ 

810 for match in OPERATOR_REGEX.finditer(logical_line): 

811 before, after = match.groups() 

812 

813 if '\t' in before: 

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

815 elif len(before) > 1: 

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

817 

818 if '\t' in after: 

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

820 elif len(after) > 1: 

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

822 

823 

824@register_check 

825def missing_whitespace(logical_line, tokens): 

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

827 

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

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

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

831 Booleans (and, or, not). 

832 

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

834 

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

836 whitespace around the operators with the lowest priorities. 

837 

838 Okay: i = i + 1 

839 Okay: submitted += 1 

840 Okay: x = x * 2 - 1 

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

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

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

844 Okay: alpha[:-i] 

845 Okay: [a, b] 

846 Okay: (3,) 

847 Okay: a[3,] = 1 

848 Okay: a[1:4] 

849 Okay: a[:4] 

850 Okay: a[1:] 

851 Okay: a[1:4:2] 

852 

853 E225: i=i+1 

854 E225: submitted +=1 

855 E225: x = x /2 - 1 

856 E225: z = x **y 

857 E225: z = 1and 1 

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

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

860 E227: c = a|b 

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

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

863 E231: foo(bar,baz) 

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

865 """ 

866 need_space = False 

867 prev_type = tokenize.OP 

868 prev_text = prev_end = None 

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

870 brace_stack = [] 

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

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

873 brace_stack.append(text) 

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

875 brace_stack.append('f') 

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

877 brace_stack.append('l') 

878 elif brace_stack: 

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

880 brace_stack.pop() 

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

882 brace_stack.pop() 

883 elif ( 

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

885 token_type == tokenize.OP and 

886 text == ':' 

887 ): 

888 brace_stack.pop() 

889 

890 if token_type in SKIP_COMMENTS: 

891 continue 

892 

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

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

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

896 # slice 

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

898 pass 

899 # 3.12+ fstring format specifier 

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

901 pass 

902 # tuple (and list for some reason?) 

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

904 pass 

905 else: 

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

907 

908 if need_space: 

909 if start != prev_end: 

910 # Found a (probably) needed space 

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

912 yield (need_space[0], 

913 "E225 missing whitespace around operator") 

914 need_space = False 

915 elif ( 

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

917 # ^ 

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

919 # ^ 

920 # f = lambda a, /: 

921 # ^ 

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

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

924 # ^ 

925 prev_text == ')' and text == ':' 

926 ): 

927 # Tolerate the "/" operator in function definition 

928 # For more info see PEP570 

929 pass 

930 else: 

931 if need_space is True or need_space[1]: 

932 # A needed trailing space was not found 

933 yield prev_end, "E225 missing whitespace around operator" 

934 elif prev_text != '**': 

935 code, optype = 'E226', 'arithmetic' 

936 if prev_text == '%': 

937 code, optype = 'E228', 'modulo' 

938 elif prev_text not in ARITHMETIC_OP: 

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

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

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

942 need_space = False 

943 elif token_type in operator_types and prev_end is not None: 

944 if ( 

945 text == '=' and ( 

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

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

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

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

950 # allow python 3.8 fstring repr specifier 

951 brace_stack[-2:] == ['f', '{'] 

952 ) 

953 ): 

954 pass 

955 elif text in WS_NEEDED_OPERATORS: 

956 need_space = True 

957 elif text in UNARY_OPERATORS: 

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

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

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

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

962 prev_type != tokenize.OP and 

963 prev_text not in KEYWORDS and 

964 not keyword.issoftkeyword(prev_text) 

965 ): 

966 need_space = None 

967 elif text in WS_OPTIONAL_OPERATORS: 

968 need_space = None 

969 

970 if need_space is None: 

971 # Surrounding space is optional, but ensure that 

972 # trailing space matches opening space 

973 need_space = (prev_end, start != prev_end) 

974 elif need_space and start == prev_end: 

975 # A needed opening space was not found 

976 yield prev_end, "E225 missing whitespace around operator" 

977 need_space = False 

978 prev_type = token_type 

979 prev_text = text 

980 prev_end = end 

981 

982 

983@register_check 

984def whitespace_around_comma(logical_line): 

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

986 

987 Note: these checks are disabled by default 

988 

989 Okay: a = (1, 2) 

990 E241: a = (1, 2) 

991 E242: a = (1,\t2) 

992 """ 

993 line = logical_line 

994 for m in WHITESPACE_AFTER_COMMA_REGEX.finditer(line): 

995 found = m.start() + 1 

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

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

998 else: 

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

1000 

1001 

1002@register_check 

1003def whitespace_around_named_parameter_equals(logical_line, tokens): 

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

1005 

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

1007 keyword argument or a default parameter value, except when 

1008 using a type annotation. 

1009 

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

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

1012 Okay: boolean(a == b) 

1013 Okay: boolean(a != b) 

1014 Okay: boolean(a <= b) 

1015 Okay: boolean(a >= b) 

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

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

1018 

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

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

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

1022 """ 

1023 paren_stack = [] 

1024 no_space = False 

1025 require_space = False 

1026 prev_end = None 

1027 annotated_func_arg = False 

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

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

1030 

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

1032 missing_message = "E252 missing whitespace around parameter equals" 

1033 

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

1035 if token_type == tokenize.NL: 

1036 continue 

1037 if no_space: 

1038 no_space = False 

1039 if start != prev_end: 

1040 yield (prev_end, message) 

1041 if require_space: 

1042 require_space = False 

1043 if start == prev_end: 

1044 yield (prev_end, missing_message) 

1045 if token_type == tokenize.OP: 

1046 if text in '([': 

1047 paren_stack.append(text) 

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

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

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

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

1052 if in_generic and paren_stack == ['[']: 

1053 annotated_func_arg = True 

1054 elif text in ')]' and paren_stack: 

1055 paren_stack.pop() 

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

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

1058 annotated_func_arg = True 

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

1060 annotated_func_arg = False 

1061 elif paren_stack and text == '=': 

1062 if annotated_func_arg and len(paren_stack) == 1: 

1063 require_space = True 

1064 if start == prev_end: 

1065 yield (prev_end, missing_message) 

1066 else: 

1067 no_space = True 

1068 if start != prev_end: 

1069 yield (prev_end, message) 

1070 if not paren_stack: 

1071 annotated_func_arg = False 

1072 

1073 prev_end = end 

1074 

1075 

1076@register_check 

1077def whitespace_before_comment(logical_line, tokens): 

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

1079 

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

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

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

1083 

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

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

1086 

1087 Okay: x = x + 1 # Increment x 

1088 Okay: x = x + 1 # Increment x 

1089 Okay: # Block comments: 

1090 Okay: # - Block comment list 

1091 Okay: # \xa0- Block comment list 

1092 E261: x = x + 1 # Increment x 

1093 E262: x = x + 1 #Increment x 

1094 E262: x = x + 1 # Increment x 

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

1096 E265: #Block comment 

1097 E266: ### Block comment 

1098 """ 

1099 prev_end = (0, 0) 

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

1101 if token_type == tokenize.COMMENT: 

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

1103 if inline_comment: 

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

1105 yield (prev_end, 

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

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

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

1109 if inline_comment: 

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

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

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

1113 if bad_prefix != '#': 

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

1115 elif comment: 

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

1117 elif token_type != tokenize.NL: 

1118 prev_end = end 

1119 

1120 

1121@register_check 

1122def imports_on_separate_lines(logical_line): 

1123 r"""Place imports on separate lines. 

1124 

1125 Okay: import os\nimport sys 

1126 E401: import sys, os 

1127 

1128 Okay: from subprocess import Popen, PIPE 

1129 Okay: from myclas import MyClass 

1130 Okay: from foo.bar.yourclass import YourClass 

1131 Okay: import myclass 

1132 Okay: import foo.bar.yourclass 

1133 """ 

1134 line = logical_line 

1135 if line.startswith('import '): 

1136 found = line.find(',') 

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

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

1139 

1140 

1141@register_check 

1142def module_imports_on_top_of_file( 

1143 logical_line, indent_level, checker_state, noqa): 

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

1145 

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

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

1148 

1149 Okay: import os 

1150 Okay: # this is a comment\nimport os 

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

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

1153 E402: a=1\nimport os 

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

1155 E402: a=1\nfrom sys import x 

1156 

1157 Okay: if x:\n import os 

1158 """ # noqa 

1159 def is_string_literal(line): 

1160 if line[0] in 'uUbB': 

1161 line = line[1:] 

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

1163 line = line[1:] 

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

1165 

1166 allowed_keywords = ( 

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

1168 

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

1170 return 

1171 if not logical_line: # Allow empty lines or comments 

1172 return 

1173 if noqa: 

1174 return 

1175 line = logical_line 

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

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

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

1179 elif re.match(DUNDER_REGEX, line): 

1180 return 

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

1182 # Allow certain keywords intermixed with imports in order to 

1183 # support conditional or filtered importing 

1184 return 

1185 elif is_string_literal(line): 

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

1187 # error. 

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

1189 checker_state['seen_non_imports'] = True 

1190 else: 

1191 checker_state['seen_docstring'] = True 

1192 else: 

1193 checker_state['seen_non_imports'] = True 

1194 

1195 

1196@register_check 

1197def compound_statements(logical_line): 

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

1199 discouraged. 

1200 

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

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

1203 Also avoid folding such long lines! 

1204 

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

1206 binds a lambda expression directly to a name. 

1207 

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

1209 Okay: do_one() 

1210 Okay: do_two() 

1211 Okay: do_three() 

1212 

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

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

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

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

1217 E701: else: do_non_blah_thing() 

1218 E701: try: something() 

1219 E701: finally: cleanup() 

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

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

1222 E703: do_four(); # useless semicolon 

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

1224 E731: f = lambda x: 2*x 

1225 """ 

1226 line = logical_line 

1227 last_char = len(line) - 1 

1228 found = line.find(':') 

1229 prev_found = 0 

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

1231 while -1 < found < last_char: 

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

1233 if ( 

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

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

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

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

1238 ): 

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

1240 if lambda_kw: 

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

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

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

1244 "def") 

1245 break 

1246 if STARTSWITH_DEF_REGEX.match(line): 

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

1248 elif STARTSWITH_INDENT_STATEMENT_REGEX.match(line): 

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

1250 prev_found = found 

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

1252 found = line.find(';') 

1253 while -1 < found: 

1254 if found < last_char: 

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

1256 else: 

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

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

1259 

1260 

1261@register_check 

1262def explicit_line_join(logical_line, tokens): 

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

1264 

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

1266 implied line continuation inside parentheses, brackets and braces. 

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

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

1269 backslash for line continuation. 

1270 

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

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

1273 

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

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

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

1277 Okay: aaa = 123 # \\ 

1278 """ 

1279 prev_start = prev_end = parens = 0 

1280 comment = False 

1281 backslash = None 

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

1283 if token_type == tokenize.COMMENT: 

1284 comment = True 

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

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

1287 if start[0] != prev_start: 

1288 comment = False # Reset comment flag on newline 

1289 if end[0] != prev_end: 

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

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

1292 else: 

1293 backslash = None 

1294 prev_start = prev_end = end[0] 

1295 else: 

1296 prev_start = start[0] 

1297 if token_type == tokenize.OP: 

1298 if text in '([{': 

1299 parens += 1 

1300 elif text in ')]}': 

1301 parens -= 1 

1302 

1303 

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

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

1306# after a line break. 

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

1308 

1309 

1310def _is_binary_operator(token_type, text): 

1311 return ( 

1312 token_type == tokenize.OP or 

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

1314 ) and ( 

1315 text not in _SYMBOLIC_OPS 

1316 ) 

1317 

1318 

1319def _break_around_binary_operators(tokens): 

1320 """Private function to reduce duplication. 

1321 

1322 This factors out the shared details between 

1323 :func:`break_before_binary_operator` and 

1324 :func:`break_after_binary_operator`. 

1325 """ 

1326 line_break = False 

1327 unary_context = True 

1328 # Previous non-newline token types and text 

1329 previous_token_type = None 

1330 previous_text = None 

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

1332 if token_type == tokenize.COMMENT: 

1333 continue 

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

1335 line_break = True 

1336 else: 

1337 yield (token_type, text, previous_token_type, previous_text, 

1338 line_break, unary_context, start) 

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

1340 line_break = False 

1341 previous_token_type = token_type 

1342 previous_text = text 

1343 

1344 

1345@register_check 

1346def break_before_binary_operator(logical_line, tokens): 

1347 r""" 

1348 Avoid breaks before binary operators. 

1349 

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

1351 operator, not before it. 

1352 

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

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

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

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

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

1358 

1359 Okay: foo(\n -x) 

1360 Okay: foo(x\n []) 

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

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

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

1364 """ 

1365 for context in _break_around_binary_operators(tokens): 

1366 (token_type, text, previous_token_type, previous_text, 

1367 line_break, unary_context, start) = context 

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

1369 not unary_context and 

1370 not _is_binary_operator(previous_token_type, 

1371 previous_text)): 

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

1373 

1374 

1375@register_check 

1376def break_after_binary_operator(logical_line, tokens): 

1377 r""" 

1378 Avoid breaks after binary operators. 

1379 

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

1381 operator, not after it. 

1382 

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

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

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

1386 

1387 Okay: foo(\n -x) 

1388 Okay: foo(x\n []) 

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

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

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

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

1393 

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

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

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

1397 """ 

1398 prev_start = None 

1399 for context in _break_around_binary_operators(tokens): 

1400 (token_type, text, previous_token_type, previous_text, 

1401 line_break, unary_context, start) = context 

1402 if (_is_binary_operator(previous_token_type, previous_text) and 

1403 line_break and 

1404 not unary_context and 

1405 not _is_binary_operator(token_type, text)): 

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

1407 prev_start = start 

1408 

1409 

1410@register_check 

1411def comparison_to_singleton(logical_line, noqa): 

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

1413 

1414 Comparisons to singletons like None should always be done 

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

1416 

1417 Okay: if arg is not None: 

1418 E711: if arg != None: 

1419 E711: if None == arg: 

1420 E712: if arg == True: 

1421 E712: if False == arg: 

1422 

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

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

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

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

1427 """ 

1428 if noqa: 

1429 return 

1430 

1431 for match in COMPARE_SINGLETON_REGEX.finditer(logical_line): 

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

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

1434 

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

1436 if singleton in ('None',): 

1437 code = 'E711' 

1438 else: 

1439 code = 'E712' 

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

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

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

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

1444 (code, singleton, msg)) 

1445 

1446 

1447@register_check 

1448def comparison_negative(logical_line): 

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

1450 

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

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

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

1454 Okay: zz = x is not y 

1455 E713: Z = not X in Y 

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

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

1458 E714: Z = not X.B is Y 

1459 """ 

1460 match = COMPARE_NEGATIVE_REGEX.search(logical_line) 

1461 if match: 

1462 pos = match.start(1) 

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

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

1465 else: 

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

1467 

1468 

1469@register_check 

1470def comparison_type(logical_line, noqa): 

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

1472 

1473 Do not compare types directly. 

1474 

1475 Okay: if isinstance(obj, int): 

1476 Okay: if type(obj) is int: 

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

1478 """ 

1479 match = COMPARE_TYPE_REGEX.search(logical_line) 

1480 if match and not noqa: 

1481 inst = match.group(1) 

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

1483 return # Allow comparison for types which are not obvious 

1484 yield ( 

1485 match.start(), 

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

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

1488 ) 

1489 

1490 

1491@register_check 

1492def bare_except(logical_line, noqa): 

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

1494 possible. 

1495 

1496 Okay: except Exception: 

1497 Okay: except BaseException: 

1498 E722: except: 

1499 """ 

1500 if noqa: 

1501 return 

1502 

1503 match = BLANK_EXCEPT_REGEX.match(logical_line) 

1504 if match: 

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

1506 

1507 

1508@register_check 

1509def ambiguous_identifier(logical_line, tokens): 

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

1511 

1512 In some fonts, these characters are indistinguishable from the 

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

1514 

1515 Okay: L = 0 

1516 Okay: o = 123 

1517 Okay: i = 42 

1518 E741: l = 0 

1519 E741: O = 123 

1520 E741: I = 42 

1521 

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

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

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

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

1526 

1527 Okay: except AttributeError as o: 

1528 Okay: with lock as L: 

1529 Okay: foo(l=12) 

1530 Okay: foo(l=I) 

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

1532 Okay: lambda arg: arg * l 

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

1534 Okay: lambda x=a.I: None 

1535 Okay: if l >= 12: 

1536 E741: except AttributeError as O: 

1537 E741: with lock as l: 

1538 E741: global I 

1539 E741: nonlocal l 

1540 E741: def foo(l): 

1541 E741: def foo(l=12): 

1542 E741: l = foo(l=12) 

1543 E741: for l in range(10): 

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

1545 E741: lambda l: None 

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

1547 E741: lambda **l: 

1548 E741: def f(**l): 

1549 E742: class I(object): 

1550 E743: def l(x): 

1551 """ 

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

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

1554 brace_depth = 0 

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

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

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

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

1559 ident = pos = None 

1560 # find function definitions 

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

1562 func_depth = brace_depth 

1563 seen_colon = False 

1564 elif ( 

1565 func_depth is not None and 

1566 text == ':' and 

1567 brace_depth == func_depth 

1568 ): 

1569 seen_colon = True 

1570 # update parameter parentheses level 

1571 if text in '([{': 

1572 brace_depth += 1 

1573 elif text in ')]}': 

1574 brace_depth -= 1 

1575 # identifiers on the lhs of an assignment operator 

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

1577 if prev_text in idents_to_avoid: 

1578 ident = prev_text 

1579 pos = prev_start 

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

1581 # 'global', or 'nonlocal' 

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

1583 if text in idents_to_avoid: 

1584 ident = text 

1585 pos = start 

1586 # function / lambda parameter definitions 

1587 if ( 

1588 func_depth is not None and 

1589 not seen_colon and 

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

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

1592 text in idents_to_avoid 

1593 ): 

1594 ident = text 

1595 pos = start 

1596 if prev_text == 'class': 

1597 if text in idents_to_avoid: 

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

1599 if prev_text == 'def': 

1600 if text in idents_to_avoid: 

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

1602 if ident: 

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

1604 prev_text = text 

1605 prev_start = start 

1606 

1607 

1608@register_check 

1609def python_3000_invalid_escape_sequence(logical_line, tokens, noqa): 

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

1611 

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

1613 W605: regex = '\.png$' 

1614 """ 

1615 if noqa: 

1616 return 

1617 

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

1619 valid = [ 

1620 '\n', 

1621 '\\', 

1622 '\'', 

1623 '"', 

1624 'a', 

1625 'b', 

1626 'f', 

1627 'n', 

1628 'r', 

1629 't', 

1630 'v', 

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

1632 'x', 

1633 

1634 # Escape sequences only recognized in string literals 

1635 'N', 

1636 'u', 

1637 'U', 

1638 ] 

1639 

1640 prefixes = [] 

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

1642 if token_type in {tokenize.STRING, FSTRING_START}: 

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

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

1645 

1646 if token_type in {tokenize.STRING, FSTRING_MIDDLE}: 

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

1648 start_line, start_col = start 

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

1650 while pos >= 0: 

1651 pos += 1 

1652 if text[pos] not in valid: 

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

1654 if line == start_line: 

1655 col = start_col + pos 

1656 else: 

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

1658 yield ( 

1659 (line, col - 1), 

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

1661 ) 

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

1663 

1664 if token_type in {tokenize.STRING, FSTRING_END}: 

1665 prefixes.pop() 

1666 

1667 

1668######################################################################## 

1669@register_check 

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

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

1672 

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

1674 the length to 72 characters is recommended. 

1675 

1676 Reports warning W505 

1677 """ 

1678 if max_doc_length is None or noqa: 

1679 return 

1680 

1681 prev_token = None 

1682 skip_lines = set() 

1683 # Skip lines that 

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

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

1686 skip_lines.add(line) 

1687 

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

1689 # Skip lines that aren't pure strings 

1690 if token_type == tokenize.STRING and skip_lines: 

1691 continue 

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

1693 # Only check comment-only lines 

1694 if prev_token is None or prev_token in SKIP_TOKENS: 

1695 lines = line.splitlines() 

1696 for line_num, physical_line in enumerate(lines): 

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

1698 return 

1699 length = len(physical_line) 

1700 chunks = physical_line.split() 

1701 if token_type == tokenize.COMMENT: 

1702 if (len(chunks) == 2 and 

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

1704 continue 

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

1706 if (len(chunks) == 1 and 

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

1708 continue 

1709 if length > max_doc_length: 

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

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

1712 "(%d > %d characters)" 

1713 % (length, max_doc_length)) 

1714 prev_token = token_type 

1715 

1716 

1717######################################################################## 

1718# Helper functions 

1719######################################################################## 

1720 

1721 

1722def readlines(filename): 

1723 """Read the source code.""" 

1724 try: 

1725 with tokenize.open(filename) as f: 

1726 return f.readlines() 

1727 except (LookupError, SyntaxError, UnicodeError): 

1728 # Fall back if file encoding is improperly declared 

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

1730 return f.readlines() 

1731 

1732 

1733def stdin_get_value(): 

1734 """Read the value from stdin.""" 

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

1736 

1737 

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

1739 

1740 

1741def expand_indent(line): 

1742 r"""Return the amount of indentation. 

1743 

1744 Tabs are expanded to the next multiple of 8. 

1745 """ 

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

1747 if '\t' not in line: 

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

1749 result = 0 

1750 for char in line: 

1751 if char == '\t': 

1752 result = result // 8 * 8 + 8 

1753 elif char == ' ': 

1754 result += 1 

1755 else: 

1756 break 

1757 return result 

1758 

1759 

1760def mute_string(text): 

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

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

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

1764 end = len(text) - 1 

1765 # Triple quotes 

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

1767 start += 2 

1768 end -= 2 

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

1770 

1771 

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

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

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

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

1776 rv = {} 

1777 path = nrows = None 

1778 for line in diff.splitlines(): 

1779 if nrows: 

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

1781 nrows -= 1 

1782 continue 

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

1784 hunk_match = HUNK_REGEX.match(line) 

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

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

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

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

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

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

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

1792 path = path[2:] 

1793 rv[path] = set() 

1794 return { 

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

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

1797 if rows and filename_match(filepath, patterns) 

1798 } 

1799 

1800 

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

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

1803 

1804 Return a list of absolute paths. 

1805 """ 

1806 if not value: 

1807 return [] 

1808 if isinstance(value, list): 

1809 return value 

1810 paths = [] 

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

1812 path = path.strip() 

1813 if '/' in path: 

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

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

1816 return paths 

1817 

1818 

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

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

1821 

1822 If patterns is unspecified, this always returns True. 

1823 """ 

1824 if not patterns: 

1825 return default 

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

1827 

1828 

1829def update_counts(s, counts): 

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

1831 for characters in counts""" 

1832 for char in s: 

1833 if char in counts: 

1834 counts[char] += 1 

1835 

1836 

1837def _is_eol_token(token): 

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

1839 

1840 

1841######################################################################## 

1842# Framework to run all checks 

1843######################################################################## 

1844 

1845 

1846class Checker: 

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

1848 

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

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

1851 if options is None: 

1852 options = StyleGuide(kwargs).options 

1853 else: 

1854 assert not kwargs 

1855 self._io_error = None 

1856 self._physical_checks = options.physical_checks 

1857 self._logical_checks = options.logical_checks 

1858 self._ast_checks = options.ast_checks 

1859 self.max_line_length = options.max_line_length 

1860 self.max_doc_length = options.max_doc_length 

1861 self.indent_size = options.indent_size 

1862 self.fstring_start = 0 

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

1864 self.hang_closing = options.hang_closing 

1865 self.indent_size = options.indent_size 

1866 self.verbose = options.verbose 

1867 self.filename = filename 

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

1869 self._checker_states = {} 

1870 if filename is None: 

1871 self.filename = 'stdin' 

1872 self.lines = lines or [] 

1873 elif filename == '-': 

1874 self.filename = 'stdin' 

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

1876 elif lines is None: 

1877 try: 

1878 self.lines = readlines(filename) 

1879 except OSError: 

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

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

1882 self.lines = [] 

1883 else: 

1884 self.lines = lines 

1885 if self.lines: 

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

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

1888 if ord0 == 0xfeff: 

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

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

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

1892 self.report = report or options.report 

1893 self.report_error = self.report.error 

1894 self.noqa = False 

1895 

1896 def report_invalid_syntax(self): 

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

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

1899 if len(exc.args) > 1: 

1900 offset = exc.args[1] 

1901 if len(offset) > 2: 

1902 offset = offset[1:3] 

1903 else: 

1904 offset = (1, 0) 

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

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

1907 self.report_invalid_syntax) 

1908 

1909 def readline(self): 

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

1911 if self.line_number >= self.total_lines: 

1912 return '' 

1913 line = self.lines[self.line_number] 

1914 self.line_number += 1 

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

1916 self.indent_char = line[0] 

1917 return line 

1918 

1919 def run_check(self, check, argument_names): 

1920 """Run a check plugin.""" 

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

1922 return check(*arguments) 

1923 

1924 def init_checker_state(self, name, argument_names): 

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

1926 if 'checker_state' in argument_names: 

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

1928 

1929 def check_physical(self, line): 

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

1931 self.physical_line = line 

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

1933 self.init_checker_state(name, argument_names) 

1934 result = self.run_check(check, argument_names) 

1935 if result is not None: 

1936 (offset, text) = result 

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

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

1939 self.indent_char = line[0] 

1940 

1941 def build_tokens_line(self): 

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

1943 logical = [] 

1944 comments = [] 

1945 length = 0 

1946 prev_row = prev_col = mapping = None 

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

1948 if token_type in SKIP_TOKENS: 

1949 continue 

1950 if not mapping: 

1951 mapping = [(0, start)] 

1952 if token_type == tokenize.COMMENT: 

1953 comments.append(text) 

1954 continue 

1955 if token_type == tokenize.STRING: 

1956 text = mute_string(text) 

1957 elif token_type == FSTRING_MIDDLE: # pragma: >=3.12 cover 

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

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

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

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

1962 if prev_row: 

1963 (start_row, start_col) = start 

1964 if prev_row != start_row: # different row 

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

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

1967 text not in '}])'): 

1968 text = ' ' + text 

1969 elif prev_col != start_col: # different column 

1970 text = line[prev_col:start_col] + text 

1971 logical.append(text) 

1972 length += len(text) 

1973 mapping.append((length, end)) 

1974 (prev_row, prev_col) = end 

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

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

1977 return mapping 

1978 

1979 def check_logical(self): 

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

1981 self.report.increment_logical_line() 

1982 mapping = self.build_tokens_line() 

1983 if not mapping: 

1984 return 

1985 

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

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

1988 start_line = self.lines[start_row - 1] 

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

1990 if self.blank_before < self.blank_lines: 

1991 self.blank_before = self.blank_lines 

1992 if self.verbose >= 2: 

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

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

1995 if self.verbose >= 4: 

1996 print(' ' + name) 

1997 self.init_checker_state(name, argument_names) 

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

1999 if not isinstance(offset, tuple): 

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

2001 # to find a given offset in them. 

2002 token_offset, pos = mapping[bisect.bisect_left( 

2003 mapping_offsets, offset)] 

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

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

2006 if self.logical_line: 

2007 self.previous_indent_level = self.indent_level 

2008 self.previous_logical = self.logical_line 

2009 if not self.indent_level: 

2010 self.previous_unindented_logical_line = self.logical_line 

2011 self.blank_lines = 0 

2012 self.tokens = [] 

2013 

2014 def check_ast(self): 

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

2016 try: 

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

2018 except (ValueError, SyntaxError, TypeError): 

2019 return self.report_invalid_syntax() 

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

2021 checker = cls(tree, self.filename) 

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

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

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

2025 

2026 def generate_tokens(self): 

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

2028 if self._io_error: 

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

2030 tokengen = tokenize.generate_tokens(self.readline) 

2031 try: 

2032 prev_physical = '' 

2033 for token in tokengen: 

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

2035 return 

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

2037 self.maybe_check_physical(token, prev_physical) 

2038 yield token 

2039 prev_physical = token[4] 

2040 except (SyntaxError, tokenize.TokenError): 

2041 self.report_invalid_syntax() 

2042 

2043 def maybe_check_physical(self, token, prev_physical): 

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

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

2046 

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

2048 self.fstring_start = token.start[0] 

2049 # a newline token ends a single physical line. 

2050 elif _is_eol_token(token): 

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

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

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

2054 if token.line == '': 

2055 self.check_physical(prev_physical) 

2056 else: 

2057 self.check_physical(token.line) 

2058 elif ( 

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

2060 token.type == FSTRING_END 

2061 ): 

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

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

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

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

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

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

2068 # physical line. 

2069 # 

2070 # Subtleties: 

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

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

2073 # physical checks for the entire multiline string 

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

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

2076 # check_physical() to give accurate feedback 

2077 if noqa(token.line): 

2078 return 

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

2080 start = self.fstring_start 

2081 else: 

2082 start = token.start[0] 

2083 end = token.end[0] 

2084 

2085 self.multiline = True 

2086 self.line_number = start 

2087 for line_number in range(start, end): 

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

2089 self.line_number += 1 

2090 self.multiline = False 

2091 

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

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

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

2095 self.total_lines = len(self.lines) 

2096 if self._ast_checks: 

2097 self.check_ast() 

2098 self.line_number = 0 

2099 self.indent_char = None 

2100 self.indent_level = self.previous_indent_level = 0 

2101 self.previous_logical = '' 

2102 self.previous_unindented_logical_line = '' 

2103 self.tokens = [] 

2104 self.blank_lines = self.blank_before = 0 

2105 parens = 0 

2106 for token in self.generate_tokens(): 

2107 self.tokens.append(token) 

2108 token_type, text = token[0:2] 

2109 if self.verbose >= 3: 

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

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

2112 else: 

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

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

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

2116 if token_type == tokenize.OP: 

2117 if text in '([{': 

2118 parens += 1 

2119 elif text in '}])': 

2120 parens -= 1 

2121 elif not parens: 

2122 if token_type in NEWLINE: 

2123 if token_type == tokenize.NEWLINE: 

2124 self.check_logical() 

2125 self.blank_before = 0 

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

2127 # The physical line contains only this token. 

2128 self.blank_lines += 1 

2129 del self.tokens[0] 

2130 else: 

2131 self.check_logical() 

2132 if self.tokens: 

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

2134 self.check_logical() 

2135 return self.report.get_file_results() 

2136 

2137 

2138class BaseReport: 

2139 """Collect the results of the checks.""" 

2140 

2141 print_filename = False 

2142 

2143 def __init__(self, options): 

2144 self._benchmark_keys = options.benchmark_keys 

2145 self._ignore_code = options.ignore_code 

2146 # Results 

2147 self.elapsed = 0 

2148 self.total_errors = 0 

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

2150 self.messages = {} 

2151 

2152 def start(self): 

2153 """Start the timer.""" 

2154 self._start_time = time.time() 

2155 

2156 def stop(self): 

2157 """Stop the timer.""" 

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

2159 

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

2161 """Signal a new file.""" 

2162 self.filename = filename 

2163 self.lines = lines 

2164 self.expected = expected or () 

2165 self.line_offset = line_offset 

2166 self.file_errors = 0 

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

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

2169 

2170 def increment_logical_line(self): 

2171 """Signal a new logical line.""" 

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

2173 

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

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

2176 code = text[:4] 

2177 if self._ignore_code(code): 

2178 return 

2179 if code in self.counters: 

2180 self.counters[code] += 1 

2181 else: 

2182 self.counters[code] = 1 

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

2184 # Don't care about expected errors or warnings 

2185 if code in self.expected: 

2186 return 

2187 if self.print_filename and not self.file_errors: 

2188 print(self.filename) 

2189 self.file_errors += 1 

2190 self.total_errors += 1 

2191 return code 

2192 

2193 def get_file_results(self): 

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

2195 return self.file_errors 

2196 

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

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

2199 return sum(self.counters[key] 

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

2201 

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

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

2204 

2205 prefix='' matches all errors and warnings 

2206 prefix='E' matches all errors 

2207 prefix='W' matches all warnings 

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

2209 """ 

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

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

2212 

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

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

2215 for line in self.get_statistics(prefix): 

2216 print(line) 

2217 

2218 def print_benchmark(self): 

2219 """Print benchmark numbers.""" 

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

2221 if self.elapsed: 

2222 for key in self._benchmark_keys: 

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

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

2225 self.counters[key])) 

2226 

2227 

2228class FileReport(BaseReport): 

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

2230 

2231 print_filename = True 

2232 

2233 

2234class StandardReport(BaseReport): 

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

2236 

2237 def __init__(self, options): 

2238 super().__init__(options) 

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

2240 options.format) 

2241 self._repeat = options.repeat 

2242 self._show_source = options.show_source 

2243 self._show_pep8 = options.show_pep8 

2244 

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

2246 """Signal a new file.""" 

2247 self._deferred_print = [] 

2248 return super().init_file( 

2249 filename, lines, expected, line_offset) 

2250 

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

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

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

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

2255 self._deferred_print.append( 

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

2257 return code 

2258 

2259 def get_file_results(self): 

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

2261 self._deferred_print.sort() 

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

2263 print(self._fmt % { 

2264 'path': self.filename, 

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

2266 'code': code, 'text': text, 

2267 }) 

2268 if self._show_source: 

2269 if line_number > len(self.lines): 

2270 line = '' 

2271 else: 

2272 line = self.lines[line_number - 1] 

2273 print(line.rstrip()) 

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

2275 if self._show_pep8 and doc: 

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

2277 

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

2279 # line can be broken where buffer boundary since other 

2280 # processes write to same file. 

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

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

2283 # len(line) < 8192. 

2284 sys.stdout.flush() 

2285 return self.file_errors 

2286 

2287 

2288class DiffReport(StandardReport): 

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

2290 

2291 def __init__(self, options): 

2292 super().__init__(options) 

2293 self._selected = options.selected_lines 

2294 

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

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

2297 return 

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

2299 

2300 

2301class StyleGuide: 

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

2303 

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

2305 # build options from the command line 

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

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

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

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

2310 # build options from dict 

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

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

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

2314 options, self.paths = process_options( 

2315 arglist, parse_argv, config_file, parser, verbose) 

2316 if options_dict: 

2317 options.__dict__.update(options_dict) 

2318 if 'paths' in options_dict: 

2319 self.paths = options_dict['paths'] 

2320 

2321 self.runner = self.input_file 

2322 self.options = options 

2323 

2324 if not options.reporter: 

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

2326 

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

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

2329 # The default choice: ignore controversial checks 

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

2331 else: 

2332 # Ignore all checks which are not explicitly selected 

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

2334 options.benchmark_keys = BENCHMARK_KEYS[:] 

2335 options.ignore_code = self.ignore_code 

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

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

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

2339 self.init_report() 

2340 

2341 def init_report(self, reporter=None): 

2342 """Initialize the report instance.""" 

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

2344 return self.options.report 

2345 

2346 def check_files(self, paths=None): 

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

2348 if paths is None: 

2349 paths = self.paths 

2350 report = self.options.report 

2351 runner = self.runner 

2352 report.start() 

2353 try: 

2354 for path in paths: 

2355 if os.path.isdir(path): 

2356 self.input_dir(path) 

2357 elif not self.excluded(path): 

2358 runner(path) 

2359 except KeyboardInterrupt: 

2360 print('... stopped') 

2361 report.stop() 

2362 return report 

2363 

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

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

2366 if self.options.verbose: 

2367 print('checking %s' % filename) 

2368 fchecker = self.checker_class( 

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

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

2371 

2372 def input_dir(self, dirname): 

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

2374 dirname = dirname.rstrip('/') 

2375 if self.excluded(dirname): 

2376 return 0 

2377 counters = self.options.report.counters 

2378 verbose = self.options.verbose 

2379 filepatterns = self.options.filename 

2380 runner = self.runner 

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

2382 if verbose: 

2383 print('directory ' + root) 

2384 counters['directories'] += 1 

2385 for subdir in sorted(dirs): 

2386 if self.excluded(subdir, root): 

2387 dirs.remove(subdir) 

2388 for filename in sorted(files): 

2389 # contain a pattern that matches? 

2390 if ( 

2391 filename_match(filename, filepatterns) and 

2392 not self.excluded(filename, root) 

2393 ): 

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

2395 

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

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

2398 

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

2400 """ 

2401 if not self.options.exclude: 

2402 return False 

2403 basename = os.path.basename(filename) 

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

2405 return True 

2406 if parent: 

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

2408 filename = os.path.abspath(filename) 

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

2410 

2411 def ignore_code(self, code): 

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

2413 

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

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

2416 the error code, return True. 

2417 """ 

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

2419 for s in self.options.select): 

2420 return False 

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

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

2423 

2424 def get_checks(self, argument_name): 

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

2426 

2427 Find all globally visible functions where the first argument 

2428 name starts with argument_name and which contain selected tests. 

2429 """ 

2430 checks = [] 

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

2432 (codes, args) = attrs 

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

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

2435 return sorted(checks) 

2436 

2437 

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

2439 """Create the parser for the program.""" 

2440 parser = OptionParser(prog=prog, version=version, 

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

2442 parser.config_options = [ 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2459 "matching these comma separated patterns " 

2460 "(default: %default)") 

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

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

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

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

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

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

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

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

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

2470 "(implies --first)") 

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

2472 help="count errors and warnings") 

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

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

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

2476 "total is not null") 

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

2478 default=MAX_LINE_LENGTH, 

2479 help="set maximum allowed line length " 

2480 "(default: %default)") 

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

2482 default=None, 

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

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

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

2486 default=INDENT_SIZE, 

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

2488 "(default: %default)") 

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

2490 help="hang closing bracket instead of matching " 

2491 "indentation of opening bracket's line") 

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

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

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

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

2496 "the unified diff received on STDIN") 

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

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

2499 help="measure processing speed") 

2500 return parser 

2501 

2502 

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

2504 """Read and parse configurations. 

2505 

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

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

2508 

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

2510 local configurations in the current directory or above will be 

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

2512 ConfigParser. 

2513 """ 

2514 config = configparser.RawConfigParser() 

2515 

2516 cli_conf = options.config 

2517 

2518 local_dir = os.curdir 

2519 

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

2521 if options.verbose: 

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

2523 config.read(USER_CONFIG) 

2524 

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

2526 while tail: 

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

2528 local_dir = parent 

2529 if options.verbose: 

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

2531 break 

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

2533 

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

2535 if options.verbose: 

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

2537 config.read(cli_conf) 

2538 

2539 pycodestyle_section = None 

2540 if config.has_section(parser.prog): 

2541 pycodestyle_section = parser.prog 

2542 elif config.has_section('pep8'): 

2543 pycodestyle_section = 'pep8' # Deprecated 

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

2545 

2546 if pycodestyle_section: 

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

2548 

2549 # First, read the default values 

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

2551 

2552 # Second, parse the configuration 

2553 for opt in config.options(pycodestyle_section): 

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

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

2556 continue 

2557 if options.verbose > 1: 

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

2559 config.get(pycodestyle_section, opt))) 

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

2561 opt_type = option_list[normalized_opt] 

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

2563 value = config.getint(pycodestyle_section, opt) 

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

2565 value = config.getboolean(pycodestyle_section, opt) 

2566 else: 

2567 value = config.get(pycodestyle_section, opt) 

2568 if normalized_opt == 'exclude': 

2569 value = normalize_paths(value, local_dir) 

2570 setattr(new_options, normalized_opt, value) 

2571 

2572 # Third, overwrite with the command-line options 

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

2574 return options 

2575 

2576 

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

2578 parser=None, verbose=None): 

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

2580 

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

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

2583 """ 

2584 if not parser: 

2585 parser = get_parser() 

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

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

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

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

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

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

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

2593 help="user config file location") 

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

2595 if not arglist and not parse_argv: 

2596 arglist = [] 

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

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

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

2600 options.reporter = None 

2601 

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

2603 if verbose is not None: 

2604 options.verbose = verbose 

2605 

2606 if parse_argv and not args: 

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

2608 for name in PROJECT_CONFIG): 

2609 args = ['.'] 

2610 else: 

2611 parser.error('input not specified') 

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

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

2614 

2615 options.filename = _parse_multi_options(options.filename) 

2616 options.exclude = normalize_paths(options.exclude) 

2617 options.select = _parse_multi_options(options.select) 

2618 options.ignore = _parse_multi_options(options.ignore) 

2619 

2620 if options.diff: 

2621 options.reporter = DiffReport 

2622 stdin = stdin_get_value() 

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

2624 args = sorted(options.selected_lines) 

2625 

2626 return options, args 

2627 

2628 

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

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

2631 

2632 Turns the following: 

2633 

2634 A, 

2635 B, 

2636 

2637 into ["A", "B"] 

2638 """ 

2639 if options: 

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

2641 else: 

2642 return options 

2643 

2644 

2645def _main(): 

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

2647 import signal 

2648 

2649 # Handle "Broken pipe" gracefully 

2650 try: 

2651 signal.signal(signal.SIGPIPE, lambda signum, frame: sys.exit(1)) 

2652 except AttributeError: 

2653 pass # not supported on Windows 

2654 

2655 style_guide = StyleGuide(parse_argv=True) 

2656 options = style_guide.options 

2657 

2658 report = style_guide.check_files() 

2659 

2660 if options.statistics: 

2661 report.print_statistics() 

2662 

2663 if options.benchmark: 

2664 report.print_benchmark() 

2665 

2666 if report.total_errors: 

2667 if options.count: 

2668 sys.stderr.write(str(report.total_errors) + '\n') 

2669 sys.exit(1) 

2670 

2671 

2672if __name__ == '__main__': 

2673 _main()