def install(**kwargs):
    """setup entry point"""
    if USE_SETUPTOOLS:
        if "--force-manifest" in sys.argv:
            sys.argv.remove("--force-manifest")
    packages = [modname] + get_packages(join(base_dir, "pylint"), modname)
    if USE_SETUPTOOLS:
        if install_requires:
            kwargs["install_requires"] = install_requires
            kwargs["dependency_links"] = dependency_links
        kwargs["entry_points"] = {
            "console_scripts": [
                "pylint = pylint:run_pylint",
                "epylint = pylint:run_epylint",
                "pyreverse = pylint:run_pyreverse",
                "symilar = pylint:run_symilar",
            ]
        }
    kwargs["packages"] = packages
    cmdclass = {"install_lib": MyInstallLib, "build_py": build_py}
    if easy_install_lib:
        cmdclass["easy_install"] = easy_install
    return setup(
        name=distname,
        version=__pkginfo__["version"],
        license=__pkginfo__["license"],
        description=__pkginfo__["description"],
        long_description=long_description,
        author=__pkginfo__["author"],
        author_email=__pkginfo__["author_email"],
        url=__pkginfo__["web"],
        scripts=ensure_scripts(scripts),
        classifiers=__pkginfo__["classifiers"],
        data_files=data_files,
        ext_modules=ext_modules,
        cmdclass=cmdclass,
        extras_require=extras_require,
        test_suite="test",
        python_requires=">=3.4.*",
        setup_requires=["pytest-runner"],
        tests_require=["pytest"],
        **kwargs
    )

def
install
(
*
*
kwargs
)
:
if
USE_SETUPTOOLS
:
if
"--force-manifest"
in
sys
.
argv
:
sys
.
argv
.
remove
(
"--force-manifest"
)
packages
=
[
modname
]
+
get_packages
(
join
(
base_dir
,
"pylint"
)
,
modname
)
if
USE_SETUPTOOLS
:
if
install_requires
:
kwargs
[
"install_requires"
]
=
install_requires
kwargs
[
"dependency_links"
]
=
dependency_links
kwargs
[
"entry_points"
]
=
{
"console_scripts"
:
[
"pylint = pylint:run_pylint"
,
"epylint = pylint:run_epylint"
,
"pyreverse = pylint:run_pyreverse"
,
"symilar = pylint:run_symilar"
,
]
}
kwargs
[
"packages"
]
=
packages
cmdclass
=
{
"install_lib"
:
MyInstallLib
,
"build_py"
:
build_py
}
if
easy_install_lib
:
cmdclass
[
"easy_install"
]
=
easy_install
return
setup
(
name
=
distname
,
version
=
__pkginfo__
[
"version"
]
,
license
=
__pkginfo__
[
"license"
]
,
description
=
__pkginfo__
[
"description"
]
,
long_description
=
long_description
,
author
=
__pkginfo__
[
"author"
]
,
author_email
=
__pkginfo__
[
"author_email"
]
,
url
=
__pkginfo__
[
"web"
]
,
scripts
=
ensure_scripts
(
scripts
)
,
classifiers
=
__pkginfo__
[
"classifiers"
]
,
data_files
=
data_files
,
ext_modules
=
ext_modules
,
cmdclass
=
cmdclass
,
extras_require
=
extras_require
,
test_suite
=
"test"
,
python_requires
=
">=3.4.*"
,
setup_requires
=
[
"pytest-runner"
]
,
tests_require
=
[
"pytest"
]
,
*
*
kwargs
)


def run(self):
        """overridden from install_lib class"""
        install_lib.install_lib.run(self)
        # manually install included directories if any
        if include_dirs:
            for directory in include_dirs:
                dest = join(self.install_dir, directory)
                if sys.version_info >= (3, 0):
                    exclude = {"invalid_encoded_data*", "unknown_encoding*"}
                else:
                    exclude = set()
                shutil.rmtree(dest, ignore_errors=True)
                shutil.copytree(
                    directory, dest, ignore=shutil.ignore_patterns(*exclude)
                )


def report_similarities(sect, stats, old_stats):
    """make a layout with some stats about duplication"""
    lines = ["", "now", "previous", "difference"]
    lines += table_lines_from_stats(
        stats, old_stats, ("nb_duplicated_lines", "percent_duplicated_lines")
    )
    sect.append(Table(children=lines, cols=4, rheaders=1, cheaders=1))

def report_similarities ( sect , stats , old_stats ) : lines = [ "" , "now" , "previous" , "difference" ] lines += table_lines_from_stats ( stats , old_stats , ( "nb_duplicated_lines" , "percent_duplicated_lines" ) ) sect . append ( Table ( children = lines , cols = 4 , rheaders = 1 , cheaders = 1 ) )


def Run(argv=None):
    """standalone command line access point"""
    if argv is None:
        argv = sys.argv[1:]
    from getopt import getopt

    s_opts = "hdi"
    l_opts = (
        "help",
        "duplicates=",
        "ignore-comments",
        "ignore-imports",
        "ignore-docstrings",
    )
    min_lines = 4
    ignore_comments = False
    ignore_docstrings = False
    ignore_imports = False
    opts, args = getopt(argv, s_opts, l_opts)
    for opt, val in opts:
        if opt in ("-d", "--duplicates"):
            min_lines = int(val)
        elif opt in ("-h", "--help"):
            usage()
        elif opt in ("-i", "--ignore-comments"):
            ignore_comments = True
        elif opt in ("--ignore-docstrings",):
            ignore_docstrings = True
        elif opt in ("--ignore-imports",):
            ignore_imports = True
    if not args:
        usage(1)
    sim = Similar(min_lines, ignore_comments, ignore_docstrings, ignore_imports)
    for filename in args:
        with open(filename) as stream:
            sim.append_stream(filename, stream)
    sim.run()
    sys.exit(0)

def Run ( argv = None ) : if argv is None : argv = sys . argv [ 1 : ] from getopt import getopt s_opts = "hdi" l_opts = ( "help" , "duplicates=" , "ignore-comments" , "ignore-imports" , "ignore-docstrings" , ) min_lines = 4 ignore_comments = False ignore_docstrings = False ignore_imports = False opts , args = getopt ( argv , s_opts , l_opts ) for opt , val in opts : if opt in ( "-d" , "--duplicates" ) : min_lines = int ( val ) elif opt in ( "-h" , "--help" ) : usage ( ) elif opt in ( "-i" , "--ignore-comments" ) : ignore_comments = True elif opt in ( "--ignore-docstrings" , ) : ignore_docstrings = True elif opt in ( "--ignore-imports" , ) : ignore_imports = True if not args : usage ( 1 ) sim = Similar ( min_lines , ignore_comments , ignore_docstrings , ignore_imports ) for filename in args : with open ( filename ) as stream : sim . append_stream ( filename , stream ) sim . run ( ) sys . exit ( 0 )


def append_stream(self, streamid, stream, encoding=None):
        """append a file to search for similarities"""
        if encoding is None:
            readlines = stream.readlines
        else:
            readlines = decoding_stream(stream, encoding).readlines
        try:
            self.linesets.append(
                LineSet(
                    streamid,
                    readlines(),
                    self.ignore_comments,
                    self.ignore_docstrings,
                    self.ignore_imports,
                )
            )
        except UnicodeDecodeError:
            pass

def append_stream ( self , streamid , stream , encoding = None ) : if encoding is None : readlines = stream . readlines else : readlines = decoding_stream ( stream , encoding ) . readlines try : self . linesets . append ( LineSet ( streamid , readlines ( ) , self . ignore_comments , self . ignore_docstrings , self . ignore_imports , ) ) except UnicodeDecodeError : pass


def _compute_sims(self):
        """compute similarities in appended files"""
        no_duplicates = defaultdict(list)
        for num, lineset1, idx1, lineset2, idx2 in self._iter_sims():
            duplicate = no_duplicates[num]
            for couples in duplicate:
                if (lineset1, idx1) in couples or (lineset2, idx2) in couples:
                    couples.add((lineset1, idx1))
                    couples.add((lineset2, idx2))
                    break
            else:
                duplicate.append({(lineset1, idx1), (lineset2, idx2)})
        sims = []
        for num, ensembles in no_duplicates.items():
            for couples in ensembles:
                sims.append((num, couples))
        sims.sort()
        sims.reverse()
        return sims

def _compute_sims ( self ) : no_duplicates = defaultdict ( list ) for num , lineset1 , idx1 , lineset2 , idx2 in self . _iter_sims ( ) : duplicate = no_duplicates [ num ] for couples in duplicate : if ( lineset1 , idx1 ) in couples or ( lineset2 , idx2 ) in couples : couples . add ( ( lineset1 , idx1 ) ) couples . add ( ( lineset2 , idx2 ) ) break else : duplicate . append ( { ( lineset1 , idx1 ) , ( lineset2 , idx2 ) } ) sims = [ ] for num , ensembles in no_duplicates . items ( ) : for couples in ensembles : sims . append ( ( num , couples ) ) sims . sort ( ) sims . reverse ( ) return sims


def _display_sims(self, sims):
        """display computed similarities on stdout"""
        nb_lignes_dupliquees = 0
        for num, couples in sims:
            print()
            print(num, "similar lines in", len(couples), "files")
            couples = sorted(couples)
            for lineset, idx in couples:
                print("==%s:%s" % (lineset.name, idx))
            # pylint: disable=W0631
            for line in lineset._real_lines[idx : idx + num]:
                print("  ", line.rstrip())
            nb_lignes_dupliquees += num * (len(couples) - 1)
        nb_total_lignes = sum([len(lineset) for lineset in self.linesets])
        print(
            "TOTAL lines=%s duplicates=%s percent=%.2f"
            % (
                nb_total_lignes,
                nb_lignes_dupliquees,
                nb_lignes_dupliquees * 100.0 / nb_total_lignes,
            )
        )


def _find_common(self, lineset1, lineset2):
        """find similarities in the two given linesets"""
        lines1 = lineset1.enumerate_stripped
        lines2 = lineset2.enumerate_stripped
        find = lineset2.find
        index1 = 0
        min_lines = self.min_lines
        while index1 < len(lineset1):
            skip = 1
            num = 0
            for index2 in find(lineset1[index1]):
                non_blank = 0
                for num, ((_, line1), (_, line2)) in enumerate(
                    zip(lines1(index1), lines2(index2))
                ):
                    if line1 != line2:
                        if non_blank > min_lines:
                            yield num, lineset1, index1, lineset2, index2
                        skip = max(skip, num)
                        break
                    if line1:
                        non_blank += 1
                else:
                    # we may have reach the end
                    num += 1
                    if non_blank > min_lines:
                        yield num, lineset1, index1, lineset2, index2
                    skip = max(skip, num)
            index1 += skip

