def _check_keyword_parentheses(self, tokens, start):
        """Check that there are not unnecessary parens after a keyword.

        Parens are unnecessary if there is exactly one balanced outer pair on a
        line, and it is followed by a colon, and contains no commas (i.e. is not a
        tuple).

        Args:
        tokens: list of Tokens; the entire list of Tokens.
        start: int; the position of the keyword in the token list.
        """
        # If the next token is not a paren, we're fine.
        if self._inside_brackets(":") and tokens[start][1] == "for":
            self._pop_token()
        if tokens[start + 1][1] != "(":
            return

        found_and_or = False
        depth = 0
        keyword_token = str(tokens[start][1])
        line_num = tokens[start][2][0]

        for i in range(start, len(tokens) - 1):
            token = tokens[i]

            # If we hit a newline, then assume any parens were for continuation.
            if token[0] == tokenize.NL:
                return

            if token[1] == "(":
                depth += 1
            elif token[1] == ")":
                depth -= 1
                if depth:
                    continue
                # ')' can't happen after if (foo), since it would be a syntax error.
                if tokens[i + 1][1] in (":", ")", "]", "}", "in") or tokens[i + 1][
                    0
                ] in (tokenize.NEWLINE, tokenize.ENDMARKER, tokenize.COMMENT):
                    # The empty tuple () is always accepted.
                    if i == start + 2:
                        return
                    if keyword_token == "not":
                        if not found_and_or:
                            self.add_message(
                                "superfluous-parens", line=line_num, args=keyword_token
                            )
                    elif keyword_token in ("return", "yield"):
                        self.add_message(
                            "superfluous-parens", line=line_num, args=keyword_token
                        )
                    elif keyword_token not in self._keywords_with_parens:
                        if not found_and_or:
                            self.add_message(
                                "superfluous-parens", line=line_num, args=keyword_token
                            )
                return
            elif depth == 1:
                # This is a tuple, which is always acceptable.
                if token[1] == ",":
                    return
                # 'and' and 'or' are the only boolean operators with lower precedence
                # than 'not', so parens are only required when they are found.
                if token[1] in ("and", "or"):
                    found_and_or = True
                # A yield inside an expression must always be in parentheses,
                # quit early without error.
                elif token[1] == "yield":
                    return
                # A generator expression always has a 'for' token in it, and
                # the 'for' token is only legal inside parens when it is in a
                # generator expression.  The parens are necessary here, so bail
                # without an error.
                elif token[1] == "for":
                    return

def _check_keyword_parentheses ( self , tokens , start ) : if self . _inside_brackets ( ":" ) and tokens [ start ] [ 1 ] == "for" : self . _pop_token ( ) if tokens [ start + 1 ] [ 1 ] != "(" : return found_and_or = False depth = 0 keyword_token = str ( tokens [ start ] [ 1 ] ) line_num = tokens [ start ] [ 2 ] [ 0 ] for i in range ( start , len ( tokens ) - 1 ) : token = tokens [ i ] if token [ 0 ] == tokenize . NL : return if token [ 1 ] == "(" : depth += 1 elif token [ 1 ] == ")" : depth -= 1 if depth : continue if tokens [ i + 1 ] [ 1 ] in ( ":" , ")" , "]" , "}" , "in" ) or tokens [ i + 1 ] [ 0 ] in ( tokenize . NEWLINE , tokenize . ENDMARKER , tokenize . COMMENT ) : if i == start + 2 : return if keyword_token == "not" : if not found_and_or : self . add_message ( "superfluous-parens" , line = line_num , args = keyword_token ) elif keyword_token in ( "return" , "yield" ) : self . add_message ( "superfluous-parens" , line = line_num , args = keyword_token ) elif keyword_token not in self . _keywords_with_parens : if not found_and_or : self . add_message ( "superfluous-parens" , line = line_num , args = keyword_token ) return elif depth == 1 : if token [ 1 ] == "," : return if token [ 1 ] in ( "and" , "or" ) : found_and_or = True elif token [ 1 ] == "yield" : return elif token [ 1 ] == "for" : return

Check that there are not unnecessary parens after a keyword .


def _has_valid_type_annotation(self, tokens, i):
        """Extended check of PEP-484 type hint presence"""
        if not self._inside_brackets("("):
            return False
        # token_info
        # type string start end line
        #  0      1     2    3    4
        bracket_level = 0
        for token in tokens[i - 1 :: -1]:
            if token[1] == ":":
                return True
            if token[1] == "(":
                return False
            if token[1] == "]":
                bracket_level += 1
            elif token[1] == "[":
                bracket_level -= 1
            elif token[1] == ",":
                if not bracket_level:
                    return False
            elif token[1] in (".", "..."):
                continue
            elif token[0] not in (tokenize.NAME, tokenize.STRING, tokenize.NL):
                return False
        return False

def _has_valid_type_annotation ( self , tokens , i ) : if not self . _inside_brackets ( "(" ) : return False bracket_level = 0 for token in tokens [ i - 1 : : - 1 ] : if token [ 1 ] == ":" : return True if token [ 1 ] == "(" : return False if token [ 1 ] == "]" : bracket_level += 1 elif token [ 1 ] == "[" : bracket_level -= 1 elif token [ 1 ] == "," : if not bracket_level : return False elif token [ 1 ] in ( "." , "..." ) : continue elif token [ 0 ] not in ( tokenize . NAME , tokenize . STRING , tokenize . NL ) : return False return False

Extended check of PEP - 484 type hint presence


def _check_equals_spacing(self, tokens, i):
        """Check the spacing of a single equals sign."""
        if self._has_valid_type_annotation(tokens, i):
            self._check_space(tokens, i, (_MUST, _MUST))
        elif self._inside_brackets("(") or self._inside_brackets("lambda"):
            self._check_space(tokens, i, (_MUST_NOT, _MUST_NOT))
        else:
            self._check_space(tokens, i, (_MUST, _MUST))

def _check_equals_spacing ( self , tokens , i ) : if self . _has_valid_type_annotation ( tokens , i ) : self . _check_space ( tokens , i , ( _MUST , _MUST ) ) elif self . _inside_brackets ( "(" ) or self . _inside_brackets ( "lambda" ) : self . _check_space ( tokens , i , ( _MUST_NOT , _MUST_NOT ) ) else : self . _check_space ( tokens , i , ( _MUST , _MUST ) )

Check the spacing of a single equals sign .


def _check_surrounded_by_space(self, tokens, i):
        """Check that a binary operator is surrounded by exactly one space."""
        self._check_space(tokens, i, (_MUST, _MUST))

def _check_surrounded_by_space ( self , tokens , i ) : self . _check_space ( tokens , i , ( _MUST , _MUST ) )

Check that a binary operator is surrounded by exactly one space .


def visit_default(self, node):
        """check the node line number and check it if not yet done"""
        if not node.is_statement:
            return
        if not node.root().pure_python:
            return  # XXX block visit of child nodes
        prev_sibl = node.previous_sibling()
        if prev_sibl is not None:
            prev_line = prev_sibl.fromlineno
        else:
            # The line on which a finally: occurs in a try/finally
            # is not directly represented in the AST. We infer it
            # by taking the last line of the body and adding 1, which
            # should be the line of finally:
            if (
                isinstance(node.parent, nodes.TryFinally)
                and node in node.parent.finalbody
            ):
                prev_line = node.parent.body[0].tolineno + 1
            else:
                prev_line = node.parent.statement().fromlineno
        line = node.fromlineno
        assert line, node
        if prev_line == line and self._visited_lines.get(line) != 2:
            self._check_multi_statement_line(node, line)
            return
        if line in self._visited_lines:
            return
        try:
            tolineno = node.blockstart_tolineno
        except AttributeError:
            tolineno = node.tolineno
        assert tolineno, node
        lines = []
        for line in range(line, tolineno + 1):
            self._visited_lines[line] = 1
            try:
                lines.append(self._lines[line].rstrip())
            except KeyError:
                lines.append("")

def visit_default ( self , node ) : if not node . is_statement : return if not node . root ( ) . pure_python : return prev_sibl = node . previous_sibling ( ) if prev_sibl is not None : prev_line = prev_sibl . fromlineno else : if ( isinstance ( node . parent , nodes . TryFinally ) and node in node . parent . finalbody ) : prev_line = node . parent . body [ 0 ] . tolineno + 1 else : prev_line = node . parent . statement ( ) . fromlineno line = node . fromlineno assert line , node if prev_line == line and self . _visited_lines . get ( line ) != 2 : self . _check_multi_statement_line ( node , line ) return if line in self . _visited_lines : return try : tolineno = node . blockstart_tolineno except AttributeError : tolineno = node . tolineno assert tolineno , node lines = [ ] for line in range ( line , tolineno + 1 ) : self . _visited_lines [ line ] = 1 try : lines . append ( self . _lines [ line ] . rstrip ( ) ) except KeyError : lines . append ( "" )


def _check_multi_statement_line(self, node, line):
        """Check for lines containing multiple statements."""
        # Do not warn about multiple nested context managers
        # in with statements.
        if isinstance(node, nodes.With):
            return
        # For try... except... finally..., the two nodes
        # appear to be on the same line due to how the AST is built.
        if isinstance(node, nodes.TryExcept) and isinstance(
            node.parent, nodes.TryFinally
        ):
            return
        if (
            isinstance(node.parent, nodes.If)
            and not node.parent.orelse
            and self.config.single_line_if_stmt
        ):
            return
        if (
            isinstance(node.parent, nodes.ClassDef)
            and len(node.parent.body) == 1
            and self.config.single_line_class_stmt
        ):
            return
        self.add_message("multiple-statements", node=node)
        self._visited_lines[line] = 2

def _check_multi_statement_line ( self , node , line ) : if isinstance ( node , nodes . With ) : return if isinstance ( node , nodes . TryExcept ) and isinstance ( node . parent , nodes . TryFinally ) : return if ( isinstance ( node . parent , nodes . If ) and not node . parent . orelse and self . config . single_line_if_stmt ) : return if ( isinstance ( node . parent , nodes . ClassDef ) and len ( node . parent . body ) == 1 and self . config . single_line_class_stmt ) : return self . add_message ( "multiple-statements" , node = node ) self . _visited_lines [ line ] = 2

Check for lines containing multiple statements .


