"Fossies" - the Fresh Open Source Software Archive

Member "eric6-20.9/eric/eric6/Plugins/CheckerPlugins/CodeStyleChecker/pycodestyle.py" (4 Jul 2020, 105954 Bytes) of package /linux/misc/eric6-20.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "pycodestyle.py" see the Fossies "Dox" file reference documentation.

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