def
_find_common
(
self
,
lineset1
,
lineset2
)
:
lines1
=
lineset1
.
enumerate_stripped
lines2
=
lineset2
.
enumerate_stripped
find
=
lineset2
.
find
index1
=
0
min_lines
=
self
.
min_lines
while
index1
<
len
(
lineset1
)
:
skip
=
1
num
=
0
for
index2
in
find
(
lineset1
[
index1
]
)
:
non_blank
=
0
for
num
,
(
(
_
,
line1
)
,
(
_
,
line2
)
)
in
enumerate
(
zip
(
lines1
(
index1
)
,
lines2
(
index2
)
)
)
:
if
line1
!=
line2
:
if
non_blank
>
min_lines
:
yield
num
,
lineset1
,
index1
,
lineset2
,
index2
skip
=
max
(
skip
,
num
)
break
if
line1
:
non_blank
+=
1
else
:
# we may have reach the end
num
+=
1
if
non_blank
>
min_lines
:
yield
num
,
lineset1
,
index1
,
lineset2
,
index2
skip
=
max
(
skip
,
num
)
index1
+=
skip


def _iter_sims(self):
        """iterate on similarities among all files, by making a cartesian
        product
        """
        for idx, lineset in enumerate(self.linesets[:-1]):
            for lineset2 in self.linesets[idx + 1 :]:
                for sim in self._find_common(lineset, lineset2):
                    yield sim

def _iter_sims ( self ) : for idx , lineset in enumerate ( self . linesets [ : - 1 ] ) : for lineset2 in self . linesets [ idx + 1 : ] : for sim in self . _find_common ( lineset , lineset2 ) : yield sim

iterate on similarities among all files by making a cartesian product


def enumerate_stripped(self, start_at=0):
        """return an iterator on stripped lines, starting from a given index
        if specified, else 0
        """
        idx = start_at
        if start_at:
            lines = self._stripped_lines[start_at:]
        else:
            lines = self._stripped_lines
        for line in lines:
            # if line:
            yield idx, line
            idx += 1

def
enumerate_stripped
(
self
,
start_at
=
0
)
:
idx
=
start_at
if
start_at
:
lines
=
self
.
_stripped_lines
[
start_at
:
]
else
:
lines
=
self
.
_stripped_lines
for
line
in
lines
:
# if line:
yield
idx
,
line
idx
+=
1

return an iterator on stripped lines starting from a given index if specified else 0


def _mk_index(self):
        """create the index for this set"""
        index = defaultdict(list)
        for line_no, line in enumerate(self._stripped_lines):
            if line:
                index[line].append(line_no)
        return index

def _mk_index ( self ) : index = defaultdict ( list ) for line_no , line in enumerate ( self . _stripped_lines ) : if line : index [ line ] . append ( line_no ) return index


def _definition_equivalent_to_call(definition, call):
    """Check if a definition signature is equivalent to a call."""
    if definition.kwargs:
        same_kw_variadics = definition.kwargs in call.starred_kws
    else:
        same_kw_variadics = not call.starred_kws
    if definition.varargs:
        same_args_variadics = definition.varargs in call.starred_args
    else:
        same_args_variadics = not call.starred_args
    same_kwonlyargs = all(kw in call.kws for kw in definition.kwonlyargs)
    same_args = definition.args == call.args

    no_additional_kwarg_arguments = True
    if call.kws:
        for keyword in call.kws:
            is_arg = keyword in call.args
            is_kwonly = keyword in definition.kwonlyargs
            if not is_arg and not is_kwonly:
                # Maybe this argument goes into **kwargs,
                # or it is an extraneous argument.
                # In any case, the signature is different than
                # the call site, which stops our search.
                no_additional_kwarg_arguments = False
                break

    return all(
        (
            same_args,
            same_kwonlyargs,
            same_args_variadics,
            same_kw_variadics,
            no_additional_kwarg_arguments,
        )
    )

Check if a definition signature is equivalent to a call .


def _check_arg_equality(node_a, node_b, attr_name):
    """
    Check equality of nodes based on the comparison of their attributes named attr_name.

    Args:
        node_a (astroid.node): first node to compare.
        node_b (astroid.node): second node to compare.
        attr_name (str): name of the nodes attribute to use for comparison.

    Returns:
        bool: True if node_a.attr_name == node_b.attr_name, False otherwise.
    """
    return getattr(node_a, attr_name) == getattr(node_b, attr_name)

def _check_arg_equality ( node_a , node_b , attr_name ) : return getattr ( node_a , attr_name ) == getattr ( node_b , attr_name )

Check equality of nodes based on the comparison of their attributes named attr_name .


def _has_different_parameters_default_value(original, overridden):
    """
    Check if original and overridden methods arguments have different default values

    Return True if one of the overridden arguments has a default
    value different from the default value of the original argument
    If one of the method doesn't have argument (.args is None)
    return False
    """
    if original.args is None or overridden.args is None:
        return False

    all_args = chain(original.args, original.kwonlyargs)
    original_param_names = [param.name for param in all_args]
    default_missing = object()
    for param_name in original_param_names:
        try:
            original_default = original.default_value(param_name)
        except astroid.exceptions.NoDefault:
            original_default = default_missing
        try:
            overridden_default = overridden.default_value(param_name)
        except astroid.exceptions.NoDefault:
            overridden_default = default_missing

        default_list = [
            arg == default_missing for arg in (original_default, overridden_default)
        ]
        if any(default_list) and not all(default_list):
            # Only one arg has no default value
            return True

        astroid_type_compared_attr = {
            astroid.Const: "value",
            astroid.ClassDef: "name",
            astroid.Tuple: "elts",
            astroid.List: "elts",
        }
        handled_types = tuple(
            astroid_type for astroid_type in astroid_type_compared_attr
        )
        original_type = _get_node_type(original_default, handled_types)
        if original_type:
            #  We handle only astroid types that are inside the dict astroid_type_compared_attr
            if not isinstance(overridden_default, original_type):
                #  Two args with same name but different types
                return True
            if not _check_arg_equality(
                original_default,
                overridden_default,
                astroid_type_compared_attr[original_type],
            ):
                # Two args with same type but different values
                return True
    return False


def _different_parameters(original, overridden, dummy_parameter_regex):
    """Determine if the two methods have different parameters

    They are considered to have different parameters if:

       * they have different positional parameters, including different names

       * one of the methods is having variadics, while the other is not

       * they have different keyword only parameters.

    """
    original_parameters = _positional_parameters(original)
    overridden_parameters = _positional_parameters(overridden)

    different_positional = _has_different_parameters(
        original_parameters, overridden_parameters, dummy_parameter_regex
    )
    different_kwonly = _has_different_parameters(
        original.args.kwonlyargs, overridden.args.kwonlyargs, dummy_parameter_regex
    )
    if original.name in PYMETHODS:
        # Ignore the difference for special methods. If the parameter
        # numbers are different, then that is going to be caught by
        # unexpected-special-method-signature.
        # If the names are different, it doesn't matter, since they can't
        # be used as keyword arguments anyway.
        different_positional = different_kwonly = False

    # Both or none should have extra variadics, otherwise the method
    # loses or gains capabilities that are not reflected into the parent method,
    # leading to potential inconsistencies in the code.
    different_kwarg = (
        sum(1 for param in (original.args.kwarg, overridden.args.kwarg) if not param)
        == 1
    )
    different_vararg = (
        sum(1 for param in (original.args.vararg, overridden.args.vararg) if not param)
        == 1
    )

    return any(
        (different_positional, different_kwarg, different_vararg, different_kwonly)
    )


def _safe_infer_call_result(node, caller, context=None):
    """
    Safely infer the return value of a function.

    Returns None if inference failed or if there is some ambiguity (more than
    one node has been inferred). Otherwise returns infered value.
    """
    try:
        inferit = node.infer_call_result(caller, context=context)
        value = next(inferit)
    except astroid.InferenceError:
        return None  # inference failed
    except StopIteration:
        return None  # no values infered
    try:
        next(inferit)
        return None  # there is ambiguity on the inferred node
    except astroid.InferenceError:
        return None  # there is some kind of ambiguity
    except StopIteration:
        return value

Safely infer the return value of a function .


def set_accessed(self, node):
        """Set the given node as accessed."""

        frame = node_frame_class(node)
        if frame is None:
            # The node does not live in a class.
            return
        self._scopes[frame][node.attrname].append(node)

def
set_accessed
(
self
,
node
)
:
frame
=
node_frame_class
(
node
)
if
frame
is
:
# The node does not live in a class.
return
self
.
_scopes
[
frame
]
[
node
.
attrname
]
.
append
(
node
)


def visit_classdef(self, node):
        """init visit variable _accessed
        """
        self._check_bases_classes(node)
        # if not an exception or a metaclass
        if node.type == "class" and has_known_bases(node):
            try:
                node.local_attr("__init__")
            except astroid.NotFoundError:
                self.add_message("no-init", args=node, node=node)
        self._check_slots(node)
        self._check_proper_bases(node)
        self._check_consistent_mro(node)

def
visit_classdef
(
self
,
node
)
:
self
.
_check_bases_classes
(
node
)
# if not an exception or a metaclass
if
node
.
type
==
"class"
and
has_known_bases
(
node
)
:
try
:
node
.
local_attr
(
"__init__"
)
except
astroid
.
NotFoundError
:
self
.
add_message
(
"no-init"
,
args
=
node
,
node
=
node
)
self
.
_check_slots
(
node
)
self
.
_check_proper_bases
(
node
)
self
.
_check_consistent_mro
(
node
)


def _check_consistent_mro(self, node):
        """Detect that a class has a consistent mro or duplicate bases."""
        try:
            node.mro()
        except InconsistentMroError:
            self.add_message("inconsistent-mro", args=node.name, node=node)
        except DuplicateBasesError:
            self.add_message("duplicate-bases", args=node.name, node=node)
        except NotImplementedError:
            # Old style class, there's no mro so don't do anything.
            pass

Detect that a class has a consistent mro or duplicate bases .