def check_lines(self, lines, i):
        """check lines have less than a maximum number of characters
        """
        max_chars = self.config.max_line_length
        ignore_long_line = self.config.ignore_long_lines

        def check_line(line, i):
            if not line.endswith("\n"):
                self.add_message("missing-final-newline", line=i)
            else:
                # exclude \f (formfeed) from the rstrip
                stripped_line = line.rstrip("\t\n\r\v ")
                if not stripped_line and _EMPTY_LINE in self.config.no_space_check:
                    # allow empty lines
                    pass
                elif line[len(stripped_line) :] not in ("\n", "\r\n"):
                    self.add_message(
                        "trailing-whitespace", line=i, col_offset=len(stripped_line)
                    )
                # Don't count excess whitespace in the line length.
                line = stripped_line
            mobj = OPTION_RGX.search(line)
            if mobj and "=" in line:
                front_of_equal, _, back_of_equal = mobj.group(1).partition("=")
                if front_of_equal.strip() == "disable":
                    if "line-too-long" in {
                        _msg_id.strip() for _msg_id in back_of_equal.split(",")
                    }:
                        return None
                    line = line.rsplit("#", 1)[0].rstrip()

            if len(line) > max_chars and not ignore_long_line.search(line):
                self.add_message("line-too-long", line=i, args=(len(line), max_chars))
            return i + 1

        unsplit_ends = {
            "\v",
            "\x0b",
            "\f",
            "\x0c",
            "\x1c",
            "\x1d",
            "\x1e",
            "\x85",
            "\u2028",
            "\u2029",
        }
        unsplit = []
        for line in lines.splitlines(True):
            if line[-1] in unsplit_ends:
                unsplit.append(line)
                continue

            if unsplit:
                unsplit.append(line)
                line = "".join(unsplit)
                unsplit = []

            i = check_line(line, i)
            if i is None:
                break

        if unsplit:
            check_line("".join(unsplit), i)

def
check_lines
(
self
,
lines
,
i
)
:
max_chars
=
self
.
config
.
max_line_length
ignore_long_line
=
self
.
config
.
ignore_long_lines
def
check_line
(
line
,
i
)
:
if
not
line
.
endswith
(
"\n"
)
:
self
.
add_message
(
"missing-final-newline"
,
line
=
i
)
else
:
stripped_line
=
line
.
rstrip
(
"\t\n\r\v "
)
if
not
stripped_line
and
_EMPTY_LINE
in
self
.
config
.
no_space_check
:
pass
elif
line
[
len
(
stripped_line
)
:
]
not
in
(
"\n"
,
"\r\n"
)
:
self
.
add_message
(
"trailing-whitespace"
,
line
=
i
,
col_offset
=
len
(
stripped_line
)
)
line
=
stripped_line
mobj
=
OPTION_RGX
.
search
(
line
)
if
mobj
and
"="
in
line
:
front_of_equal
,
_
,
back_of_equal
=
mobj
.
group
(
1
)
.
partition
(
"="
)
if
front_of_equal
.
strip
(
)
==
"disable"
:
if
"line-too-long"
in
{
_msg_id
.
strip
(
)
for
_msg_id
in
back_of_equal
.
split
(
","
)
}
:
return
line
=
line
.
rsplit
(
"#"
,
1
)
[
0
]
.
rstrip
(
)
if
len
(
line
)
>
max_chars
and
not
ignore_long_line
.
search
(
line
)
:
self
.
add_message
(
"line-too-long"
,
line
=
i
,
args
=
(
len
(
line
)
,
max_chars
)
)
return
i
+
1
unsplit_ends
=
{
"\v"
,
"\x0b"
,
"\f"
,
"\x0c"
,
"\x1c"
,
"\x1d"
,
"\x1e"
,
"\x85"
,
"\u2028"
,
"\u2029"
,
}
unsplit
=
[
]
for
line
in
lines
.
splitlines
(
True
)
:
if
line
[
1
]
in
unsplit_ends
:
unsplit
.
append
(
line
)
continue
if
unsplit
:
unsplit
.
append
(
line
)
line
=
""
.
join
(
unsplit
)
unsplit
=
[
]
i
=
check_line
(
line
,
i
)
if
i
is
:
break
if
unsplit
:
check_line
(
""
.
join
(
unsplit
)
,
i
)


def check_indent_level(self, string, expected, line_num):
        """return the indent level of the string
        """
        indent = self.config.indent_string
        if indent == "\\t":  # \t is not interpreted in the configuration file
            indent = "\t"
        level = 0
        unit_size = len(indent)
        while string[:unit_size] == indent:
            string = string[unit_size:]
            level += 1
        suppl = ""
        while string and string[0] in " \t":
            if string[0] != indent[0]:
                if string[0] == "\t":
                    args = ("tab", "space")
                else:
                    args = ("space", "tab")
                self.add_message("mixed-indentation", args=args, line=line_num)
                return level
            suppl += string[0]
            string = string[1:]
        if level != expected or suppl:
            i_type = "spaces"
            if indent[0] == "\t":
                i_type = "tabs"
            self.add_message(
                "bad-indentation",
                line=line_num,
                args=(level * unit_size + len(suppl), i_type, expected * unit_size),
            )
        return None

def
check_indent_level
(
self
,
string
,
expected
,
line_num
)
:
indent
=
self
.
config
.
indent_string
if
indent
==
"\\t"
:
indent
=
"\t"
level
=
0
unit_size
=
len
(
indent
)
while
string
[
:
unit_size
]
==
indent
:
string
=
string
[
unit_size
:
]
level
+=
1
suppl
=
""
while
string
and
string
[
0
]
in
" \t"
:
if
string
[
0
]
!=
indent
[
0
]
:
if
string
[
0
]
==
"\t"
:
args
=
(
"tab"
,
"space"
)
else
:
args
=
(
"space"
,
"tab"
)
self
.
add_message
(
"mixed-indentation"
,
args
=
args
,
line
=
line_num
)
return
level
suppl
+=
string
[
0
]
string
=
string
[
1
:
]
if
level
!=
expected
or
suppl
:
i_type
=
"spaces"
if
indent
[
0
]
==
"\t"
:
i_type
=
"tabs"
self
.
add_message
(
"bad-indentation"
,
line
=
line_num
,
args
=
(
level
*
unit_size
+
len
(
suppl
)
,
i_type
,
expected
*
unit_size
)
,
)
return


def _in_iterating_context(node):
    """Check if the node is being used as an iterator.

    Definition is taken from lib2to3.fixer_util.in_special_context().
    """
    parent = node.parent
    # Since a call can't be the loop variant we only need to know if the node's
    # parent is a 'for' loop to know it's being used as the iterator for the
    # loop.
    if isinstance(parent, astroid.For):
        return True
    # Need to make sure the use of the node is in the iterator part of the
    # comprehension.
    if isinstance(parent, astroid.Comprehension):
        if parent.iter == node:
            return True
    # Various built-ins can take in an iterable or list and lead to the same
    # value.
    elif isinstance(parent, astroid.Call):
        if isinstance(parent.func, astroid.Name):
            parent_scope = parent.func.lookup(parent.func.name)[0]
            if _is_builtin(parent_scope) and parent.func.name in _ACCEPTS_ITERATOR:
                return True
        elif isinstance(parent.func, astroid.Attribute):
            if parent.func.attrname in ATTRIBUTES_ACCEPTS_ITERATOR:
                return True

        inferred = utils.safe_infer(parent.func)
        if inferred:
            if inferred.qname() in _BUILTIN_METHOD_ACCEPTS_ITERATOR:
                return True
            root = inferred.root()
            if root and root.name == "itertools":
                return True
    # If the call is in an unpacking, there's no need to warn,
    # since it can be considered iterating.
    elif isinstance(parent, astroid.Assign) and isinstance(
        parent.targets[0], (astroid.List, astroid.Tuple)
    ):
        if len(parent.targets[0].elts) > 1:
            return True
    # If the call is in a containment check, we consider that to
    # be an iterating context
    elif (
        isinstance(parent, astroid.Compare)
        and len(parent.ops) == 1
        and parent.ops[0][0] == "in"
    ):
        return True
    # Also if it's an `yield from`, that's fair
    elif isinstance(parent, astroid.YieldFrom):
        return True
    if isinstance(parent, astroid.Starred):
        return True
    return False

def _in_iterating_context ( node ) : parent = node . parent if isinstance ( parent , astroid . For ) : return True if isinstance ( parent , astroid . Comprehension ) : if parent . iter == node : return True elif isinstance ( parent , astroid . Call ) : if isinstance ( parent . func , astroid . Name ) : parent_scope = parent . func . lookup ( parent . func . name ) [ 0 ] if _is_builtin ( parent_scope ) and parent . func . name in _ACCEPTS_ITERATOR : return True elif isinstance ( parent . func , astroid . Attribute ) : if parent . func . attrname in ATTRIBUTES_ACCEPTS_ITERATOR : return True inferred = utils . safe_infer ( parent . func ) if inferred : if inferred . qname ( ) in _BUILTIN_METHOD_ACCEPTS_ITERATOR : return True root = inferred . root ( ) if root and root . name == "itertools" : return True elif isinstance ( parent , astroid . Assign ) and isinstance ( parent . targets [ 0 ] , ( astroid . List , astroid . Tuple ) ) : if len ( parent . targets [ 0 ] . elts ) > 1 : return True elif ( isinstance ( parent , astroid . Compare ) and len ( parent . ops ) == 1 and parent . ops [ 0 ] [ 0 ] == "in" ) : return True elif isinstance ( parent , astroid . YieldFrom ) : return True if isinstance ( parent , astroid . Starred ) : return True return False

Check if the node is being used as an iterator .


def _is_conditional_import(node):
    """Checks if an import node is in the context of a conditional.
    """
    parent = node.parent
    return isinstance(
        parent, (astroid.TryExcept, astroid.ExceptHandler, astroid.If, astroid.IfExp)
    )

def _is_conditional_import ( node ) : parent = node . parent return isinstance ( parent , ( astroid . TryExcept , astroid . ExceptHandler , astroid . If , astroid . IfExp ) )

Checks if an import node is in the context of a conditional .


def visit_name(self, node):
        """Detect when a "bad" built-in is referenced."""
        found_node, _ = node.lookup(node.name)
        if not _is_builtin(found_node):
            return
        if node.name not in self._bad_builtins:
            return
        if node_ignores_exception(node) or isinstance(
            find_try_except_wrapper_node(node), astroid.ExceptHandler
        ):
            return

        message = node.name.lower() + "-builtin"
        self.add_message(message, node=node)

def visit_name ( self , node ) : found_node , _ = node . lookup ( node . name ) if not _is_builtin ( found_node ) : return if node . name not in self . _bad_builtins : return if node_ignores_exception ( node ) or isinstance ( find_try_except_wrapper_node ( node ) , astroid . ExceptHandler ) : return message = node . name . lower ( ) + "-builtin" self . add_message ( message , node = node )

Detect when a bad built - in is referenced .


def visit_subscript(self, node):
        """ Look for indexing exceptions. """
        try:
            for inferred in node.value.infer():
                if not isinstance(inferred, astroid.Instance):
                    continue
                if utils.inherit_from_std_ex(inferred):
                    self.add_message("indexing-exception", node=node)
        except astroid.InferenceError:
            return

def visit_subscript ( self , node ) : try : for inferred in node . value . infer ( ) : if not isinstance ( inferred , astroid . Instance ) : continue if utils . inherit_from_std_ex ( inferred ) : self . add_message ( "indexing-exception" , node = node ) except astroid . InferenceError : return