def _check_proper_bases(self, node):
        """
        Detect that a class inherits something which is not
        a class or a type.
        """
        for base in node.bases:
            ancestor = safe_infer(base)
            if ancestor in (astroid.Uninferable, None):
                continue
            if isinstance(ancestor, astroid.Instance) and ancestor.is_subtype_of(
                "%s.type" % (BUILTINS,)
            ):
                continue

            if not isinstance(ancestor, astroid.ClassDef) or _is_invalid_base_class(
                ancestor
            ):
                self.add_message("inherit-non-class", args=base.as_string(), node=node)

            if ancestor.name == object.__name__:
                self.add_message(
                    "useless-object-inheritance", args=node.name, node=node
                )

def _check_proper_bases ( self , node ) : for base in node . bases : ancestor = safe_infer ( base ) if ancestor in ( astroid . Uninferable , None ) : continue if isinstance ( ancestor , astroid . Instance ) and ancestor . is_subtype_of ( "%s.type" % ( BUILTINS , ) ) : continue if not isinstance ( ancestor , astroid . ClassDef ) or _is_invalid_base_class ( ancestor ) : self . add_message ( "inherit-non-class" , args = base . as_string ( ) , node = node ) if ancestor . name == object . __name__ : self . add_message ( "useless-object-inheritance" , args = node . name , node = node )

Detect that a class inherits something which is not a class or a type .


def visit_functiondef(self, node):
        """check method arguments, overriding"""
        # ignore actual functions
        if not node.is_method():
            return

        self._check_useless_super_delegation(node)

        klass = node.parent.frame()
        self._meth_could_be_func = True
        # check first argument is self if this is actually a method
        self._check_first_arg_for_type(node, klass.type == "metaclass")
        if node.name == "__init__":
            self._check_init(node)
            return
        # check signature if the method overloads inherited method
        for overridden in klass.local_attr_ancestors(node.name):
            # get astroid for the searched method
            try:
                meth_node = overridden[node.name]
            except KeyError:
                # we have found the method but it's not in the local
                # dictionary.
                # This may happen with astroid build from living objects
                continue
            if not isinstance(meth_node, astroid.FunctionDef):
                continue
            self._check_signature(node, meth_node, "overridden", klass)
            break
        if node.decorators:
            for decorator in node.decorators.nodes:
                if isinstance(decorator, astroid.Attribute) and decorator.attrname in (
                    "getter",
                    "setter",
                    "deleter",
                ):
                    # attribute affectation will call this method, not hiding it
                    return
                if isinstance(decorator, astroid.Name):
                    if decorator.name == "property":
                        # attribute affectation will either call a setter or raise
                        # an attribute error, anyway not hiding the function
                        return

                # Infer the decorator and see if it returns something useful
                inferred = safe_infer(decorator)
                if not inferred:
                    return
                if isinstance(inferred, astroid.FunctionDef):
                    # Okay, it's a decorator, let's see what it can infer.
                    try:
                        inferred = next(inferred.infer_call_result(inferred))
                    except astroid.InferenceError:
                        return
                try:
                    if (
                        isinstance(inferred, (astroid.Instance, astroid.ClassDef))
                        and inferred.getattr("__get__")
                        and inferred.getattr("__set__")
                    ):
                        return
                except astroid.AttributeInferenceError:
                    pass

        # check if the method is hidden by an attribute
        try:
            overridden = klass.instance_attr(node.name)[0]  # XXX
            overridden_frame = overridden.frame()
            if (
                isinstance(overridden_frame, astroid.FunctionDef)
                and overridden_frame.type == "method"
            ):
                overridden_frame = overridden_frame.parent.frame()
            if isinstance(overridden_frame, astroid.ClassDef) and klass.is_subtype_of(
                overridden_frame.qname()
            ):
                args = (overridden.root().name, overridden.fromlineno)
                self.add_message("method-hidden", args=args, node=node)
        except astroid.NotFoundError:
            pass


def _check_useless_super_delegation(self, function):
        """Check if the given function node is an useless method override

        We consider it *useless* if it uses the super() builtin, but having
        nothing additional whatsoever than not implementing the method at all.
        If the method uses super() to delegate an operation to the rest of the MRO,
        and if the method called is the same as the current one, the arguments
        passed to super() are the same as the parameters that were passed to
        this method, then the method could be removed altogether, by letting
        other implementation to take precedence.
        """

        if (
            not function.is_method()
            # With decorators is a change of use
            or function.decorators
        ):
            return

        body = function.body
        if len(body) != 1:
            # Multiple statements, which means this overridden method
            # could do multiple things we are not aware of.
            return

        statement = body[0]
        if not isinstance(statement, (astroid.Expr, astroid.Return)):
            # Doing something else than what we are interested into.
            return

        call = statement.value
        if (
            not isinstance(call, astroid.Call)
            # Not a super() attribute access.
            or not isinstance(call.func, astroid.Attribute)
        ):
            return

        # Should be a super call.
        try:
            super_call = next(call.func.expr.infer())
        except astroid.InferenceError:
            return
        else:
            if not isinstance(super_call, objects.Super):
                return

        # The name should be the same.
        if call.func.attrname != function.name:
            return

        # Should be a super call with the MRO pointer being the
        # current class and the type being the current instance.
        current_scope = function.parent.scope()
        if (
            super_call.mro_pointer != current_scope
            or not isinstance(super_call.type, astroid.Instance)
            or super_call.type.name != current_scope.name
        ):
            return

        #  Check values of default args
        klass = function.parent.frame()
        meth_node = None
        for overridden in klass.local_attr_ancestors(function.name):
            # get astroid for the searched method
            try:
                meth_node = overridden[function.name]
            except KeyError:
                # we have found the method but it's not in the local
                # dictionary.
                # This may happen with astroid build from living objects
                continue
            if (
                not isinstance(meth_node, astroid.FunctionDef)
                # If the method have an ancestor which is not a
                # function then it is legitimate to redefine it
                or _has_different_parameters_default_value(
                    meth_node.args, function.args
                )
            ):
                return
            break

        # Detect if the parameters are the same as the call's arguments.
        params = _signature_from_arguments(function.args)
        args = _signature_from_call(call)

        if meth_node is not None:

            def form_annotations(annotations):
                return [
                    annotation.as_string() for annotation in filter(None, annotations)
                ]

            called_annotations = form_annotations(function.args.annotations)
            overridden_annotations = form_annotations(meth_node.args.annotations)
            if called_annotations and overridden_annotations:
                if called_annotations != overridden_annotations:
                    return

        if _definition_equivalent_to_call(params, args):
            self.add_message(
                "useless-super-delegation", node=function, args=(function.name,)
            )


def leave_functiondef(self, node):
        """on method node, check if this method couldn't be a function

        ignore class, static and abstract methods, initializer,
        methods overridden from a parent class.
        """
        if node.is_method():
            if node.args.args is not None:
                self._first_attrs.pop()
            if not self.linter.is_message_enabled("no-self-use"):
                return
            class_node = node.parent.frame()
            if (
                self._meth_could_be_func
                and node.type == "method"
                and node.name not in PYMETHODS
                and not (
                    node.is_abstract()
                    or overrides_a_method(class_node, node.name)
                    or decorated_with_property(node)
                    or _has_bare_super_call(node)
                )
            ):
                self.add_message("no-self-use", node=node)

def leave_functiondef ( self , node ) : if node . is_method ( ) : if node . args . args is not None : self . _first_attrs . pop ( ) if not self . linter . is_message_enabled ( "no-self-use" ) : return class_node = node . parent . frame ( ) if ( self . _meth_could_be_func and node . type == "method" and node . name not in PYMETHODS and not ( node . is_abstract ( ) or overrides_a_method ( class_node , node . name ) or decorated_with_property ( node ) or _has_bare_super_call ( node ) ) ) : self . add_message ( "no-self-use" , node = node )

on method node check if this method couldn t be a function


def _check_in_slots(self, node):
        """ Check that the given AssignAttr node
        is defined in the class slots.
        """
        inferred = safe_infer(node.expr)
        if not isinstance(inferred, astroid.Instance):
            return

        klass = inferred._proxied
        if not has_known_bases(klass):
            return
        if "__slots__" not in klass.locals or not klass.newstyle:
            return

        slots = klass.slots()
        if slots is None:
            return
        # If any ancestor doesn't use slots, the slots
        # defined for this class are superfluous.
        if any(
            "__slots__" not in ancestor.locals and ancestor.name != "object"
            for ancestor in klass.ancestors()
        ):
            return

        if not any(slot.value == node.attrname for slot in slots):
            # If we have a '__dict__' in slots, then
            # assigning any name is valid.
            if not any(slot.value == "__dict__" for slot in slots):
                if _is_attribute_property(node.attrname, klass):
                    # Properties circumvent the slots mechanism,
                    # so we should not emit a warning for them.
                    return
                if node.attrname in klass.locals and _has_data_descriptor(
                    klass, node.attrname
                ):
                    # Descriptors circumvent the slots mechanism as well.
                    return
                if node.attrname == "__class__" and _has_same_layout_slots(
                    slots, node.parent.value
                ):
                    return
                self.add_message("assigning-non-slot", args=(node.attrname,), node=node)

Check that the given AssignAttr node is defined in the class slots .


def visit_name(self, node):
        """check if the name handle an access to a class member
        if so, register it
        """
        if self._first_attrs and (
            node.name == self._first_attrs[-1] or not self._first_attrs[-1]
        ):
            self._meth_could_be_func = False

def visit_name ( self , node ) : if self . _first_attrs and ( node . name == self . _first_attrs [ - 1 ] or not self . _first_attrs [ - 1 ] ) : self . _meth_could_be_func = False

check if the name handle an access to a class member if so register it


def _check_accessed_members(self, node, accessed):
        """check that accessed members are defined"""
        # XXX refactor, probably much simpler now that E0201 is in type checker
        excs = ("AttributeError", "Exception", "BaseException")
        for attr, nodes in accessed.items():
            try:
                # is it a class attribute ?
                node.local_attr(attr)
                # yes, stop here
                continue
            except astroid.NotFoundError:
                pass
            # is it an instance attribute of a parent class ?
            try:
                next(node.instance_attr_ancestors(attr))
                # yes, stop here
                continue
            except StopIteration:
                pass
            # is it an instance attribute ?
            try:
                defstmts = node.instance_attr(attr)
            except astroid.NotFoundError:
                pass
            else:
                # filter out augment assignment nodes
                defstmts = [stmt for stmt in defstmts if stmt not in nodes]
                if not defstmts:
                    # only augment assignment for this node, no-member should be
                    # triggered by the typecheck checker
                    continue
                # filter defstmts to only pick the first one when there are
                # several assignments in the same scope
                scope = defstmts[0].scope()
                defstmts = [
                    stmt
                    for i, stmt in enumerate(defstmts)
                    if i == 0 or stmt.scope() is not scope
                ]
                # if there are still more than one, don't attempt to be smarter
                # than we can be
                if len(defstmts) == 1:
                    defstmt = defstmts[0]
                    # check that if the node is accessed in the same method as
                    # it's defined, it's accessed after the initial assignment
                    frame = defstmt.frame()
                    lno = defstmt.fromlineno
                    for _node in nodes:
                        if (
                            _node.frame() is frame
                            and _node.fromlineno < lno
                            and not astroid.are_exclusive(
                                _node.statement(), defstmt, excs
                            )
                        ):
                            self.add_message(
                                "access-member-before-definition",
                                node=_node,
                                args=(attr, lno),
                            )