def visit_attribute(self, node):
        """Look for removed attributes"""
        if node.attrname == "xreadlines":
            self.add_message("xreadlines-attribute", node=node)
            return

        exception_message = "message"
        try:
            for inferred in node.expr.infer():
                if isinstance(inferred, astroid.Instance) and utils.inherit_from_std_ex(
                    inferred
                ):
                    if node.attrname == exception_message:

                        # Exceptions with .message clearly defined are an exception
                        if exception_message in inferred.instance_attrs:
                            continue
                        self.add_message("exception-message-attribute", node=node)
                if isinstance(inferred, astroid.Module):
                    self._warn_if_deprecated(
                        node, inferred.name, {node.attrname}, report_on_modules=False
                    )
        except astroid.InferenceError:
            return

def visit_attribute ( self , node ) : if node . attrname == "xreadlines" : self . add_message ( "xreadlines-attribute" , node = node ) return exception_message = "message" try : for inferred in node . expr . infer ( ) : if isinstance ( inferred , astroid . Instance ) and utils . inherit_from_std_ex ( inferred ) : if node . attrname == exception_message : if exception_message in inferred . instance_attrs : continue self . add_message ( "exception-message-attribute" , node = node ) if isinstance ( inferred , astroid . Module ) : self . _warn_if_deprecated ( node , inferred . name , { node . attrname } , report_on_modules = False ) except astroid . InferenceError : return


def visit_excepthandler(self, node):
        """Visit an except handler block and check for exception unpacking."""

        def _is_used_in_except_block(node):
            scope = node.scope()
            current = node
            while (
                current
                and current != scope
                and not isinstance(current, astroid.ExceptHandler)
            ):
                current = current.parent
            return isinstance(current, astroid.ExceptHandler) and current.type != node

        if isinstance(node.name, (astroid.Tuple, astroid.List)):
            self.add_message("unpacking-in-except", node=node)
            return

        if not node.name:
            return

        # Find any names
        scope = node.parent.scope()
        scope_names = scope.nodes_of_class(astroid.Name, skip_klass=astroid.FunctionDef)
        scope_names = list(scope_names)
        potential_leaked_names = [
            scope_name
            for scope_name in scope_names
            if scope_name.name == node.name.name
            and scope_name.lineno > node.lineno
            and not _is_used_in_except_block(scope_name)
        ]
        reassignments_for_same_name = {
            assign_name.lineno
            for assign_name in scope.nodes_of_class(
                astroid.AssignName, skip_klass=astroid.FunctionDef
            )
            if assign_name.name == node.name.name
        }
        for leaked_name in potential_leaked_names:
            if any(
                node.lineno < elem < leaked_name.lineno
                for elem in reassignments_for_same_name
            ):
                continue
            self.add_message("exception-escape", node=leaked_name)

def visit_excepthandler ( self , node ) : def _is_used_in_except_block ( node ) : scope = node . scope ( ) current = node while ( current and current != scope and not isinstance ( current , astroid . ExceptHandler ) ) : current = current . parent return isinstance ( current , astroid . ExceptHandler ) and current . type != node if isinstance ( node . name , ( astroid . Tuple , astroid . List ) ) : self . add_message ( "unpacking-in-except" , node = node ) return if not node . name : return scope = node . parent . scope ( ) scope_names = scope . nodes_of_class ( astroid . Name , skip_klass = astroid . FunctionDef ) scope_names = list ( scope_names ) potential_leaked_names = [ scope_name for scope_name in scope_names if scope_name . name == node . name . name and scope_name . lineno > node . lineno and not _is_used_in_except_block ( scope_name ) ] reassignments_for_same_name = { assign_name . lineno for assign_name in scope . nodes_of_class ( astroid . AssignName , skip_klass = astroid . FunctionDef ) if assign_name . name == node . name . name } for leaked_name in potential_leaked_names : if any ( node . lineno < elem < leaked_name . lineno for elem in reassignments_for_same_name ) : continue self . add_message ( "exception-escape" , node = leaked_name )

Visit an except handler block and check for exception unpacking .


def visit_raise(self, node):
        """Visit a raise statement and check for raising
        strings or old-raise-syntax.
        """

        # Ignore empty raise.
        if node.exc is None:
            return
        expr = node.exc
        if self._check_raise_value(node, expr):
            return
        try:
            value = next(astroid.unpack_infer(expr))
        except astroid.InferenceError:
            return
        self._check_raise_value(node, value)

def visit_raise ( self , node ) : if node . exc is None : return expr = node . exc if self . _check_raise_value ( node , expr ) : return try : value = next ( astroid . unpack_infer ( expr ) ) except astroid . InferenceError : return self . _check_raise_value ( node , value )

Visit a raise statement and check for raising strings or old - raise - syntax .


def find_pylintrc():
    """search the pylint rc file and return its path if it find it, else None
    """
    # is there a pylint rc file in the current directory ?
    if os.path.exists("pylintrc"):
        return os.path.abspath("pylintrc")
    if os.path.exists(".pylintrc"):
        return os.path.abspath(".pylintrc")
    if os.path.isfile("__init__.py"):
        curdir = os.path.abspath(os.getcwd())
        while os.path.isfile(os.path.join(curdir, "__init__.py")):
            curdir = os.path.abspath(os.path.join(curdir, ".."))
            if os.path.isfile(os.path.join(curdir, "pylintrc")):
                return os.path.join(curdir, "pylintrc")
            if os.path.isfile(os.path.join(curdir, ".pylintrc")):
                return os.path.join(curdir, ".pylintrc")
    if "PYLINTRC" in os.environ and os.path.exists(os.environ["PYLINTRC"]):
        pylintrc = os.environ["PYLINTRC"]
    else:
        user_home = os.path.expanduser("~")
        if user_home in ("~", "/root"):
            pylintrc = ".pylintrc"
        else:
            pylintrc = os.path.join(user_home, ".pylintrc")
            if not os.path.isfile(pylintrc):
                pylintrc = os.path.join(user_home, ".config", "pylintrc")
    if not os.path.isfile(pylintrc):
        if os.path.isfile("/etc/pylintrc"):
            pylintrc = "/etc/pylintrc"
        else:
            pylintrc = None
    return pylintrc

def find_pylintrc ( ) : if os . path . exists ( "pylintrc" ) : return os . path . abspath ( "pylintrc" ) if os . path . exists ( ".pylintrc" ) : return os . path . abspath ( ".pylintrc" ) if os . path . isfile ( "__init__.py" ) : curdir = os . path . abspath ( os . getcwd ( ) ) while os . path . isfile ( os . path . join ( curdir , "__init__.py" ) ) : curdir = os . path . abspath ( os . path . join ( curdir , ".." ) ) if os . path . isfile ( os . path . join ( curdir , "pylintrc" ) ) : return os . path . join ( curdir , "pylintrc" ) if os . path . isfile ( os . path . join ( curdir , ".pylintrc" ) ) : return os . path . join ( curdir , ".pylintrc" ) if "PYLINTRC" in os . environ and os . path . exists ( os . environ [ "PYLINTRC" ] ) : pylintrc = os . environ [ "PYLINTRC" ] else : user_home = os . path . expanduser ( "~" ) if user_home in ( "~" , "/root" ) : pylintrc = ".pylintrc" else : pylintrc = os . path . join ( user_home , ".pylintrc" ) if not os . path . isfile ( pylintrc ) : pylintrc = os . path . join ( user_home , ".config" , "pylintrc" ) if not os . path . isfile ( pylintrc ) : if os . path . isfile ( "/etc/pylintrc" ) : pylintrc = "/etc/pylintrc" else : pylintrc = None return pylintrc

search the pylint rc file and return its path if it find it else None


def _validate(value, optdict, name=""):
    """return a validated value for an option according to its type

    optional argument name is only used for error message formatting
    """
    try:
        _type = optdict["type"]
    except KeyError:
        # FIXME
        return value
    return _call_validator(_type, optdict, name, value)

def _validate ( value , optdict , name = "" ) : try : _type = optdict [ "type" ] except KeyError : return value return _call_validator ( _type , optdict , name , value )


def _expand_default(self, option):
    """Patch OptionParser.expand_default with custom behaviour

    This will handle defaults to avoid overriding values in the
    configuration file.
    """
    if self.parser is None or not self.default_tag:
        return option.help
    optname = option._long_opts[0][2:]
    try:
        provider = self.parser.options_manager._all_options[optname]
    except KeyError:
        value = None
    else:
        optdict = provider.get_option_def(optname)
        optname = provider.option_attrname(optname, optdict)
        value = getattr(provider.config, optname, optdict)
        value = utils._format_option_value(optdict, value)
    if value is optparse.NO_DEFAULT or not value:
        value = self.NO_DEFAULT_VALUE
    return option.help.replace(self.default_tag, str(value))

def _expand_default ( self , option ) : if self . parser is None or not self . default_tag : return option . help optname = option . _long_opts [ 0 ] [ 2 : ] try : provider = self . parser . options_manager . _all_options [ optname ] except KeyError : value = None else : optdict = provider . get_option_def ( optname ) optname = provider . option_attrname ( optname , optdict ) value = getattr ( provider . config , optname , optdict ) value = utils . _format_option_value ( optdict , value ) if value is optparse . NO_DEFAULT or not value : value = self . NO_DEFAULT_VALUE return option . help . replace ( self . default_tag , str ( value ) )

Patch OptionParser . expand_default with custom behaviour


def _match_long_opt(self, opt):
        """Disable abbreviations."""
        if opt not in self._long_opt:
            raise optparse.BadOptionError(opt)
        return opt

def _match_long_opt ( self , opt ) : if opt not in self . _long_opt : raise optparse . BadOptionError ( opt ) return opt


def register_options_provider(self, provider, own_group=True):
        """register an options provider"""
        assert provider.priority <= 0, "provider's priority can't be >= 0"
        for i in range(len(self.options_providers)):
            if provider.priority > self.options_providers[i].priority:
                self.options_providers.insert(i, provider)
                break
        else:
            self.options_providers.append(provider)
        non_group_spec_options = [
            option for option in provider.options if "group" not in option[1]
        ]
        groups = getattr(provider, "option_groups", ())
        if own_group and non_group_spec_options:
            self.add_option_group(
                provider.name.upper(),
                provider.__doc__,
                non_group_spec_options,
                provider,
            )
        else:
            for opt, optdict in non_group_spec_options:
                self.add_optik_option(provider, self.cmdline_parser, opt, optdict)
        for gname, gdoc in groups:
            gname = gname.upper()
            goptions = [
                option
                for option in provider.options
                if option[1].get("group", "").upper() == gname
            ]
            self.add_option_group(gname, gdoc, goptions, provider)

def
register_options_provider
(
self
,
provider
,
own_group
=
True
)
:
assert
provider
.
priority
<=
0
,
"provider's priority can't be >= 0"
for
i
in
range
(
len
(
self
.
options_providers
)
)
:
if
provider
.
priority
>
self
.
options_providers
[
i
]
.
priority
:
self
.
options_providers
.
insert
(
i
,
provider
)
break
else
:
self
.
options_providers
.
append
(
provider
)
non_group_spec_options
=
[
option
for
option
in
provider
.
options
if
"group"
not
in
option
[
1
]
]
groups
=
getattr
(
provider
,
"option_groups"
,
(
)
)
if
own_group
and
non_group_spec_options
:
self
.
add_option_group
(
provider
.
name
.
upper
(
)
,
provider
.
__doc__
,
non_group_spec_options
,
provider
,
)
else
:
for
opt
,
optdict
in
non_group_spec_options
:
self
.
add_optik_option
(
provider
,
self
.
cmdline_parser
,
opt
,
optdict
)
for
gname
,
gdoc
in
groups
:
gname
=
gname
.
upper
(
)
goptions
=
[
option
for
option
in
provider
.
options
if
option
[
1
]
.
get
(
"group"
,
""
)
.
upper
(
)
==
gname
]
self
.
add_option_group
(
gname
,
gdoc
,
goptions
,
provider
)


def cb_set_provider_option(self, option, opt, value, parser):
        """optik callback for option setting"""
        if opt.startswith("--"):
            # remove -- on long option
            opt = opt[2:]
        else:
            # short option, get its long equivalent
            opt = self._short_options[opt[1:]]
        # trick since we can't set action='store_true' on options
        if value is None:
            value = 1
        self.global_set_option(opt, value)

def cb_set_provider_option ( self , option , opt , value , parser ) : if opt . startswith ( "--" ) : opt = opt [ 2 : ] else : opt = self . _short_options [ opt [ 1 : ] ] if value is None : value = 1 self . global_set_option ( opt , value )


def global_set_option(self, opt, value):
        """set option on the correct option provider"""
        self._all_options[opt].set_option(opt, value)

def global_set_option ( self , opt , value ) : self . _all_options [ opt ] . set_option ( opt , value )


def generate_config(self, stream=None, skipsections=(), encoding=None):
        """write a configuration file according to the current configuration
        into the given stream or stdout
        """
        options_by_section = {}
        sections = []
        for provider in self.options_providers:
            for section, options in provider.options_by_section():
                if section is None:
                    section = provider.name
                if section in skipsections:
                    continue
                options = [
                    (n, d, v)
                    for (n, d, v) in options
                    if d.get("type") is not None and not d.get("deprecated")
                ]
                if not options:
                    continue
                if section not in sections:
                    sections.append(section)
                alloptions = options_by_section.setdefault(section, [])
                alloptions += options
        stream = stream or sys.stdout
        printed = False
        for section in sections:
            if printed:
                print("\n", file=stream)
            utils.format_section(
                stream, section.upper(), sorted(options_by_section[section])
            )
            printed = True

def generate_config ( self , stream = None , skipsections = ( ) , encoding = None ) : options_by_section = { } sections = [ ] for provider in self . options_providers : for section , options in provider . options_by_section ( ) : if section is None : section = provider . name if section in skipsections : continue options = [ ( n , d , v ) for ( n , d , v ) in options if d . get ( "type" ) is not None and not d . get ( "deprecated" ) ] if not options : continue if section not in sections : sections . append ( section ) alloptions = options_by_section . setdefault ( section , [ ] ) alloptions += options stream = stream or sys . stdout printed = False for section in sections : if printed : print ( "\n" , file = stream ) utils . format_section ( stream , section . upper ( ) , sorted ( options_by_section [ section ] ) ) printed = True


def load_config_file(self):
        """dispatch values previously read from a configuration file to each
        options provider)
        """
        parser = self.cfgfile_parser
        for section in parser.sections():
            for option, value in parser.items(section):
                try:
                    self.global_set_option(option, value)
                except (KeyError, optparse.OptionError):
                    # TODO handle here undeclared options appearing in the config file
                    continue

def load_config_file ( self ) : parser = self . cfgfile_parser for section in parser . sections ( ) : for option , value in parser . items ( section ) : try : self . global_set_option ( option , value ) except ( KeyError , optparse . OptionError ) : continue

dispatch values previously read from a configuration file to each options provider )


def load_command_line_configuration(self, args=None):
        """Override configuration according to command line parameters

        return additional arguments
        """
        with _patch_optparse():
            if args is None:
                args = sys.argv[1:]
            else:
                args = list(args)
            (options, args) = self.cmdline_parser.parse_args(args=args)
            for provider in self._nocallback_options:
                config = provider.config
                for attr in config.__dict__.keys():
                    value = getattr(options, attr, None)
                    if value is None:
                        continue
                    setattr(config, attr, value)
            return args

def load_command_line_configuration ( self , args = None ) : with _patch_optparse ( ) : if args is None : args = sys . argv [ 1 : ] else : args = list ( args ) ( options , args ) = self . cmdline_parser . parse_args ( args = args ) for provider in self . _nocallback_options : config = provider . config for attr in config . __dict__ . keys ( ) : value = getattr ( options , attr , None ) if value is None : continue setattr ( config , attr , value ) return args


def add_help_section(self, title, description, level=0):
        """add a dummy option section for help purpose """
        group = optparse.OptionGroup(
            self.cmdline_parser, title=title.capitalize(), description=description
        )
        group.level = level
        self._maxlevel = max(self._maxlevel, level)
        self.cmdline_parser.add_option_group(group)

def add_help_section ( self , title , description , level = 0 ) : group = optparse . OptionGroup ( self . cmdline_parser , title = title . capitalize ( ) , description = description ) group . level = level self . _maxlevel = max ( self . _maxlevel , level ) self . cmdline_parser . add_option_group ( group )


def help(self, level=0):
        """return the usage string for available options """
        self.cmdline_parser.formatter.output_level = level
        with _patch_optparse():
            return self.cmdline_parser.format_help()

def help ( self , level = 0 ) : self . cmdline_parser . formatter . output_level = level with _patch_optparse ( ) : return self . cmdline_parser . format_help ( )


def load_defaults(self):
        """initialize the provider using default values"""
        for opt, optdict in self.options:
            action = optdict.get("action")
            if action != "callback":
                # callback action have no default
                if optdict is None:
                    optdict = self.get_option_def(opt)
                default = optdict.get("default")
                self.set_option(opt, default, action, optdict)

def load_defaults ( self ) : for opt , optdict in self . options : action = optdict . get ( "action" ) if action != "callback" : if optdict is None : optdict = self . get_option_def ( opt ) default = optdict . get ( "default" ) self . set_option ( opt , default , action , optdict )


def option_attrname(self, opt, optdict=None):
        """get the config attribute corresponding to opt"""
        if optdict is None:
            optdict = self.get_option_def(opt)
        return optdict.get("dest", opt.replace("-", "_"))

def option_attrname ( self , opt , optdict = None ) : if optdict is None : optdict = self . get_option_def ( opt ) return optdict . get ( "dest" , opt . replace ( "-" , "_" ) )


def get_option_def(self, opt):
        """return the dictionary defining an option given its name"""
        assert self.options
        for option in self.options:
            if option[0] == opt:
                return option[1]
        raise optparse.OptionError(
            "no such option %s in section %r" % (opt, self.name), opt
        )

def
get_option_def
(
self
,
opt
)
:
assert
self
.
options
for
option
in
self
.
options
:
if
option
[
0
]
==
opt
:
return
option
[
1
]
raise
optparse
.
OptionError
(
"no such option %s in section %r"
%
(
opt
,
self
.
name
)
,
opt
)


def options_by_section(self):
        """return an iterator on options grouped by section

        (section, [list of (optname, optdict, optvalue)])
        """
        sections = {}
        for optname, optdict in self.options:
            sections.setdefault(optdict.get("group"), []).append(
                (optname, optdict, self.option_value(optname))
            )
        if None in sections:
            yield None, sections.pop(None)
        for section, options in sorted(sections.items()):
            yield section.upper(), options

def options_by_section ( self ) : sections = { } for optname , optdict in self . options : sections . setdefault ( optdict . get ( "group" ) , [ ] ) . append ( ( optname , optdict , self . option_value ( optname ) ) ) if None in sections : yield None , sections . pop ( None ) for section , options in sorted ( sections . items ( ) ) : yield section . upper ( ) , options


def is_method_call(func, types=(), methods=()):
    """Determines if a BoundMethod node represents a method call.

    Args:
      func (astroid.BoundMethod): The BoundMethod AST node to check.
      types (Optional[String]): Optional sequence of caller type names to restrict check.
      methods (Optional[String]): Optional sequence of method names to restrict check.

    Returns:
      bool: true if the node represents a method call for the given type and
      method names, False otherwise.
    """
    return (
        isinstance(func, astroid.BoundMethod)
        and isinstance(func.bound, astroid.Instance)
        and (func.bound.name in types if types else True)
        and (func.name in methods if methods else True)
    )

def is_method_call ( func , types = ( ) , methods = ( ) ) : return ( isinstance ( func , astroid . BoundMethod ) and isinstance ( func . bound , astroid . Instance ) and ( func . bound . name in types if types else True ) and ( func . name in methods if methods else True ) )

Determines if a BoundMethod node represents a method call .


def is_complex_format_str(node):
    """Checks if node represents a string with complex formatting specs.

    Args:
        node (astroid.node_classes.NodeNG): AST node to check
    Returns:
        bool: True if inferred string uses complex formatting, False otherwise
    """
    inferred = utils.safe_infer(node)
    if inferred is None or not isinstance(inferred.value, str):
        return True
    try:
        parsed = list(string.Formatter().parse(inferred.value))
    except ValueError:
        # This format string is invalid
        return False
    for _, _, format_spec, _ in parsed:
        if format_spec:
            return True
    return False

def is_complex_format_str ( node ) : inferred = utils . safe_infer ( node ) if inferred is None or not isinstance ( inferred . value , str ) : return True try : parsed = list ( string . Formatter ( ) . parse ( inferred . value ) ) except ValueError : return False for _ , _ , format_spec , _ in parsed : if format_spec : return True return False

Checks if node represents a string with complex formatting specs .


def visit_module(self, node):  # pylint: disable=unused-argument
        """Clears any state left in this checker from last module checked."""
        # The code being checked can just as easily "import logging as foo",
        # so it is necessary to process the imports and store in this field
        # what name the logging module is actually given.
        self._logging_names = set()
        logging_mods = self.config.logging_modules

        self._format_style = self.config.logging_format_style
        self._logging_modules = set(logging_mods)
        self._from_imports = {}
        for logging_mod in logging_mods:
            parts = logging_mod.rsplit(".", 1)
            if len(parts) > 1:
                self._from_imports[parts[0]] = parts[1]

def visit_module ( self , node ) : self . _logging_names = set ( ) logging_mods = self . config . logging_modules self . _format_style = self . config . logging_format_style self . _logging_modules = set ( logging_mods ) self . _from_imports = { } for logging_mod in logging_mods : parts = logging_mod . rsplit ( "." , 1 ) if len ( parts ) > 1 : self . _from_imports [ parts [ 0 ] ] = parts [ 1 ]