def _check_bases_classes(self, node):
        """check that the given class node implements abstract methods from
        base classes
        """

        def is_abstract(method):
            return method.is_abstract(pass_is_abstract=False)

        # check if this class abstract
        if class_is_abstract(node):
            return

        methods = sorted(
            unimplemented_abstract_methods(node, is_abstract).items(),
            key=lambda item: item[0],
        )
        for name, method in methods:
            owner = method.parent.frame()
            if owner is node:
                continue
            # owner is not this class, it must be a parent class
            # check that the ancestor's method is not abstract
            if name in node.locals:
                # it is redefined as an attribute or with a descriptor
                continue
            self.add_message("abstract-method", node=node, args=(name, owner.name))


def _check_signature(self, method1, refmethod, class_type, cls):
        """check that the signature of the two given methods match
        """
        if not (
            isinstance(method1, astroid.FunctionDef)
            and isinstance(refmethod, astroid.FunctionDef)
        ):
            self.add_message(
                "method-check-failed", args=(method1, refmethod), node=method1
            )
            return

        instance = cls.instantiate_class()
        method1 = function_to_method(method1, instance)
        refmethod = function_to_method(refmethod, instance)

        # Don't care about functions with unknown argument (builtins).
        if method1.args.args is None or refmethod.args.args is None:
            return

        # Ignore private to class methods.
        if is_attr_private(method1.name):
            return
        # Ignore setters, they have an implicit extra argument,
        # which shouldn't be taken in consideration.
        if method1.decorators:
            for decorator in method1.decorators.nodes:
                if (
                    isinstance(decorator, astroid.Attribute)
                    and decorator.attrname == "setter"
                ):
                    return

        if _different_parameters(
            refmethod, method1, dummy_parameter_regex=self._dummy_rgx
        ):
            self.add_message(
                "arguments-differ", args=(class_type, method1.name), node=method1
            )
        elif len(method1.args.defaults) < len(refmethod.args.defaults):
            self.add_message(
                "signature-differs", args=(class_type, method1.name), node=method1
            )


def _is_mandatory_method_param(self, node):
        """Check if astroid.Name corresponds to first attribute variable name

        Name is `self` for method, `cls` for classmethod and `mcs` for metaclass.
        """
        return (
            self._first_attrs
            and isinstance(node, astroid.Name)
            and node.name == self._first_attrs[-1]
        )

def _is_mandatory_method_param ( self , node ) : return ( self . _first_attrs and isinstance ( node , astroid . Name ) and node . name == self . _first_attrs [ - 1 ] )

Check if astroid . Name corresponds to first attribute variable name


def _is_raising(body: typing.List) -> bool:
    """Return true if the given statement node raise an exception"""
    for node in body:
        if isinstance(node, astroid.Raise):
            return True
    return False

def _is_raising ( body : typing . List ) -> bool : for node in body : if isinstance ( node , astroid . Raise ) : return True return False


def _check_bad_exception_context(self, node):
        """Verify that the exception context is properly set.

        An exception context can be only `None` or an exception.
        """
        cause = utils.safe_infer(node.cause)
        if cause in (astroid.Uninferable, None):
            return

        if isinstance(cause, astroid.Const):
            if cause.value is not None:
                self.add_message("bad-exception-context", node=node)
        elif not isinstance(cause, astroid.ClassDef) and not utils.inherit_from_std_ex(
            cause
        ):
            self.add_message("bad-exception-context", node=node)

def _check_bad_exception_context ( self , node ) : cause = utils . safe_infer ( node . cause ) if cause in ( astroid . Uninferable , None ) : return if isinstance ( cause , astroid . Const ) : if cause . value is not None : self . add_message ( "bad-exception-context" , node = node ) elif not isinstance ( cause , astroid . ClassDef ) and not utils . inherit_from_std_ex ( cause ) : self . add_message ( "bad-exception-context" , node = node )

Verify that the exception context is properly set .


def visit_functiondef(self, node):
        """check use of super"""
        # ignore actual functions or method within a new style class
        if not node.is_method():
            return
        klass = node.parent.frame()
        for stmt in node.nodes_of_class(astroid.Call):
            if node_frame_class(stmt) != node_frame_class(node):
                # Don't look down in other scopes.
                continue

            expr = stmt.func
            if not isinstance(expr, astroid.Attribute):
                continue

            call = expr.expr
            # skip the test if using super
            if not (
                isinstance(call, astroid.Call)
                and isinstance(call.func, astroid.Name)
                and call.func.name == "super"
            ):
                continue

            if not klass.newstyle and has_known_bases(klass):
                # super should not be used on an old style class
                continue
            else:
                # super first arg should be the class
                if not call.args:
                    if sys.version_info[0] == 3:
                        # unless Python 3
                        continue
                    else:
                        self.add_message("missing-super-argument", node=call)
                        continue

                # calling super(type(self), self) can lead to recursion loop
                # in derived classes
                arg0 = call.args[0]
                if (
                    isinstance(arg0, astroid.Call)
                    and isinstance(arg0.func, astroid.Name)
                    and arg0.func.name == "type"
                ):
                    self.add_message("bad-super-call", node=call, args=("type",))
                    continue

                # calling super(self.__class__, self) can lead to recursion loop
                # in derived classes
                if (
                    len(call.args) >= 2
                    and isinstance(call.args[1], astroid.Name)
                    and call.args[1].name == "self"
                    and isinstance(arg0, astroid.Attribute)
                    and arg0.attrname == "__class__"
                ):
                    self.add_message(
                        "bad-super-call", node=call, args=("self.__class__",)
                    )
                    continue

                try:
                    supcls = call.args and next(call.args[0].infer(), None)
                except astroid.InferenceError:
                    continue

                if klass is not supcls:
                    name = None
                    # if supcls is not Uninferable, then supcls was infered
                    # and use its name. Otherwise, try to look
                    # for call.args[0].name
                    if supcls:
                        name = supcls.name
                    elif call.args and hasattr(call.args[0], "name"):
                        name = call.args[0].name
                    if name:
                        self.add_message("bad-super-call", node=call, args=(name,))


def display_reports(self, layout):
        """display results encapsulated in the layout tree"""
        self.section = 0
        if hasattr(layout, "report_id"):
            layout.children[0].children[0].data += " (%s)" % layout.report_id
        self._display(layout)

def
display_reports
(
self
,
layout
)
:
self
.
section
=
0
if
hasattr
(
layout
,
"report_id"
)
:
layout
.
children
[
0
]
.
children
[
0
]
.
data
+=
" (%s)"
%
layout
.
report_id
self
.
_display
(
layout
)


def _is_typing_namedtuple(node: astroid.ClassDef) -> bool:
    """Check if a class node is a typing.NamedTuple class"""
    for base in node.ancestors():
        if base.qname() == TYPING_NAMEDTUPLE:
            return True
    return False

def _is_typing_namedtuple ( node : astroid . ClassDef ) -> bool : for base in node . ancestors ( ) : if base . qname ( ) == TYPING_NAMEDTUPLE : return True return False

Check if a class node is a typing . NamedTuple class


def _is_enum_class(node: astroid.ClassDef) -> bool:
    """Check if a class definition defines an Enum class.

    :param node: The class node to check.
    :type node: astroid.ClassDef

    :returns: True if the given node represents an Enum class. False otherwise.
    :rtype: bool
    """
    for base in node.bases:
        try:
            inferred_bases = base.inferred()
        except astroid.InferenceError:
            continue

        for ancestor in inferred_bases:
            if not isinstance(ancestor, astroid.ClassDef):
                continue

            if ancestor.name == "Enum" and ancestor.root().name == "enum":
                return True

    return False

def _is_enum_class ( node : astroid . ClassDef ) -> bool : for base in node . bases : try : inferred_bases = base . inferred ( ) except astroid . InferenceError : continue for ancestor in inferred_bases : if not isinstance ( ancestor , astroid . ClassDef ) : continue if ancestor . name == "Enum" and ancestor . root ( ) . name == "enum" : return True return False

Check if a class definition defines an Enum class .


def _is_dataclass(node: astroid.ClassDef) -> bool:
    """Check if a class definition defines a Python 3.7+ dataclass

    :param node: The class node to check.
    :type node: astroid.ClassDef

    :returns: True if the given node represents a dataclass class. False otherwise.
    :rtype: bool
    """
    if not node.decorators:
        return False

    root_locals = node.root().locals
    for decorator in node.decorators.nodes:
        if isinstance(decorator, astroid.Call):
            decorator = decorator.func
        if not isinstance(decorator, (astroid.Name, astroid.Attribute)):
            continue
        if isinstance(decorator, astroid.Name):
            name = decorator.name
        else:
            name = decorator.attrname
        if name == DATACLASS_DECORATOR and DATACLASS_DECORATOR in root_locals:
            return True
    return False

def _is_dataclass ( node : astroid . ClassDef ) -> bool : if not node . decorators : return False root_locals = node . root ( ) . locals for decorator in node . decorators . nodes : if isinstance ( decorator , astroid . Call ) : decorator = decorator . func if not isinstance ( decorator , ( astroid . Name , astroid . Attribute ) ) : continue if isinstance ( decorator , astroid . Name ) : name = decorator . name else : name = decorator . attrname if name == DATACLASS_DECORATOR and DATACLASS_DECORATOR in root_locals : return True return False

Check if a class definition defines a Python 3 . 7 + dataclass


def open(self):
        """initialize visit variables"""
        self.stats = self.linter.add_stats()
        self._returns = []
        self._branches = defaultdict(int)
        self._stmts = []

def open ( self ) : self . stats = self . linter . add_stats ( ) self . _returns = [ ] self . _branches = defaultdict ( int ) self . _stmts = [ ]