Clears any state left in this checker from last module checked .


def visit_importfrom(self, node):
        """Checks to see if a module uses a non-Python logging module."""
        try:
            logging_name = self._from_imports[node.modname]
            for module, as_name in node.names:
                if module == logging_name:
                    self._logging_names.add(as_name or module)
        except KeyError:
            pass

def visit_importfrom ( self , node ) : try : logging_name = self . _from_imports [ node . modname ] for module , as_name in node . names : if module == logging_name : self . _logging_names . add ( as_name or module ) except KeyError : pass

Checks to see if a module uses a non - Python logging module .


def visit_import(self, node):
        """Checks to see if this module uses Python's built-in logging."""
        for module, as_name in node.names:
            if module in self._logging_modules:
                self._logging_names.add(as_name or module)

def visit_import ( self , node ) : for module , as_name in node . names : if module in self . _logging_modules : self . _logging_names . add ( as_name or module )

Checks to see if this module uses Python s built - in logging .


def visit_call(self, node):
        """Checks calls to logging methods."""

        def is_logging_name():
            return (
                isinstance(node.func, astroid.Attribute)
                and isinstance(node.func.expr, astroid.Name)
                and node.func.expr.name in self._logging_names
            )

        def is_logger_class():
            try:
                for inferred in node.func.infer():
                    if isinstance(inferred, astroid.BoundMethod):
                        parent = inferred._proxied.parent
                        if isinstance(parent, astroid.ClassDef) and (
                            parent.qname() == "logging.Logger"
                            or any(
                                ancestor.qname() == "logging.Logger"
                                for ancestor in parent.ancestors()
                            )
                        ):
                            return True, inferred._proxied.name
            except astroid.exceptions.InferenceError:
                pass
            return False, None

        if is_logging_name():
            name = node.func.attrname
        else:
            result, name = is_logger_class()
            if not result:
                return
        self._check_log_method(node, name)

def visit_call ( self , node ) : def is_logging_name ( ) : return ( isinstance ( node . func , astroid . Attribute ) and isinstance ( node . func . expr , astroid . Name ) and node . func . expr . name in self . _logging_names ) def is_logger_class ( ) : try : for inferred in node . func . infer ( ) : if isinstance ( inferred , astroid . BoundMethod ) : parent = inferred . _proxied . parent if isinstance ( parent , astroid . ClassDef ) and ( parent . qname ( ) == "logging.Logger" or any ( ancestor . qname ( ) == "logging.Logger" for ancestor in parent . ancestors ( ) ) ) : return True , inferred . _proxied . name except astroid . exceptions . InferenceError : pass return False , None if is_logging_name ( ) : name = node . func . attrname else : result , name = is_logger_class ( ) if not result : return self . _check_log_method ( node , name )


def _check_format_string(self, node, format_arg):
        """Checks that format string tokens match the supplied arguments.

        Args:
          node (astroid.node_classes.NodeNG): AST node to be checked.
          format_arg (int): Index of the format string in the node arguments.
        """
        num_args = _count_supplied_tokens(node.args[format_arg + 1 :])
        if not num_args:
            # If no args were supplied the string is not interpolated and can contain
            # formatting characters - it's used verbatim. Don't check any further.
            return
        format_string = node.args[format_arg].value
        if not isinstance(format_string, str):
            # If the log format is constant non-string (e.g. logging.debug(5)),
            # ensure there are no arguments.
            required_num_args = 0
        else:
            try:
                if self._format_style == "old":
                    keyword_args, required_num_args, _, _ = utils.parse_format_string(
                        format_string
                    )
                    if keyword_args:
                        # Keyword checking on logging strings is complicated by
                        # special keywords - out of scope.
                        return
                elif self._format_style == "new":
                    keyword_arguments, implicit_pos_args, explicit_pos_args = utils.parse_format_method_string(
                        format_string
                    )

                    keyword_args_cnt = len(
                        set(k for k, l in keyword_arguments if not isinstance(k, int))
                    )
                    required_num_args = (
                        keyword_args_cnt + implicit_pos_args + explicit_pos_args
                    )
            except utils.UnsupportedFormatCharacter as ex:
                char = format_string[ex.index]
                self.add_message(
                    "logging-unsupported-format",
                    node=node,
                    args=(char, ord(char), ex.index),
                )
                return
            except utils.IncompleteFormatString:
                self.add_message("logging-format-truncated", node=node)
                return
        if num_args > required_num_args:
            self.add_message("logging-too-many-args", node=node)
        elif num_args < required_num_args:
            self.add_message("logging-too-few-args", node=node)

def _check_format_string ( self , node , format_arg ) : num_args = _count_supplied_tokens ( node . args [ format_arg + 1 : ] ) if not num_args : return format_string = node . args [ format_arg ] . value if not isinstance ( format_string , str ) : required_num_args = 0 else : try : if self . _format_style == "old" : keyword_args , required_num_args , _ , _ = utils . parse_format_string ( format_string ) if keyword_args : return elif self . _format_style == "new" : keyword_arguments , implicit_pos_args , explicit_pos_args = utils . parse_format_method_string ( format_string ) keyword_args_cnt = len ( set ( k for k , l in keyword_arguments if not isinstance ( k , int ) ) ) required_num_args = ( keyword_args_cnt + implicit_pos_args + explicit_pos_args ) except utils . UnsupportedFormatCharacter as ex : char = format_string [ ex . index ] self . add_message ( "logging-unsupported-format" , node = node , args = ( char , ord ( char ) , ex . index ) , ) return except utils . IncompleteFormatString : self . add_message ( "logging-format-truncated" , node = node ) return if num_args > required_num_args : self . add_message ( "logging-too-many-args" , node = node ) elif num_args < required_num_args : self . add_message ( "logging-too-few-args" , node = node )

Checks that format string tokens match the supplied arguments .


def in_loop(node):
    """return True if the node is inside a kind of for loop"""
    parent = node.parent
    while parent is not None:
        if isinstance(
            parent,
            (
                astroid.For,
                astroid.ListComp,
                astroid.SetComp,
                astroid.DictComp,
                astroid.GeneratorExp,
            ),
        ):
            return True
        parent = parent.parent
    return False

def in_loop ( node ) : parent = node . parent while parent is not None : if isinstance ( parent , ( astroid . For , astroid . ListComp , astroid . SetComp , astroid . DictComp , astroid . GeneratorExp , ) , ) : return True parent = parent . parent return False


def _get_break_loop_node(break_node):
    """
    Returns the loop node that holds the break node in arguments.

    Args:
        break_node (astroid.Break): the break node of interest.

    Returns:
        astroid.For or astroid.While: the loop node holding the break node.
    """
    loop_nodes = (astroid.For, astroid.While)
    parent = break_node.parent
    while not isinstance(parent, loop_nodes) or break_node in getattr(
        parent, "orelse", []
    ):
        break_node = parent
        parent = parent.parent
        if parent is None:
            break
    return parent

def _get_break_loop_node ( break_node ) : loop_nodes = ( astroid . For , astroid . While ) parent = break_node . parent while not isinstance ( parent , loop_nodes ) or break_node in getattr ( parent , "orelse" , [ ] ) : break_node = parent parent = parent . parent if parent is None : break return parent

Returns the loop node that holds the break node in arguments .


def _loop_exits_early(loop):
    """
    Returns true if a loop may ends up in a break statement.

    Args:
        loop (astroid.For, astroid.While): the loop node inspected.

    Returns:
        bool: True if the loop may ends up in a break statement, False otherwise.
    """
    loop_nodes = (astroid.For, astroid.While)
    definition_nodes = (astroid.FunctionDef, astroid.ClassDef)
    inner_loop_nodes = [
        _node
        for _node in loop.nodes_of_class(loop_nodes, skip_klass=definition_nodes)
        if _node != loop
    ]
    return any(
        _node
        for _node in loop.nodes_of_class(astroid.Break, skip_klass=definition_nodes)
        if _get_break_loop_node(_node) not in inner_loop_nodes
    )

def _loop_exits_early ( loop ) : loop_nodes = ( astroid . For , astroid . While ) definition_nodes = ( astroid . FunctionDef , astroid . ClassDef ) inner_loop_nodes = [ _node for _node in loop . nodes_of_class ( loop_nodes , skip_klass = definition_nodes ) if _node != loop ] return any ( _node for _node in loop . nodes_of_class ( astroid . Break , skip_klass = definition_nodes ) if _get_break_loop_node ( _node ) not in inner_loop_nodes )

Returns true if a loop may ends up in a break statement .


def _get_properties(config):
    """Returns a tuple of property classes and names.

    Property classes are fully qualified, such as 'abc.abstractproperty' and
    property names are the actual names, such as 'abstract_property'.
    """
    property_classes = {BUILTIN_PROPERTY}
    property_names = set()  # Not returning 'property', it has its own check.
    if config is not None:
        property_classes.update(config.property_classes)
        property_names.update(
            (prop.rsplit(".", 1)[-1] for prop in config.property_classes)
        )
    return property_classes, property_names

def _get_properties ( config ) : property_classes = { BUILTIN_PROPERTY } property_names = set ( ) if config is not None : property_classes . update ( config . property_classes ) property_names . update ( ( prop . rsplit ( "." , 1 ) [ - 1 ] for prop in config . property_classes ) ) return property_classes , property_names

Returns a tuple of property classes and names .


def _determine_function_name_type(node, config=None):
    """Determine the name type whose regex the a function's name should match.

    :param node: A function node.
    :type node: astroid.node_classes.NodeNG
    :param config: Configuration from which to pull additional property classes.
    :type config: :class:`optparse.Values`

    :returns: One of ('function', 'method', 'attr')
    :rtype: str
    """
    property_classes, property_names = _get_properties(config)
    if not node.is_method():
        return "function"
    if node.decorators:
        decorators = node.decorators.nodes
    else:
        decorators = []
    for decorator in decorators:
        # If the function is a property (decorated with @property
        # or @abc.abstractproperty), the name type is 'attr'.
        if isinstance(decorator, astroid.Name) or (
            isinstance(decorator, astroid.Attribute)
            and decorator.attrname in property_names
        ):
            infered = utils.safe_infer(decorator)
            if infered and infered.qname() in property_classes:
                return "attr"
        # If the function is decorated using the prop_method.{setter,getter}
        # form, treat it like an attribute as well.
        elif isinstance(decorator, astroid.Attribute) and decorator.attrname in (
            "setter",
            "deleter",
        ):
            return "attr"
    return "method"

def _determine_function_name_type ( node , config = None ) : property_classes , property_names = _get_properties ( config ) if not node . is_method ( ) : return "function" if node . decorators : decorators = node . decorators . nodes else : decorators = [ ] for decorator in decorators : if isinstance ( decorator , astroid . Name ) or ( isinstance ( decorator , astroid . Attribute ) and decorator . attrname in property_names ) : infered = utils . safe_infer ( decorator ) if infered and infered . qname ( ) in property_classes : return "attr" elif isinstance ( decorator , astroid . Attribute ) and decorator . attrname in ( "setter" , "deleter" , ) : return "attr" return "method"

Determine the name type whose regex the a function s name should match .


def report_by_type_stats(sect, stats, _):
    """make a report of

    * percentage of different types documented
    * percentage of different types with a bad name
    """
    # percentage of different types documented and/or with a bad name
    nice_stats = {}
    for node_type in ("module", "class", "method", "function"):
        try:
            total = stats[node_type]
        except KeyError:
            raise exceptions.EmptyReportError()
        nice_stats[node_type] = {}
        if total != 0:
            try:
                documented = total - stats["undocumented_" + node_type]
                percent = (documented * 100.0) / total
                nice_stats[node_type]["percent_documented"] = "%.2f" % percent
            except KeyError:
                nice_stats[node_type]["percent_documented"] = "NC"
            try:
                percent = (stats["badname_" + node_type] * 100.0) / total
                nice_stats[node_type]["percent_badname"] = "%.2f" % percent
            except KeyError:
                nice_stats[node_type]["percent_badname"] = "NC"
    lines = ("type", "number", "old number", "difference", "%documented", "%badname")
    for node_type in ("module", "class", "method", "function"):
        new = stats[node_type]
        lines += (
            node_type,
            str(new),
            "NC",
            "NC",
            nice_stats[node_type].get("percent_documented", "0"),
            nice_stats[node_type].get("percent_badname", "0"),
        )
    sect.append(reporter_nodes.Table(children=lines, cols=6, rheaders=1))

def
report_by_type_stats
(
sect
,
stats
,
_
)
:
nice_stats
=
{
}
for
node_type
in
(
"module"
,
"class"
,
"method"
,
"function"
)
:
try
:
total
=
stats
[
node_type
]
except
KeyError
:
raise
exceptions
.
EmptyReportError
(
)
nice_stats
[
node_type
]
=
{
}
if
total
!=
0
:
try
:
documented
=
total
stats
[
"undocumented_"
+
node_type
]
percent
=
(
documented
*
100.0
)
/
total
nice_stats
[
node_type
]
[
"percent_documented"
]
=
"%.2f"
%
percent
except
KeyError
:
nice_stats
[
node_type
]
[
"percent_documented"
]
=
"NC"
try
:
percent
=
(
stats
[
"badname_"
+
node_type
]
*
100.0
)
/
total
nice_stats
[
node_type
]
[
"percent_badname"
]
=
"%.2f"
%
percent
except
KeyError
:
nice_stats
[
node_type
]
[
"percent_badname"
]
=
"NC"
lines
=
(
"type"
,
"number"
,
"old number"
,
"difference"
,
"%documented"
,
"%badname"
)
for
node_type
in
(
"module"
,
"class"
,
"method"
,
"function"
)
:
new
=
stats
[
node_type
]
lines
+=
(
node_type
,
str
(
new
)
,
"NC"
,
"NC"
,
nice_stats
[
node_type
]
.
get
(
"percent_documented"
,
"0"
)
,
nice_stats
[
node_type
]
.
get
(
"percent_badname"
,
"0"
)
,
)
sect
.
append
(
reporter_nodes
.
Table
(
children
=
lines
,
cols
=
6
,
rheaders
=
1
)
)


def redefined_by_decorator(node):
    """return True if the object is a method redefined via decorator.

    For example:
        @property
        def x(self): return self._x
        @x.setter
        def x(self, value): self._x = value
    """
    if node.decorators:
        for decorator in node.decorators.nodes:
            if (
                isinstance(decorator, astroid.Attribute)
                and getattr(decorator.expr, "name", None) == node.name
            ):
                return True
    return False

def redefined_by_decorator ( node ) : if node . decorators : for decorator in node . decorators . nodes : if ( isinstance ( decorator , astroid . Attribute ) and getattr ( decorator . expr , "name" , None ) == node . name ) : return True return False

return True if the object is a method redefined via decorator .


def _is_one_arg_pos_call(call):
    """Is this a call with exactly 1 argument,
    where that argument is positional?
    """
    return isinstance(call, astroid.Call) and len(call.args) == 1 and not call.keywords

def _is_one_arg_pos_call ( call ) : return isinstance ( call , astroid . Call ) and len ( call . args ) == 1 and not call . keywords

Is this a call with exactly 1 argument where that argument is positional?


def visit_starred(self, node):
        """Check that a Starred expression is used in an assignment target."""
        if isinstance(node.parent, astroid.Call):
            # f(*args) is converted to Call(args=[Starred]), so ignore
            # them for this check.
            return
        if PY35 and isinstance(
            node.parent, (astroid.List, astroid.Tuple, astroid.Set, astroid.Dict)
        ):
            # PEP 448 unpacking.
            return

        stmt = node.statement()
        if not isinstance(stmt, astroid.Assign):
            return

        if stmt.value is node or stmt.value.parent_of(node):
            self.add_message("star-needs-assignment-target", node=node)

def visit_starred ( self , node ) : if isinstance ( node . parent , astroid . Call ) : return if PY35 and isinstance ( node . parent , ( astroid . List , astroid . Tuple , astroid . Set , astroid . Dict ) ) : return stmt = node . statement ( ) if not isinstance ( stmt , astroid . Assign ) : return if stmt . value is node or stmt . value . parent_of ( node ) : self . add_message ( "star-needs-assignment-target" , node = node )

Check that a Starred expression is used in an assignment target .


def _check_nonlocal_and_global(self, node):
        """Check that a name is both nonlocal and global."""

        def same_scope(current):
            return current.scope() is node

        from_iter = itertools.chain.from_iterable
        nonlocals = set(
            from_iter(
                child.names
                for child in node.nodes_of_class(astroid.Nonlocal)
                if same_scope(child)
            )
        )

        if not nonlocals:
            return

        global_vars = set(
            from_iter(
                child.names
                for child in node.nodes_of_class(astroid.Global)
                if same_scope(child)
            )
        )
        for name in nonlocals.intersection(global_vars):
            self.add_message("nonlocal-and-global", args=(name,), node=node)

def _check_nonlocal_and_global ( self , node ) : def same_scope ( current ) : return current . scope ( ) is node from_iter = itertools . chain . from_iterable nonlocals = set ( from_iter ( child . names for child in node . nodes_of_class ( astroid . Nonlocal ) if same_scope ( child ) ) ) if not nonlocals : return global_vars = set ( from_iter ( child . names for child in node . nodes_of_class ( astroid . Global ) if same_scope ( child ) ) ) for name in nonlocals . intersection ( global_vars ) : self . add_message ( "nonlocal-and-global" , args = ( name , ) , node = node )

Check that a name is both nonlocal and global .


def visit_call(self, node):
        """ Check instantiating abstract class with
        abc.ABCMeta as metaclass.
        """
        try:
            for inferred in node.func.infer():
                self._check_inferred_class_is_abstract(inferred, node)
        except astroid.InferenceError:
            return

def visit_call ( self , node ) : try : for inferred in node . func . infer ( ) : self . _check_inferred_class_is_abstract ( inferred , node ) except astroid . InferenceError : return

Check instantiating abstract class with abc . ABCMeta as metaclass .


def _check_else_on_loop(self, node):
        """Check that any loop with an else clause has a break statement."""
        if node.orelse and not _loop_exits_early(node):
            self.add_message(
                "useless-else-on-loop",
                node=node,
                # This is not optimal, but the line previous
                # to the first statement in the else clause
                # will usually be the one that contains the else:.
                line=node.orelse[0].lineno - 1,
            )

def _check_else_on_loop ( self , node ) : if node . orelse and not _loop_exits_early ( node ) : self . add_message ( "useless-else-on-loop" , node = node , line = node . orelse [ 0 ] . lineno - 1 , )

Check that any loop with an else clause has a break statement .


def _check_in_loop(self, node, node_name):
        """check that a node is inside a for or while loop"""
        _node = node.parent
        while _node:
            if isinstance(_node, (astroid.For, astroid.While)):
                if node not in _node.orelse:
                    return

            if isinstance(_node, (astroid.ClassDef, astroid.FunctionDef)):
                break
            if (
                isinstance(_node, astroid.TryFinally)
                and node in _node.finalbody
                and isinstance(node, astroid.Continue)
            ):
                self.add_message("continue-in-finally", node=node)

            _node = _node.parent

        self.add_message("not-in-loop", node=node, args=node_name)

def _check_in_loop ( self , node , node_name ) : _node = node . parent while _node : if isinstance ( _node , ( astroid . For , astroid . While ) ) : if node not in _node . orelse : return if isinstance ( _node , ( astroid . ClassDef , astroid . FunctionDef ) ) : break if ( isinstance ( _node , astroid . TryFinally ) and node in _node . finalbody and isinstance ( node , astroid . Continue ) ) : self . add_message ( "continue-in-finally" , node = node ) _node = _node . parent self . add_message ( "not-in-loop" , node = node , args = node_name )


def open(self):
        """initialize visit variables and statistics
        """
        self._tryfinallys = []
        self.stats = self.linter.add_stats(module=0, function=0, method=0, class_=0)

def open ( self ) : self . _tryfinallys = [ ] self . stats = self . linter . add_stats ( module = 0 , function = 0 , method = 0 , class_ = 0 )


def visit_expr(self, node):
        """check for various kind of statements without effect"""
        expr = node.value
        if isinstance(expr, astroid.Const) and isinstance(expr.value, str):
            # treat string statement in a separated message
            # Handle PEP-257 attribute docstrings.
            # An attribute docstring is defined as being a string right after
            # an assignment at the module level, class level or __init__ level.
            scope = expr.scope()
            if isinstance(
                scope, (astroid.ClassDef, astroid.Module, astroid.FunctionDef)
            ):
                if isinstance(scope, astroid.FunctionDef) and scope.name != "__init__":
                    pass
                else:
                    sibling = expr.previous_sibling()
                    if (
                        sibling is not None
                        and sibling.scope() is scope
                        and isinstance(sibling, (astroid.Assign, astroid.AnnAssign))
                    ):
                        return
            self.add_message("pointless-string-statement", node=node)
            return

        # Ignore if this is :
        # * a direct function call
        # * the unique child of a try/except body
        # * a yieldd statement
        # * an ellipsis (which can be used on Python 3 instead of pass)
        # warn W0106 if we have any underlying function call (we can't predict
        # side effects), else pointless-statement
        if isinstance(
            expr, (astroid.Yield, astroid.Await, astroid.Ellipsis, astroid.Call)
        ) or (
            isinstance(node.parent, astroid.TryExcept) and node.parent.body == [node]
        ):
            return
        if any(expr.nodes_of_class(astroid.Call)):
            self.add_message(
                "expression-not-assigned", node=node, args=expr.as_string()
            )
        else:
            self.add_message("pointless-statement", node=node)