def visit_classdef(self, node):
        """check size of inheritance hierarchy and number of instance attributes
        """
        nb_parents = len(list(node.ancestors()))
        if nb_parents > self.config.max_parents:
            self.add_message(
                "too-many-ancestors",
                node=node,
                args=(nb_parents, self.config.max_parents),
            )

        if len(node.instance_attrs) > self.config.max_attributes:
            self.add_message(
                "too-many-instance-attributes",
                node=node,
                args=(len(node.instance_attrs), self.config.max_attributes),
            )

def visit_classdef ( self , node ) : nb_parents = len ( list ( node . ancestors ( ) ) ) if nb_parents > self . config . max_parents : self . add_message ( "too-many-ancestors" , node = node , args = ( nb_parents , self . config . max_parents ) , ) if len ( node . instance_attrs ) > self . config . max_attributes : self . add_message ( "too-many-instance-attributes" , node = node , args = ( len ( node . instance_attrs ) , self . config . max_attributes ) , )


def leave_classdef(self, node):
        """check number of public methods"""
        my_methods = sum(
            1 for method in node.mymethods() if not method.name.startswith("_")
        )

        # Does the class contain less than n public methods ?
        # This checks only the methods defined in the current class,
        # since the user might not have control over the classes
        # from the ancestors. It avoids some false positives
        # for classes such as unittest.TestCase, which provides
        # a lot of assert methods. It doesn't make sense to warn
        # when the user subclasses TestCase to add his own tests.
        if my_methods > self.config.max_public_methods:
            self.add_message(
                "too-many-public-methods",
                node=node,
                args=(my_methods, self.config.max_public_methods),
            )

        # Stop here for exception, metaclass, interface classes and other
        # classes for which we don't need to count the methods.
        if (
            node.type != "class"
            or _is_enum_class(node)
            or _is_dataclass(node)
            or _is_typing_namedtuple(node)
        ):
            return

        # Does the class contain more than n public methods ?
        # This checks all the methods defined by ancestors and
        # by the current class.
        all_methods = _count_methods_in_class(node)
        if all_methods < self.config.min_public_methods:
            self.add_message(
                "too-few-public-methods",
                node=node,
                args=(all_methods, self.config.min_public_methods),
            )


def visit_if(self, node):
        """increments the branches counter and checks boolean expressions"""
        self._check_boolean_expressions(node)
        branches = 1
        # don't double count If nodes coming from some 'elif'
        if node.orelse and (len(node.orelse) > 1 or not isinstance(node.orelse[0], If)):
            branches += 1
        self._inc_branch(node, branches)
        self._inc_all_stmts(branches)


def _check_boolean_expressions(self, node):
        """Go through "if" node `node` and counts its boolean expressions

        if the "if" node test is a BoolOp node
        """
        condition = node.test
        if not isinstance(condition, BoolOp):
            return
        nb_bool_expr = _count_boolean_expressions(condition)
        if nb_bool_expr > self.config.max_bool_expr:
            self.add_message(
                "too-many-boolean-expressions",
                node=condition,
                args=(nb_bool_expr, self.config.max_bool_expr),
            )

def _check_boolean_expressions ( self , node ) : condition = node . test if not isinstance ( condition , BoolOp ) : return nb_bool_expr = _count_boolean_expressions ( condition ) if nb_bool_expr > self . config . max_bool_expr : self . add_message ( "too-many-boolean-expressions" , node = condition , args = ( nb_bool_expr , self . config . max_bool_expr ) , )

Go through if node node and counts its boolean expressions


def _check_docstring(self, node):
        """check the node has any spelling errors"""
        docstring = node.doc
        if not docstring:
            return

        start_line = node.lineno + 1

        # Go through lines of docstring
        for idx, line in enumerate(docstring.splitlines()):
            self._check_spelling("wrong-spelling-in-docstring", line, start_line + idx)

def
_check_docstring
(
self
,
node
)
:
docstring
=
node
.
doc
if
not
docstring
:
return
start_line
=
node
.
lineno
+
1
# Go through lines of docstring
for
idx
,
line
in
enumerate
(
docstring
.
splitlines
(
)
)
:
self
.
_check_spelling
(
"wrong-spelling-in-docstring"
,
line
,
start_line
+
idx
)


def format(self, template):
        """Format the message according to the given template.

        The template format is the one of the format method :
        cf. http://docs.python.org/2/library/string.html#formatstrings
        """
        # For some reason, _asdict on derived namedtuples does not work with
        # Python 3.4. Needs some investigation.
        return template.format(**dict(zip(self._fields, self)))

Format the message according to the given template .


def _is_trailing_comma(tokens, index):
    """Check if the given token is a trailing comma

    :param tokens: Sequence of modules tokens
    :type tokens: list[tokenize.TokenInfo]
    :param int index: Index of token under check in tokens
    :returns: True if the token is a comma which trails an expression
    :rtype: bool
    """
    token = tokens[index]
    if token.exact_type != tokenize.COMMA:
        return False
    # Must have remaining tokens on the same line such as NEWLINE
    left_tokens = itertools.islice(tokens, index + 1, None)
    same_line_remaining_tokens = list(
        itertools.takewhile(
            lambda other_token, _token=token: other_token.start[0] == _token.start[0],
            left_tokens,
        )
    )
    # Note: If the newline is tokenize.NEWLINE and not tokenize.NL
    # then the newline denotes the end of expression
    is_last_element = all(
        other_token.type in (tokenize.NEWLINE, tokenize.COMMENT)
        for other_token in same_line_remaining_tokens
    )
    if not same_line_remaining_tokens or not is_last_element:
        return False

    def get_curline_index_start():
        """Get the index denoting the start of the current line"""
        for subindex, token in enumerate(reversed(tokens[:index])):
            # See Lib/tokenize.py and Lib/token.py in cpython for more info
            if token.type in (tokenize.NEWLINE, tokenize.NL):
                return index - subindex
        return 0

    curline_start = get_curline_index_start()
    expected_tokens = {"return", "yield"}
    for prevtoken in tokens[curline_start:index]:
        if "=" in prevtoken.string or prevtoken.string in expected_tokens:
            return True
    return False


def _is_actual_elif(self, node):
        """Check if the given node is an actual elif

        This is a problem we're having with the builtin ast module,
        which splits `elif` branches into a separate if statement.
        Unfortunately we need to know the exact type in certain
        cases.
        """
        if isinstance(node.parent, astroid.If):
            orelse = node.parent.orelse
            # current if node must directly follow an "else"
            if orelse and orelse == [node]:
                if (node.lineno, node.col_offset) in self._elifs:
                    return True
        return False


def _check_simplifiable_if(self, node):
        """Check if the given if node can be simplified.

        The if statement can be reduced to a boolean expression
        in some cases. For instance, if there are two branches
        and both of them return a boolean value that depends on
        the result of the statement's test, then this can be reduced
        to `bool(test)` without losing any functionality.
        """

        if self._is_actual_elif(node):
            # Not interested in if statements with multiple branches.
            return
        if len(node.orelse) != 1 or len(node.body) != 1:
            return

        # Check if both branches can be reduced.
        first_branch = node.body[0]
        else_branch = node.orelse[0]
        if isinstance(first_branch, astroid.Return):
            if not isinstance(else_branch, astroid.Return):
                return
            first_branch_is_bool = self._is_bool_const(first_branch)
            else_branch_is_bool = self._is_bool_const(else_branch)
            reduced_to = "'return bool(test)'"
        elif isinstance(first_branch, astroid.Assign):
            if not isinstance(else_branch, astroid.Assign):
                return

            # Check if we assign to the same value
            first_branch_targets = [
                target.name
                for target in first_branch.targets
                if isinstance(target, astroid.AssignName)
            ]
            else_branch_targets = [
                target.name
                for target in else_branch.targets
                if isinstance(target, astroid.AssignName)
            ]
            if not first_branch_targets or not else_branch_targets:
                return
            if sorted(first_branch_targets) != sorted(else_branch_targets):
                return

            first_branch_is_bool = self._is_bool_const(first_branch)
            else_branch_is_bool = self._is_bool_const(else_branch)
            reduced_to = "'var = bool(test)'"
        else:
            return

        if not first_branch_is_bool or not else_branch_is_bool:
            return
        if not first_branch.value.value:
            # This is a case that can't be easily simplified and
            # if it can be simplified, it will usually result in a
            # code that's harder to understand and comprehend.
            # Let's take for instance `arg and arg <= 3`. This could theoretically be
            # reduced to `not arg or arg > 3`, but the net result is that now the
            # condition is harder to understand, because it requires understanding of
            # an extra clause:
            #   * first, there is the negation of truthness with `not arg`
            #   * the second clause is `arg > 3`, which occurs when arg has a
            #     a truth value, but it implies that `arg > 3` is equivalent
            #     with `arg and arg > 3`, which means that the user must
            #     think about this assumption when evaluating `arg > 3`.
            #     The original form is easier to grasp.
            return

        self.add_message("simplifiable-if-statement", node=node, args=(reduced_to,))

#     The original form is easier to grasp.

Check if the given if node can be simplified .


def _check_stop_iteration_inside_generator(self, node):
        """Check if an exception of type StopIteration is raised inside a generator"""
        frame = node.frame()
        if not isinstance(frame, astroid.FunctionDef) or not frame.is_generator():
            return
        if utils.node_ignores_exception(node, StopIteration):
            return
        if not node.exc:
            return
        exc = utils.safe_infer(node.exc)
        if exc is None or exc is astroid.Uninferable:
            return
        if self._check_exception_inherit_from_stopiteration(exc):
            self.add_message("stop-iteration-return", node=node)


def _check_exception_inherit_from_stopiteration(exc):
        """Return True if the exception node in argument inherit from StopIteration"""
        stopiteration_qname = "{}.StopIteration".format(utils.EXCEPTIONS_MODULE)
        return any(_class.qname() == stopiteration_qname for _class in exc.mro())


def _check_raising_stopiteration_in_generator_next_call(self, node):
        """Check if a StopIteration exception is raised by the call to next function

        If the next value has a default value, then do not add message.

        :param node: Check to see if this Call node is a next function
        :type node: :class:`astroid.node_classes.Call`
        """

        def _looks_like_infinite_iterator(param):
            inferred = utils.safe_infer(param)
            if inferred:
                return inferred.qname() in KNOWN_INFINITE_ITERATORS
            return False

        if isinstance(node.func, astroid.Attribute):
            # A next() method, which is now what we want.
            return

        inferred = utils.safe_infer(node.func)
        if getattr(inferred, "name", "") == "next":
            frame = node.frame()
            # The next builtin can only have up to two
            # positional arguments and no keyword arguments
            has_sentinel_value = len(node.args) > 1
            if (
                isinstance(frame, astroid.FunctionDef)
                and frame.is_generator()
                and not has_sentinel_value
                and not utils.node_ignores_exception(node, StopIteration)
                and not _looks_like_infinite_iterator(node.args[0])
            ):
                self.add_message("stop-iteration-return", node=node)