def visit_expr ( self , node ) : expr = node . value if isinstance ( expr , astroid . Const ) and isinstance ( expr . value , str ) : scope = expr . scope ( ) if isinstance ( scope , ( astroid . ClassDef , astroid . Module , astroid . FunctionDef ) ) : if isinstance ( scope , astroid . FunctionDef ) and scope . name != "__init__" : pass else : sibling = expr . previous_sibling ( ) if ( sibling is not None and sibling . scope ( ) is scope and isinstance ( sibling , ( astroid . Assign , astroid . AnnAssign ) ) ) : return self . add_message ( "pointless-string-statement" , node = node ) return if isinstance ( expr , ( astroid . Yield , astroid . Await , astroid . Ellipsis , astroid . Call ) ) or ( isinstance ( node . parent , astroid . TryExcept ) and node . parent . body == [ node ] ) : return if any ( expr . nodes_of_class ( astroid . Call ) ) : self . add_message ( "expression-not-assigned" , node = node , args = expr . as_string ( ) ) else : self . add_message ( "pointless-statement" , node = node )


def visit_lambda(self, node):
        """check whether or not the lambda is suspicious
        """
        # if the body of the lambda is a call expression with the same
        # argument list as the lambda itself, then the lambda is
        # possibly unnecessary and at least suspicious.
        if node.args.defaults:
            # If the arguments of the lambda include defaults, then a
            # judgment cannot be made because there is no way to check
            # that the defaults defined by the lambda are the same as
            # the defaults defined by the function called in the body
            # of the lambda.
            return
        call = node.body
        if not isinstance(call, astroid.Call):
            # The body of the lambda must be a function call expression
            # for the lambda to be unnecessary.
            return
        if isinstance(node.body.func, astroid.Attribute) and isinstance(
            node.body.func.expr, astroid.Call
        ):
            # Chained call, the intermediate call might
            # return something else (but we don't check that, yet).
            return

        call_site = CallSite.from_call(call)
        ordinary_args = list(node.args.args)
        new_call_args = list(self._filter_vararg(node, call.args))
        if node.args.kwarg:
            if self._has_variadic_argument(call.kwargs, node.args.kwarg):
                return

        if node.args.vararg:
            if self._has_variadic_argument(call.starargs, node.args.vararg):
                return
        elif call.starargs:
            return

        if call.keywords:
            # Look for additional keyword arguments that are not part
            # of the lambda's signature
            lambda_kwargs = {keyword.name for keyword in node.args.defaults}
            if len(lambda_kwargs) != len(call_site.keyword_arguments):
                # Different lengths, so probably not identical
                return
            if set(call_site.keyword_arguments).difference(lambda_kwargs):
                return

        # The "ordinary" arguments must be in a correspondence such that:
        # ordinary_args[i].name == call.args[i].name.
        if len(ordinary_args) != len(new_call_args):
            return
        for arg, passed_arg in zip(ordinary_args, new_call_args):
            if not isinstance(passed_arg, astroid.Name):
                return
            if arg.name != passed_arg.name:
                return

        self.add_message("unnecessary-lambda", line=node.fromlineno, node=node)

def visit_lambda ( self , node ) : if node . args . defaults : return call = node . body if not isinstance ( call , astroid . Call ) : return if isinstance ( node . body . func , astroid . Attribute ) and isinstance ( node . body . func . expr , astroid . Call ) : return call_site = CallSite . from_call ( call ) ordinary_args = list ( node . args . args ) new_call_args = list ( self . _filter_vararg ( node , call . args ) ) if node . args . kwarg : if self . _has_variadic_argument ( call . kwargs , node . args . kwarg ) : return if node . args . vararg : if self . _has_variadic_argument ( call . starargs , node . args . vararg ) : return elif call . starargs : return if call . keywords : lambda_kwargs = { keyword . name for keyword in node . args . defaults } if len ( lambda_kwargs ) != len ( call_site . keyword_arguments ) : return if set ( call_site . keyword_arguments ) . difference ( lambda_kwargs ) : return if len ( ordinary_args ) != len ( new_call_args ) : return for arg , passed_arg in zip ( ordinary_args , new_call_args ) : if not isinstance ( passed_arg , astroid . Name ) : return if arg . name != passed_arg . name : return self . add_message ( "unnecessary-lambda" , line = node . fromlineno , node = node )


def visit_assert(self, node):
        """check the use of an assert statement on a tuple."""
        if (
            node.fail is None
            and isinstance(node.test, astroid.Tuple)
            and len(node.test.elts) == 2
        ):
            self.add_message("assert-on-tuple", node=node)

def visit_assert ( self , node ) : if ( node . fail is None and isinstance ( node . test , astroid . Tuple ) and len ( node . test . elts ) == 2 ) : self . add_message ( "assert-on-tuple" , node = node )

check the use of an assert statement on a tuple .


def visit_dict(self, node):
        """check duplicate key in dictionary"""
        keys = set()
        for k, _ in node.items:
            if isinstance(k, astroid.Const):
                key = k.value
                if key in keys:
                    self.add_message("duplicate-key", node=node, args=key)
                keys.add(key)

def visit_dict ( self , node ) : keys = set ( ) for k , _ in node . items : if isinstance ( k , astroid . Const ) : key = k . value if key in keys : self . add_message ( "duplicate-key" , node = node , args = key ) keys . add ( key )


def _check_unreachable(self, node):
        """check unreachable code"""
        unreach_stmt = node.next_sibling()
        if unreach_stmt is not None:
            self.add_message("unreachable", node=unreach_stmt)

def _check_unreachable ( self , node ) : unreach_stmt = node . next_sibling ( ) if unreach_stmt is not None : self . add_message ( "unreachable" , node = unreach_stmt )


def _check_not_in_finally(self, node, node_name, breaker_classes=()):
        """check that a node is not inside a finally clause of a
        try...finally statement.
        If we found before a try...finally bloc a parent which its type is
        in breaker_classes, we skip the whole check."""
        # if self._tryfinallys is empty, we're not an in try...finally block
        if not self._tryfinallys:
            return
        # the node could be a grand-grand...-children of the try...finally
        _parent = node.parent
        _node = node
        while _parent and not isinstance(_parent, breaker_classes):
            if hasattr(_parent, "finalbody") and _node in _parent.finalbody:
                self.add_message("lost-exception", node=node, args=node_name)
                return
            _node = _parent
            _parent = _node.parent

def _check_not_in_finally ( self , node , node_name , breaker_classes = ( ) ) : if not self . _tryfinallys : return _parent = node . parent _node = node while _parent and not isinstance ( _parent , breaker_classes ) : if hasattr ( _parent , "finalbody" ) and _node in _parent . finalbody : self . add_message ( "lost-exception" , node = node , args = node_name ) return _node = _parent _parent = _node . parent

check that a node is not inside a finally clause of a try ... finally statement . If we found before a try ... finally bloc a parent which its type is in breaker_classes we skip the whole check .


def _check_reversed(self, node):
        """ check that the argument to `reversed` is a sequence """
        try:
            argument = utils.safe_infer(utils.get_argument_from_call(node, position=0))
        except utils.NoSuchArgumentError:
            pass
        else:
            if argument is astroid.Uninferable:
                return
            if argument is None:
                # Nothing was infered.
                # Try to see if we have iter().
                if isinstance(node.args[0], astroid.Call):
                    try:
                        func = next(node.args[0].func.infer())
                    except astroid.InferenceError:
                        return
                    if getattr(
                        func, "name", None
                    ) == "iter" and utils.is_builtin_object(func):
                        self.add_message("bad-reversed-sequence", node=node)
                return

            if isinstance(argument, (astroid.List, astroid.Tuple)):
                return

            if isinstance(argument, astroid.Instance):
                if argument._proxied.name == "dict" and utils.is_builtin_object(
                    argument._proxied
                ):
                    self.add_message("bad-reversed-sequence", node=node)
                    return
                if any(
                    ancestor.name == "dict" and utils.is_builtin_object(ancestor)
                    for ancestor in argument._proxied.ancestors()
                ):
                    # Mappings aren't accepted by reversed(), unless
                    # they provide explicitly a __reversed__ method.
                    try:
                        argument.locals[REVERSED_PROTOCOL_METHOD]
                    except KeyError:
                        self.add_message("bad-reversed-sequence", node=node)
                    return

            if hasattr(argument, "getattr"):
                # everything else is not a proper sequence for reversed()
                for methods in REVERSED_METHODS:
                    for meth in methods:
                        try:
                            argument.getattr(meth)
                        except astroid.NotFoundError:
                            break
                    else:
                        break
                else:
                    self.add_message("bad-reversed-sequence", node=node)
            else:
                self.add_message("bad-reversed-sequence", node=node)

def _check_reversed ( self , node ) : try : argument = utils . safe_infer ( utils . get_argument_from_call ( node , position = 0 ) ) except utils . NoSuchArgumentError : pass else : if argument is astroid . Uninferable : return if argument is None : if isinstance ( node . args [ 0 ] , astroid . Call ) : try : func = next ( node . args [ 0 ] . func . infer ( ) ) except astroid . InferenceError : return if getattr ( func , "name" , None ) == "iter" and utils . is_builtin_object ( func ) : self . add_message ( "bad-reversed-sequence" , node = node ) return if isinstance ( argument , ( astroid . List , astroid . Tuple ) ) : return if isinstance ( argument , astroid . Instance ) : if argument . _proxied . name == "dict" and utils . is_builtin_object ( argument . _proxied ) : self . add_message ( "bad-reversed-sequence" , node = node ) return if any ( ancestor . name == "dict" and utils . is_builtin_object ( ancestor ) for ancestor in argument . _proxied . ancestors ( ) ) : try : argument . locals [ REVERSED_PROTOCOL_METHOD ] except KeyError : self . add_message ( "bad-reversed-sequence" , node = node ) return if hasattr ( argument , "getattr" ) : for methods in REVERSED_METHODS : for meth in methods : try : argument . getattr ( meth ) except astroid . NotFoundError : break else : break else : self . add_message ( "bad-reversed-sequence" , node = node ) else : self . add_message ( "bad-reversed-sequence" , node = node )

check that the argument to reversed is a sequence


def visit_assignname(self, node):
        """check module level assigned names"""
        self._check_assign_to_new_keyword_violation(node.name, node)
        frame = node.frame()
        assign_type = node.assign_type()
        if isinstance(assign_type, astroid.Comprehension):
            self._check_name("inlinevar", node.name, node)
        elif isinstance(frame, astroid.Module):
            if isinstance(assign_type, astroid.Assign) and not in_loop(assign_type):
                if isinstance(utils.safe_infer(assign_type.value), astroid.ClassDef):
                    self._check_name("class", node.name, node)
                else:
                    if not _redefines_import(node):
                        # Don't emit if the name redefines an import
                        # in an ImportError except handler.
                        self._check_name("const", node.name, node)
            elif isinstance(assign_type, astroid.ExceptHandler):
                self._check_name("variable", node.name, node)
        elif isinstance(frame, astroid.FunctionDef):
            # global introduced variable aren't in the function locals
            if node.name in frame and node.name not in frame.argnames():
                if not _redefines_import(node):
                    self._check_name("variable", node.name, node)
        elif isinstance(frame, astroid.ClassDef):
            if not list(frame.local_attr_ancestors(node.name)):
                self._check_name("class_attribute", node.name, node)