def _check_nested_blocks(self, node):
        """Update and check the number of nested blocks
        """
        # only check block levels inside functions or methods
        if not isinstance(node.scope(), astroid.FunctionDef):
            return
        # messages are triggered on leaving the nested block. Here we save the
        # stack in case the current node isn't nested in the previous one
        nested_blocks = self._nested_blocks[:]
        if node.parent == node.scope():
            self._nested_blocks = [node]
        else:
            # go through ancestors from the most nested to the less
            for ancestor_node in reversed(self._nested_blocks):
                if ancestor_node == node.parent:
                    break
                self._nested_blocks.pop()
            # if the node is an elif, this should not be another nesting level
            if isinstance(node, astroid.If) and self._is_actual_elif(node):
                if self._nested_blocks:
                    self._nested_blocks.pop()
            self._nested_blocks.append(node)

        # send message only once per group of nested blocks
        if len(nested_blocks) > len(self._nested_blocks):
            self._emit_nested_blocks_message_if_needed(nested_blocks)


def _duplicated_isinstance_types(node):
        """Get the duplicated types from the underlying isinstance calls.

        :param astroid.BoolOp node: Node which should contain a bunch of isinstance calls.
        :returns: Dictionary of the comparison objects from the isinstance calls,
                  to duplicate values from consecutive calls.
        :rtype: dict
        """
        duplicated_objects = set()
        all_types = collections.defaultdict(set)

        for call in node.values:
            if not isinstance(call, astroid.Call) or len(call.args) != 2:
                continue

            inferred = utils.safe_infer(call.func)
            if not inferred or not utils.is_builtin_object(inferred):
                continue

            if inferred.name != "isinstance":
                continue

            isinstance_object = call.args[0].as_string()
            isinstance_types = call.args[1]

            if isinstance_object in all_types:
                duplicated_objects.add(isinstance_object)

            if isinstance(isinstance_types, astroid.Tuple):
                elems = [
                    class_type.as_string() for class_type in isinstance_types.itered()
                ]
            else:
                elems = [isinstance_types.as_string()]
            all_types[isinstance_object].update(elems)

        # Remove all keys which not duplicated
        return {
            key: value for key, value in all_types.items() if key in duplicated_objects
        }

def
_duplicated_isinstance_types
(
node
)
:
duplicated_objects
=
set
(
)
all_types
=
collections
.
defaultdict
(
set
)
for
call
in
node
.
values
:
if
not
isinstance
(
call
,
astroid
.
Call
)
or
len
(
call
.
args
)
!=
2
:
continue
inferred
=
utils
.
safe_infer
(
call
.
func
)
if
not
inferred
or
not
utils
.
is_builtin_object
(
inferred
)
:
continue
if
inferred
.
name
!=
"isinstance"
:
continue
isinstance_object
=
call
.
args
[
0
]
.
as_string
(
)
isinstance_types
=
call
.
args
[
1
]
if
isinstance_object
in
all_types
:
duplicated_objects
.
add
(
isinstance_object
)
if
isinstance
(
isinstance_types
,
astroid
.
Tuple
)
:
elems
=
[
class_type
.
as_string
(
)
for
class_type
in
isinstance_types
.
itered
(
)
]
else
:
elems
=
[
isinstance_types
.
as_string
(
)
]
all_types
[
isinstance_object
]
.
update
(
elems
)
# Remove all keys which not duplicated
return
{
key
:
value
for
key
,
value
in
all_types
.
items
(
)
if
key
in
duplicated_objects
}

Get the duplicated types from the underlying isinstance calls .


def _check_consider_merging_isinstance(self, node):
        """Check isinstance calls which can be merged together."""
        if node.op != "or":
            return

        first_args = self._duplicated_isinstance_types(node)
        for duplicated_name, class_names in first_args.items():
            names = sorted(name for name in class_names)
            self.add_message(
                "consider-merging-isinstance",
                node=node,
                args=(duplicated_name, ", ".join(names)),
            )

def
_check_consider_merging_isinstance
(
self
,
node
)
:
if
node
.
op
!=
"or"
:
return
first_args
=
self
.
_duplicated_isinstance_types
(
node
)
for
duplicated_name
,
class_names
in
first_args
.
items
(
)
:
names
=
sorted
(
name
for
name
in
class_names
)
self
.
add_message
(
"consider-merging-isinstance"
,
node
=
node
,
args
=
(
duplicated_name
,
", "
.
join
(
names
)
)
,
)

Check isinstance calls which can be merged together .


def _check_chained_comparison(self, node):
        """Check if there is any chained comparison in the expression.

        Add a refactoring message if a boolOp contains comparison like a < b and b < c,
        which can be chained as a < b < c.

        Care is taken to avoid simplifying a < b < c and b < d.
        """
        if node.op != "and" or len(node.values) < 2:
            return

        def _find_lower_upper_bounds(comparison_node, uses):
            left_operand = comparison_node.left
            for operator, right_operand in comparison_node.ops:
                for operand in (left_operand, right_operand):
                    value = None
                    if isinstance(operand, astroid.Name):
                        value = operand.name
                    elif isinstance(operand, astroid.Const):
                        value = operand.value

                    if value is None:
                        continue

                    if operator in ("<", "<="):
                        if operand is left_operand:
                            uses[value]["lower_bound"].add(comparison_node)
                        elif operand is right_operand:
                            uses[value]["upper_bound"].add(comparison_node)
                    elif operator in (">", ">="):
                        if operand is left_operand:
                            uses[value]["upper_bound"].add(comparison_node)
                        elif operand is right_operand:
                            uses[value]["lower_bound"].add(comparison_node)
                left_operand = right_operand

        uses = collections.defaultdict(
            lambda: {"lower_bound": set(), "upper_bound": set()}
        )
        for comparison_node in node.values:
            if isinstance(comparison_node, astroid.Compare):
                _find_lower_upper_bounds(comparison_node, uses)

        for _, bounds in uses.items():
            num_shared = len(bounds["lower_bound"].intersection(bounds["upper_bound"]))
            num_lower_bounds = len(bounds["lower_bound"])
            num_upper_bounds = len(bounds["upper_bound"])
            if num_shared < num_lower_bounds and num_shared < num_upper_bounds:
                self.add_message("chained-comparison", node=node)
                break

def _check_chained_comparison ( self , node ) : if node . op != "and" or len ( node . values ) < 2 : return def _find_lower_upper_bounds ( comparison_node , uses ) : left_operand = comparison_node . left for operator , right_operand in comparison_node . ops : for operand in ( left_operand , right_operand ) : value = None if isinstance ( operand , astroid . Name ) : value = operand . name elif isinstance ( operand , astroid . Const ) : value = operand . value if value is None : continue if operator in ( "<" , "<=" ) : if operand is left_operand : uses [ value ] [ "lower_bound" ] . add ( comparison_node ) elif operand is right_operand : uses [ value ] [ "upper_bound" ] . add ( comparison_node ) elif operator in ( ">" , ">=" ) : if operand is left_operand : uses [ value ] [ "upper_bound" ] . add ( comparison_node ) elif operand is right_operand : uses [ value ] [ "lower_bound" ] . add ( comparison_node ) left_operand = right_operand uses = collections . defaultdict ( lambda : { "lower_bound" : set ( ) , "upper_bound" : set ( ) } ) for comparison_node in node . values : if isinstance ( comparison_node , astroid . Compare ) : _find_lower_upper_bounds ( comparison_node , uses ) for _ , bounds in uses . items ( ) : num_shared = len ( bounds [ "lower_bound" ] . intersection ( bounds [ "upper_bound" ] ) ) num_lower_bounds = len ( bounds [ "lower_bound" ] ) num_upper_bounds = len ( bounds [ "upper_bound" ] ) if num_shared < num_lower_bounds and num_shared < num_upper_bounds : self . add_message ( "chained-comparison" , node = node ) break

Check if there is any chained comparison in the expression .


def _is_and_or_ternary(node):
        """
        Returns true if node is 'condition and true_value or false_value' form.

        All of: condition, true_value and false_value should not be a complex boolean expression
        """
        return (
            isinstance(node, astroid.BoolOp)
            and node.op == "or"
            and len(node.values) == 2
            and isinstance(node.values[0], astroid.BoolOp)
            and not isinstance(node.values[1], astroid.BoolOp)
            and node.values[0].op == "and"
            and not isinstance(node.values[0].values[1], astroid.BoolOp)
            and len(node.values[0].values) == 2
        )

def _is_and_or_ternary ( node ) : return ( isinstance ( node , astroid . BoolOp ) and node . op == "or" and len ( node . values ) == 2 and isinstance ( node . values [ 0 ] , astroid . BoolOp ) and not isinstance ( node . values [ 1 ] , astroid . BoolOp ) and node . values [ 0 ] . op == "and" and not isinstance ( node . values [ 0 ] . values [ 1 ] , astroid . BoolOp ) and len ( node . values [ 0 ] . values ) == 2 )

Returns true if node is condition and true_value or false_value form .


def _check_consistent_returns(self, node):
        """Check that all return statements inside a function are consistent.

        Return statements are consistent if:
            - all returns are explicit and if there is no implicit return;
            - all returns are empty and if there is, possibly, an implicit return.

        Args:
            node (astroid.FunctionDef): the function holding the return statements.

        """
        # explicit return statements are those with a not None value
        explicit_returns = [
            _node for _node in self._return_nodes[node.name] if _node.value is not None
        ]
        if not explicit_returns:
            return
        if len(explicit_returns) == len(
            self._return_nodes[node.name]
        ) and self._is_node_return_ended(node):
            return
        self.add_message("inconsistent-return-statements", node=node)

Check that all return statements inside a function are consistent .


def _is_node_return_ended(self, node):
        """Check if the node ends with an explicit return statement.

        Args:
            node (astroid.NodeNG): node to be checked.

        Returns:
            bool: True if the node ends with an explicit statement, False otherwise.

        """
        #  Recursion base case
        if isinstance(node, astroid.Return):
            return True
        if isinstance(node, astroid.Call):
            try:
                funcdef_node = node.func.inferred()[0]
                if self._is_function_def_never_returning(funcdef_node):
                    return True
            except astroid.InferenceError:
                pass
        # Avoid the check inside while loop as we don't know
        #  if they will be completed
        if isinstance(node, astroid.While):
            return True
        if isinstance(node, astroid.Raise):
            # a Raise statement doesn't need to end with a return statement
            # but if the exception raised is handled, then the handler has to
            # ends with a return statement
            if not node.exc:
                # Ignore bare raises
                return True
            if not utils.is_node_inside_try_except(node):
                # If the raise statement is not inside a try/except statement
                #  then the exception is raised and cannot be caught. No need
                #  to infer it.
                return True
            exc = utils.safe_infer(node.exc)
            if exc is None or exc is astroid.Uninferable:
                return False
            exc_name = exc.pytype().split(".")[-1]
            handlers = utils.get_exception_handlers(node, exc_name)
            handlers = list(handlers) if handlers is not None else []
            if handlers:
                # among all the handlers handling the exception at least one
                # must end with a return statement
                return any(
                    self._is_node_return_ended(_handler) for _handler in handlers
                )
            # if no handlers handle the exception then it's ok
            return True
        if isinstance(node, astroid.If):
            # if statement is returning if there are exactly two return statements in its
            #  children : one for the body part, the other for the orelse part
            # Do not check if inner function definition are return ended.
            is_orelse_returning = any(
                self._is_node_return_ended(_ore)
                for _ore in node.orelse
                if not isinstance(_ore, astroid.FunctionDef)
            )
            is_if_returning = any(
                self._is_node_return_ended(_ifn)
                for _ifn in node.body
                if not isinstance(_ifn, astroid.FunctionDef)
            )
            return is_if_returning and is_orelse_returning
        #  recurses on the children of the node except for those which are except handler
        # because one cannot be sure that the handler will really be used
        return any(
            self._is_node_return_ended(_child)
            for _child in node.get_children()
            if not isinstance(_child, astroid.ExceptHandler)
        )

Check if the node ends with an explicit return statement .


def visit_for(self, node):
        """Emit a convention whenever range and len are used for indexing."""
        # Verify that we have a `range([start], len(...), [stop])` call and
        # that the object which is iterated is used as a subscript in the
        # body of the for.

        # Is it a proper range call?
        if not isinstance(node.iter, astroid.Call):
            return
        if not self._is_builtin(node.iter.func, "range"):
            return
        if len(node.iter.args) == 2 and not _is_constant_zero(node.iter.args[0]):
            return
        if len(node.iter.args) > 2:
            return

        # Is it a proper len call?
        if not isinstance(node.iter.args[-1], astroid.Call):
            return
        second_func = node.iter.args[-1].func
        if not self._is_builtin(second_func, "len"):
            return
        len_args = node.iter.args[-1].args
        if not len_args or len(len_args) != 1:
            return
        iterating_object = len_args[0]
        if not isinstance(iterating_object, astroid.Name):
            return
        # If we're defining __iter__ on self, enumerate won't work
        scope = node.scope()
        if iterating_object.name == "self" and scope.name == "__iter__":
            return

        # Verify that the body of the for loop uses a subscript
        # with the object that was iterated. This uses some heuristics
        # in order to make sure that the same object is used in the
        # for body.
        for child in node.body:
            for subscript in child.nodes_of_class(astroid.Subscript):
                if not isinstance(subscript.value, astroid.Name):
                    continue
                if not isinstance(subscript.slice, astroid.Index):
                    continue
                if not isinstance(subscript.slice.value, astroid.Name):
                    continue
                if subscript.slice.value.name != node.target.name:
                    continue
                if iterating_object.name != subscript.value.name:
                    continue
                if subscript.value.scope() != node.scope():
                    # Ignore this subscript if it's not in the same
                    # scope. This means that in the body of the for
                    # loop, another scope was created, where the same
                    # name for the iterating object was used.
                    continue
                self.add_message("consider-using-enumerate", node=node)
                return

Emit a convention whenever range and len are used for indexing .