def visit_assignname ( self , node ) : self . _check_assign_to_new_keyword_violation ( node . name , node ) frame = node . frame ( ) assign_type = node . assign_type ( ) if isinstance ( assign_type , astroid . Comprehension ) : self . _check_name ( "inlinevar" , node . name , node ) elif isinstance ( frame , astroid . Module ) : if isinstance ( assign_type , astroid . Assign ) and not in_loop ( assign_type ) : if isinstance ( utils . safe_infer ( assign_type . value ) , astroid . ClassDef ) : self . _check_name ( "class" , node . name , node ) else : if not _redefines_import ( node ) : self . _check_name ( "const" , node . name , node ) elif isinstance ( assign_type , astroid . ExceptHandler ) : self . _check_name ( "variable" , node . name , node ) elif isinstance ( frame , astroid . FunctionDef ) : if node . name in frame and node . name not in frame . argnames ( ) : if not _redefines_import ( node ) : self . _check_name ( "variable" , node . name , node ) elif isinstance ( frame , astroid . ClassDef ) : if not list ( frame . local_attr_ancestors ( node . name ) ) : self . _check_name ( "class_attribute" , node . name , node )


def _check_name(self, node_type, name, node, confidence=interfaces.HIGH):
        """check for a name using the type's regexp"""

        def _should_exempt_from_invalid_name(node):
            if node_type == "variable":
                inferred = utils.safe_infer(node)
                if isinstance(inferred, astroid.ClassDef):
                    return True
            return False

        if utils.is_inside_except(node):
            clobbering, _ = utils.clobber_in_except(node)
            if clobbering:
                return
        if name in self.config.good_names:
            return
        if name in self.config.bad_names:
            self.stats["badname_" + node_type] += 1
            self.add_message("blacklisted-name", node=node, args=name)
            return
        regexp = self._name_regexps[node_type]
        match = regexp.match(name)

        if _is_multi_naming_match(match, node_type, confidence):
            name_group = self._find_name_group(node_type)
            bad_name_group = self._bad_names.setdefault(name_group, {})
            warnings = bad_name_group.setdefault(match.lastgroup, [])
            warnings.append((node, node_type, name, confidence))

        if match is None and not _should_exempt_from_invalid_name(node):
            self._raise_name_warning(node, node_type, name, confidence)

def _check_name ( self , node_type , name , node , confidence = interfaces . HIGH ) : def _should_exempt_from_invalid_name ( node ) : if node_type == "variable" : inferred = utils . safe_infer ( node ) if isinstance ( inferred , astroid . ClassDef ) : return True return False if utils . is_inside_except ( node ) : clobbering , _ = utils . clobber_in_except ( node ) if clobbering : return if name in self . config . good_names : return if name in self . config . bad_names : self . stats [ "badname_" + node_type ] += 1 self . add_message ( "blacklisted-name" , node = node , args = name ) return regexp = self . _name_regexps [ node_type ] match = regexp . match ( name ) if _is_multi_naming_match ( match , node_type , confidence ) : name_group = self . _find_name_group ( node_type ) bad_name_group = self . _bad_names . setdefault ( name_group , { } ) warnings = bad_name_group . setdefault ( match . lastgroup , [ ] ) warnings . append ( ( node , node_type , name , confidence ) ) if match is None and not _should_exempt_from_invalid_name ( node ) : self . _raise_name_warning ( node , node_type , name , confidence )

check for a name using the type s regexp


def _check_docstring(
        self, node_type, node, report_missing=True, confidence=interfaces.HIGH
    ):
        """check the node has a non empty docstring"""
        docstring = node.doc
        if docstring is None:
            if not report_missing:
                return
            lines = utils.get_node_last_lineno(node) - node.lineno

            if node_type == "module" and not lines:
                # If the module has no body, there's no reason
                # to require a docstring.
                return
            max_lines = self.config.docstring_min_length

            if node_type != "module" and max_lines > -1 and lines < max_lines:
                return
            self.stats["undocumented_" + node_type] += 1
            if (
                node.body
                and isinstance(node.body[0], astroid.Expr)
                and isinstance(node.body[0].value, astroid.Call)
            ):
                # Most likely a string with a format call. Let's see.
                func = utils.safe_infer(node.body[0].value.func)
                if isinstance(func, astroid.BoundMethod) and isinstance(
                    func.bound, astroid.Instance
                ):
                    # Strings in Python 3, others in Python 2.
                    if PY3K and func.bound.name == "str":
                        return
                    if func.bound.name in ("str", "unicode", "bytes"):
                        return
            self.add_message(
                "missing-docstring", node=node, args=(node_type,), confidence=confidence
            )
        elif not docstring.strip():
            self.stats["undocumented_" + node_type] += 1
            self.add_message(
                "empty-docstring", node=node, args=(node_type,), confidence=confidence
            )

def _check_docstring ( self , node_type , node , report_missing = True , confidence = interfaces . HIGH ) : docstring = node . doc if docstring is None : if not report_missing : return lines = utils . get_node_last_lineno ( node ) - node . lineno if node_type == "module" and not lines : return max_lines = self . config . docstring_min_length if node_type != "module" and max_lines > - 1 and lines < max_lines : return self . stats [ "undocumented_" + node_type ] += 1 if ( node . body and isinstance ( node . body [ 0 ] , astroid . Expr ) and isinstance ( node . body [ 0 ] . value , astroid . Call ) ) : func = utils . safe_infer ( node . body [ 0 ] . value . func ) if isinstance ( func , astroid . BoundMethod ) and isinstance ( func . bound , astroid . Instance ) : if PY3K and func . bound . name == "str" : return if func . bound . name in ( "str" , "unicode" , "bytes" ) : return self . add_message ( "missing-docstring" , node = node , args = ( node_type , ) , confidence = confidence ) elif not docstring . strip ( ) : self . stats [ "undocumented_" + node_type ] += 1 self . add_message ( "empty-docstring" , node = node , args = ( node_type , ) , confidence = confidence )


def _check_literal_comparison(self, literal, node):
        """Check if we compare to a literal, which is usually what we do not want to do."""
        nodes = (astroid.List, astroid.Tuple, astroid.Dict, astroid.Set)
        is_other_literal = isinstance(literal, nodes)
        is_const = False
        if isinstance(literal, astroid.Const):
            if isinstance(literal.value, bool) or literal.value is None:
                # Not interested in this values.
                return
            is_const = isinstance(literal.value, (bytes, str, int, float))

        if is_const or is_other_literal:
            self.add_message("literal-comparison", node=node)

def _check_literal_comparison ( self , literal , node ) : nodes = ( astroid . List , astroid . Tuple , astroid . Dict , astroid . Set ) is_other_literal = isinstance ( literal , nodes ) is_const = False if isinstance ( literal , astroid . Const ) : if isinstance ( literal . value , bool ) or literal . value is None : return is_const = isinstance ( literal . value , ( bytes , str , int , float ) ) if is_const or is_other_literal : self . add_message ( "literal-comparison" , node = node )

Check if we compare to a literal which is usually what we do not want to do .


def _subgraph(self, node, name, extra_blocks=()):
        """create the subgraphs representing any `if` and `for` statements"""
        if self.graph is None:
            # global loop
            self.graph = PathGraph(node)
            self._subgraph_parse(node, node, extra_blocks)
            self.graphs["%s%s" % (self.classname, name)] = self.graph
            self.reset()
        else:
            self._append_node(node)
            self._subgraph_parse(node, node, extra_blocks)

def _subgraph ( self , node , name , extra_blocks = ( ) ) : if self . graph is None : self . graph = PathGraph ( node ) self . _subgraph_parse ( node , node , extra_blocks ) self . graphs [ "%s%s" % ( self . classname , name ) ] = self . graph self . reset ( ) else : self . _append_node ( node ) self . _subgraph_parse ( node , node , extra_blocks )

create the subgraphs representing any if and for statements


def _subgraph_parse(
        self, node, pathnode, extra_blocks
    ):  # pylint: disable=unused-argument
        """parse the body and any `else` block of `if` and `for` statements"""
        loose_ends = []
        self.tail = node
        self.dispatch_list(node.body)
        loose_ends.append(self.tail)
        for extra in extra_blocks:
            self.tail = node
            self.dispatch_list(extra.body)
            loose_ends.append(self.tail)
        if node.orelse:
            self.tail = node
            self.dispatch_list(node.orelse)
            loose_ends.append(self.tail)
        else:
            loose_ends.append(node)
        if node:
            bottom = "%s" % self._bottom_counter
            self._bottom_counter += 1
            for le in loose_ends:
                self.graph.connect(le, bottom)
            self.tail = bottom

def _subgraph_parse ( self , node , pathnode , extra_blocks ) : loose_ends = [ ] self . tail = node self . dispatch_list ( node . body ) loose_ends . append ( self . tail ) for extra in extra_blocks : self . tail = node self . dispatch_list ( extra . body ) loose_ends . append ( self . tail ) if node . orelse : self . tail = node self . dispatch_list ( node . orelse ) loose_ends . append ( self . tail ) else : loose_ends . append ( node ) if node : bottom = "%s" % self . _bottom_counter self . _bottom_counter += 1 for le in loose_ends : self . graph . connect ( le , bottom ) self . tail = bottom

parse the body and any else block of if and for statements


def visit_module(self, node):
        """visit an astroid.Module node to check too complex rating and
        add message if is greather than max_complexity stored from options"""
        visitor = PathGraphingAstVisitor()
        for child in node.body:
            visitor.preorder(child, visitor)
        for graph in visitor.graphs.values():
            complexity = graph.complexity()
            node = graph.root
            if hasattr(node, "name"):
                node_name = "'%s'" % node.name
            else:
                node_name = "This '%s'" % node.__class__.__name__.lower()
            if complexity <= self.config.max_complexity:
                continue
            self.add_message(
                "too-complex", node=node, confidence=HIGH, args=(node_name, complexity)
            )

def
visit_module
(
self
,
node
)
:
visitor
=
PathGraphingAstVisitor
(
)
for
child
in
node
.
body
:
visitor
.
preorder
(
child
,
visitor
)
for
graph
in
visitor
.
graphs
.
values
(
)
:
complexity
=
graph
.
complexity
(
)
node
=
graph
.
root
if
hasattr
(
node
,
"name"
)
:
node_name
=
"'%s'"
%
node
.
name
else
:
node_name
=
"This '%s'"
%
node
.
__class__
.
__name__
.
lower
(
)
if
complexity
<=
self
.
config
.
max_complexity
:
continue
self
.
add_message
(
"too-complex"
,
node
=
node
,
confidence
=
HIGH
,
args
=
(
node_name
,
complexity
)
)

visit an astroid . Module node to check too complex rating and add message if is greather than max_complexity stored from options