def _check_graphviz_available(output_format):
    """check if we need graphviz for different output format"""
    try:
        subprocess.call(["dot", "-V"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    except OSError:
        print(
            "The output format '%s' is currently not available.\n"
            "Please install 'Graphviz' to have other output formats "
            "than 'dot' or 'vcg'." % output_format
        )
        sys.exit(32)


def run(self, args):
        """checking arguments and run project"""
        if not args:
            print(self.help())
            return 1
        # insert current working directory to the python path to recognize
        # dependencies to local modules even if cwd is not in the PYTHONPATH
        sys.path.insert(0, os.getcwd())
        try:
            project = project_from_files(
                args,
                project_name=self.config.project,
                black_list=self.config.black_list,
            )
            linker = Linker(project, tag=True)
            handler = DiadefsHandler(self.config)
            diadefs = handler.get_diadefs(project, linker)
        finally:
            sys.path.pop(0)

        if self.config.output_format == "vcg":
            writer.VCGWriter(self.config).write(diadefs)
        else:
            writer.DotWriter(self.config).write(diadefs)
        return 0


def write_packages(self, diagram):
        """write a package diagram"""
        # sorted to get predictable (hence testable) results
        for i, obj in enumerate(sorted(diagram.modules(), key=lambda x: x.title)):
            self.printer.emit_node(i, label=self.get_title(obj), shape="box")
            obj.fig_id = i
        # package dependencies
        for rel in diagram.get_relationships("depends"):
            self.printer.emit_edge(
                rel.from_object.fig_id, rel.to_object.fig_id, **self.pkg_edges
            )


def write_classes(self, diagram):
        """write a class diagram"""
        # sorted to get predictable (hence testable) results
        for i, obj in enumerate(sorted(diagram.objects, key=lambda x: x.title)):
            self.printer.emit_node(i, **self.get_values(obj))
            obj.fig_id = i
        # inheritance links
        for rel in diagram.get_relationships("specialization"):
            self.printer.emit_edge(
                rel.from_object.fig_id, rel.to_object.fig_id, **self.inh_edges
            )
        # implementation links
        for rel in diagram.get_relationships("implements"):
            self.printer.emit_edge(
                rel.from_object.fig_id, rel.to_object.fig_id, **self.imp_edges
            )
        # generate associations
        for rel in diagram.get_relationships("association"):
            self.printer.emit_edge(
                rel.from_object.fig_id,
                rel.to_object.fig_id,
                label=rel.name,
                **self.association_edges
            )


def set_printer(self, file_name, basename):
        """initialize DotWriter and add options for layout.
        """
        layout = dict(rankdir="BT")
        self.printer = DotBackend(basename, additional_param=layout)
        self.file_name = file_name

def set_printer ( self , file_name , basename ) : layout = dict ( rankdir = "BT" ) self . printer = DotBackend ( basename , additional_param = layout ) self . file_name = file_name

initialize DotWriter and add options for layout .


def set_printer(self, file_name, basename):
        """initialize VCGWriter for a UML graph"""
        self.graph_file = open(file_name, "w+")
        self.printer = VCGPrinter(self.graph_file)
        self.printer.open_graph(
            title=basename,
            layoutalgorithm="dfs",
            late_edge_labels="yes",
            port_sharing="no",
            manhattan_edges="yes",
        )
        self.printer.emit_node = self.printer.node
        self.printer.emit_edge = self.printer.edge

def set_printer ( self , file_name , basename ) : self . graph_file = open ( file_name , "w+" ) self . printer = VCGPrinter ( self . graph_file ) self . printer . open_graph ( title = basename , layoutalgorithm = "dfs" , late_edge_labels = "yes" , port_sharing = "no" , manhattan_edges = "yes" , ) self . printer . emit_node = self . printer . node self . printer . emit_edge = self . printer . edge


def may_be_emitted(self):
        """return True if message may be emitted using the current interpreter"""
        if self.minversion is not None and self.minversion > sys.version_info:
            return False
        if self.maxversion is not None and self.maxversion <= sys.version_info:
            return False
        return True

def may_be_emitted ( self ) : if self . minversion is not None and self . minversion > sys . version_info : return False if self . maxversion is not None and self . maxversion <= sys . version_info : return False return True


def format_help(self, checkerref=False):
        """return the help string for the given message id"""
        desc = self.descr
        if checkerref:
            desc += " This message belongs to the %s checker." % self.checker.name
        title = self.msg
        if self.symbol:
            msgid = "%s (%s)" % (self.symbol, self.msgid)
        else:
            msgid = self.msgid
        if self.minversion or self.maxversion:
            restr = []
            if self.minversion:
                restr.append("< %s" % ".".join([str(n) for n in self.minversion]))
            if self.maxversion:
                restr.append(">= %s" % ".".join([str(n) for n in self.maxversion]))
            restr = " or ".join(restr)
            if checkerref:
                desc += " It can't be emitted when using Python %s." % restr
            else:
                desc += " This message can't be emitted when using Python %s." % restr
        desc = normalize_text(" ".join(desc.split()), indent="  ")
        if title != "%s":
            title = title.splitlines()[0]

            return ":%s: *%s*\n%s" % (msgid, title.rstrip(" "), desc)
        return ":%s:\n%s" % (msgid, desc)


def _get_env():
    """Extracts the environment PYTHONPATH and appends the current sys.path to
    those."""
    env = dict(os.environ)
    env["PYTHONPATH"] = os.pathsep.join(sys.path)
    return env

def _get_env ( ) : env = dict ( os . environ ) env [ "PYTHONPATH" ] = os . pathsep . join ( sys . path ) return env

Extracts the environment PYTHONPATH and appends the current sys . path to those .


def lint(filename, options=()):
    """Pylint the given file.

    When run from emacs we will be in the directory of a file, and passed its
    filename.  If this file is part of a package and is trying to import other
    modules from within its own package or another package rooted in a directory
    below it, pylint will classify it as a failed import.

    To get around this, we traverse down the directory tree to find the root of
    the package this module is in.  We then invoke pylint from this directory.

    Finally, we must correct the filenames in the output generated by pylint so
    Emacs doesn't become confused (it will expect just the original filename,
    while pylint may extend it with extra directories if we've traversed down
    the tree)
    """
    # traverse downwards until we are out of a python package
    full_path = osp.abspath(filename)
    parent_path = osp.dirname(full_path)
    child_path = osp.basename(full_path)

    while parent_path != "/" and osp.exists(osp.join(parent_path, "__init__.py")):
        child_path = osp.join(osp.basename(parent_path), child_path)
        parent_path = osp.dirname(parent_path)

    # Start pylint
    # Ensure we use the python and pylint associated with the running epylint
    run_cmd = "import sys; from pylint.lint import Run; Run(sys.argv[1:])"
    cmd = (
        [sys.executable, "-c", run_cmd]
        + [
            "--msg-template",
            "{path}:{line}: {category} ({msg_id}, {symbol}, {obj}) {msg}",
            "-r",
            "n",
            child_path,
        ]
        + list(options)
    )
    process = Popen(
        cmd, stdout=PIPE, cwd=parent_path, env=_get_env(), universal_newlines=True
    )

    for line in process.stdout:
        # remove pylintrc warning
        if line.startswith("No config file found"):
            continue

        # modify the file name thats output to reverse the path traversal we made
        parts = line.split(":")
        if parts and parts[0] == child_path:
            line = ":".join([filename] + parts[1:])
        print(line, end=" ")

    process.wait()
    return process.returncode


def py_run(command_options="", return_std=False, stdout=None, stderr=None):
    """Run pylint from python

    ``command_options`` is a string containing ``pylint`` command line options;
    ``return_std`` (boolean) indicates return of created standard output
    and error (see below);
    ``stdout`` and ``stderr`` are 'file-like' objects in which standard output
    could be written.

    Calling agent is responsible for stdout/err management (creation, close).
    Default standard output and error are those from sys,
    or standalone ones (``subprocess.PIPE``) are used
    if they are not set and ``return_std``.

    If ``return_std`` is set to ``True``, this function returns a 2-uple
    containing standard output and error related to created process,
    as follows: ``(stdout, stderr)``.

    To silently run Pylint on a module, and get its standard output and error:
        >>> (pylint_stdout, pylint_stderr) = py_run( 'module_name.py', True)
    """
    # Detect if we use Python as executable or not, else default to `python`
    executable = sys.executable if "python" in sys.executable else "python"

    # Create command line to call pylint
    epylint_part = [executable, "-c", "from pylint import epylint;epylint.Run()"]
    options = shlex.split(command_options, posix=not sys.platform.startswith("win"))
    cli = epylint_part + options

    # Providing standard output and/or error if not set
    if stdout is None:
        if return_std:
            stdout = PIPE
        else:
            stdout = sys.stdout
    if stderr is None:
        if return_std:
            stderr = PIPE
        else:
            stderr = sys.stderr
    # Call pylint in a subprocess
    process = Popen(
        cli,
        shell=False,
        stdout=stdout,
        stderr=stderr,
        env=_get_env(),
        universal_newlines=True,
    )
    proc_stdout, proc_stderr = process.communicate()
    # Return standard output and error
    if return_std:
        return StringIO(proc_stdout), StringIO(proc_stderr)
    return None


def _get_cycles(graph_dict, path, visited, result, vertice):
    """recursive function doing the real work for get_cycles"""
    if vertice in path:
        cycle = [vertice]
        for node in path[::-1]:
            if node == vertice:
                break
            cycle.insert(0, node)
        # make a canonical representation
        start_from = min(cycle)
        index = cycle.index(start_from)
        cycle = cycle[index:] + cycle[0:index]
        # append it to result if not already in
        if cycle not in result:
            result.append(cycle)
        return
    path.append(vertice)
    try:
        for node in graph_dict[vertice]:
            # don't check already visited nodes again
            if node not in visited:
                _get_cycles(graph_dict, path, visited, result, node)
                visited.add(node)
    except KeyError:
        pass
    path.pop()


def get_source(self):
        """returns self._source"""
        if self._source is None:
            self.emit("}\n")
            self._source = "\n".join(self.lines)
            del self.lines
        return self._source

def get_source ( self ) : if self . _source is None : self . emit ( "}\n" ) self . _source = "\n" . join ( self . lines ) del self . lines return self . _source


def generate(self, outputfile=None, dotfile=None, mapfile=None):
        """Generates a graph file.

        :param str outputfile: filename and path [defaults to graphname.png]
        :param str dotfile: filename and path [defaults to graphname.dot]
        :param str mapfile: filename and path

        :rtype: str
        :return: a path to the generated file
        """
        import subprocess  # introduced in py 2.4

        name = self.graphname
        if not dotfile:
            # if 'outputfile' is a dot file use it as 'dotfile'
            if outputfile and outputfile.endswith(".dot"):
                dotfile = outputfile
            else:
                dotfile = "%s.dot" % name
        if outputfile is not None:
            storedir, _, target = target_info_from_filename(outputfile)
            if target != "dot":
                pdot, dot_sourcepath = tempfile.mkstemp(".dot", name)
                os.close(pdot)
            else:
                dot_sourcepath = osp.join(storedir, dotfile)
        else:
            target = "png"
            pdot, dot_sourcepath = tempfile.mkstemp(".dot", name)
            ppng, outputfile = tempfile.mkstemp(".png", name)
            os.close(pdot)
            os.close(ppng)
        pdot = codecs.open(dot_sourcepath, "w", encoding="utf8")
        pdot.write(self.source)
        pdot.close()
        if target != "dot":
            use_shell = sys.platform == "win32"
            if mapfile:
                subprocess.call(
                    [
                        self.renderer,
                        "-Tcmapx",
                        "-o",
                        mapfile,
                        "-T",
                        target,
                        dot_sourcepath,
                        "-o",
                        outputfile,
                    ],
                    shell=use_shell,
                )
            else:
                subprocess.call(
                    [self.renderer, "-T", target, dot_sourcepath, "-o", outputfile],
                    shell=use_shell,
                )
            os.unlink(dot_sourcepath)
        return outputfile


def _rest_format_section(stream, section, options, doc=None):
    """format an options section using as ReST formatted output"""
    if section:
        print("%s\n%s" % (section, "'" * len(section)), file=stream)
    if doc:
        print(normalize_text(doc, line_len=79, indent=""), file=stream)
        print(file=stream)
    for optname, optdict, value in options:
        help_opt = optdict.get("help")
        print(":%s:" % optname, file=stream)
        if help_opt:
            help_opt = normalize_text(help_opt, line_len=79, indent="  ")
            print(help_opt, file=stream)
        if value:
            value = str(_format_option_value(optdict, value))
            print(file=stream)
            print("  Default: ``%s``" % value.replace("`` ", "```` ``"), file=stream)

def
_rest_format_section
(
stream
,
section
,
options
,
doc
=
)
:
if
section
:
print
(
"%s\n%s"
%
(
section
,
"'"
*
len
(
section
)
)
,
file
=
stream
)
if
doc
:
print
(
normalize_text
(
doc
,
line_len
=
79
,
indent
=
""
)
,
file
=
stream
)
print
(
file
=
stream
)
for
optname
,
optdict
,
value
in
options
:
help_opt
=
optdict
.
get
(
"help"
)
print
(
":%s:"
%
optname
,
file
=
stream
)
if
help_opt
:
help_opt
=
normalize_text
(
help_opt
,
line_len
=
79
,
indent
=
"  "
)
print
(
help_opt
,
file
=
stream
)
if
value
:
value
=
str
(
_format_option_value
(
optdict
,
value
)
)
print
(
file
=
stream
)
print
(
"  Default: ``%s``"
%
value
.
replace
(
"`` "
,
"```` ``"
)
,
file
=
stream
)


def _register_by_id_managed_msg(self, msgid, line, is_disabled=True):
        """If the msgid is a numeric one, then register it to inform the user
        it could furnish instead a symbolic msgid."""
        try:
            message_definitions = self.msgs_store.get_message_definitions(msgid)
            for message_definition in message_definitions:
                if msgid == message_definition.msgid:
                    MessagesHandlerMixIn.__by_id_managed_msgs.append(
                        (
                            self.current_name,
                            message_definition.msgid,
                            message_definition.symbol,
                            line,
                            is_disabled,
                        )
                    )
        except UnknownMessageError:
            pass

def _register_by_id_managed_msg ( self , msgid , line , is_disabled = True ) : try : message_definitions = self . msgs_store . get_message_definitions ( msgid ) for message_definition in message_definitions : if msgid == message_definition . msgid : MessagesHandlerMixIn . __by_id_managed_msgs . append ( ( self . current_name , message_definition . msgid , message_definition . symbol , line , is_disabled , ) ) except UnknownMessageError : pass

If the msgid is a numeric one then register it to inform the user it could furnish instead a symbolic msgid .


def disable(self, msgid, scope="package", line=None, ignore_unknown=False):
        """don't output message of the given id"""
        self._set_msg_status(
            msgid, enable=False, scope=scope, line=line, ignore_unknown=ignore_unknown
        )
        self._register_by_id_managed_msg(msgid, line)

def disable ( self , msgid , scope = "package" , line = None , ignore_unknown = False ) : self . _set_msg_status ( msgid , enable = False , scope = scope , line = line , ignore_unknown = ignore_unknown ) self . _register_by_id_managed_msg ( msgid , line )


def enable(self, msgid, scope="package", line=None, ignore_unknown=False):
        """reenable message of the given id"""
        self._set_msg_status(
            msgid, enable=True, scope=scope, line=line, ignore_unknown=ignore_unknown
        )
        self._register_by_id_managed_msg(msgid, line, is_disabled=False)

def enable ( self , msgid , scope = "package" , line = None , ignore_unknown = False ) : self . _set_msg_status ( msgid , enable = True , scope = scope , line = line , ignore_unknown = ignore_unknown ) self . _register_by_id_managed_msg ( msgid , line , is_disabled = False )


def _message_symbol(self, msgid):
        """Get the message symbol of the given message id

        Return the original message id if the message does not
        exist.
        """
        try:
            return [md.symbol for md in self.msgs_store.get_message_definitions(msgid)]
        except UnknownMessageError:
            return msgid

def _message_symbol ( self , msgid ) : try : return [ md . symbol for md in self . msgs_store . get_message_definitions ( msgid ) ] except UnknownMessageError : return msgid


def is_message_enabled(self, msg_descr, line=None, confidence=None):
        """return true if the message associated to the given message id is
        enabled

        msgid may be either a numeric or symbolic message id.
        """
        if self.config.confidence and confidence:
            if confidence.name not in self.config.confidence:
                return False
        try:
            message_definitions = self.msgs_store.get_message_definitions(msg_descr)
            msgids = [md.msgid for md in message_definitions]
        except UnknownMessageError:
            # The linter checks for messages that are not registered
            # due to version mismatch, just treat them as message IDs
            # for now.
            msgids = [msg_descr]
        for msgid in msgids:
            if self.is_one_message_enabled(msgid, line):
                return True
        return False