def _check_imports_order(self, _module_node):
        """Checks imports of module `node` are grouped by category

        Imports must follow this order: standard, 3rd party, local
        """
        std_imports = []
        third_party_imports = []
        first_party_imports = []
        # need of a list that holds third or first party ordered import
        external_imports = []
        local_imports = []
        third_party_not_ignored = []
        first_party_not_ignored = []
        local_not_ignored = []
        isort_obj = isort.SortImports(
            file_contents="",
            known_third_party=self.config.known_third_party,
            known_standard_library=self.config.known_standard_library,
        )
        for node, modname in self._imports_stack:
            if modname.startswith("."):
                package = "." + modname.split(".")[1]
            else:
                package = modname.split(".")[0]
            nested = not isinstance(node.parent, astroid.Module)
            ignore_for_import_order = not self.linter.is_message_enabled(
                "wrong-import-order", node.fromlineno
            )
            import_category = isort_obj.place_module(package)
            node_and_package_import = (node, package)
            if import_category in ("FUTURE", "STDLIB"):
                std_imports.append(node_and_package_import)
                wrong_import = (
                    third_party_not_ignored
                    or first_party_not_ignored
                    or local_not_ignored
                )
                if self._is_fallback_import(node, wrong_import):
                    continue
                if wrong_import and not nested:
                    self.add_message(
                        "wrong-import-order",
                        node=node,
                        args=(
                            'standard import "%s"' % node.as_string(),
                            '"%s"' % wrong_import[0][0].as_string(),
                        ),
                    )
            elif import_category == "THIRDPARTY":
                third_party_imports.append(node_and_package_import)
                external_imports.append(node_and_package_import)
                if not nested and not ignore_for_import_order:
                    third_party_not_ignored.append(node_and_package_import)
                wrong_import = first_party_not_ignored or local_not_ignored
                if wrong_import and not nested:
                    self.add_message(
                        "wrong-import-order",
                        node=node,
                        args=(
                            'third party import "%s"' % node.as_string(),
                            '"%s"' % wrong_import[0][0].as_string(),
                        ),
                    )
            elif import_category == "FIRSTPARTY":
                first_party_imports.append(node_and_package_import)
                external_imports.append(node_and_package_import)
                if not nested and not ignore_for_import_order:
                    first_party_not_ignored.append(node_and_package_import)
                wrong_import = local_not_ignored
                if wrong_import and not nested:
                    self.add_message(
                        "wrong-import-order",
                        node=node,
                        args=(
                            'first party import "%s"' % node.as_string(),
                            '"%s"' % wrong_import[0][0].as_string(),
                        ),
                    )
            elif import_category == "LOCALFOLDER":
                local_imports.append((node, package))
                if not nested and not ignore_for_import_order:
                    local_not_ignored.append((node, package))
        return std_imports, external_imports, local_imports

def
_check_imports_order
(
self
,
_module_node
)
:
std_imports
=
[
]
third_party_imports
=
[
]
first_party_imports
=
[
]
external_imports
=
[
]
local_imports
=
[
]
third_party_not_ignored
=
[
]
first_party_not_ignored
=
[
]
local_not_ignored
=
[
]
isort_obj
=
isort
.
SortImports
(
file_contents
=
""
,
known_third_party
=
self
.
config
.
known_third_party
,
known_standard_library
=
self
.
config
.
known_standard_library
,
)
for
node
,
modname
in
self
.
_imports_stack
:
if
modname
.
startswith
(
"."
)
:
package
=
"."
+
modname
.
split
(
"."
)
[
1
]
else
:
package
=
modname
.
split
(
"."
)
[
0
]
nested
=
not
isinstance
(
node
.
parent
,
astroid
.
Module
)
ignore_for_import_order
=
not
self
.
linter
.
is_message_enabled
(
"wrong-import-order"
,
node
.
fromlineno
)
import_category
=
isort_obj
.
place_module
(
package
)
node_and_package_import
=
(
node
,
package
)
if
import_category
in
(
"FUTURE"
,
"STDLIB"
)
:
std_imports
.
append
(
node_and_package_import
)
wrong_import
=
(
third_party_not_ignored
or
first_party_not_ignored
or
local_not_ignored
)
if
self
.
_is_fallback_import
(
node
,
wrong_import
)
:
continue
if
wrong_import
and
not
nested
:
self
.
add_message
(
"wrong-import-order"
,
node
=
node
,
args
=
(
'standard import "%s"'
%
node
.
as_string
(
)
,
'"%s"'
%
wrong_import
[
0
]
[
0
]
.
as_string
(
)
,
)
,
)
elif
import_category
==
"THIRDPARTY"
:
third_party_imports
.
append
(
node_and_package_import
)
external_imports
.
append
(
node_and_package_import
)
if
not
nested
and
not
ignore_for_import_order
:
third_party_not_ignored
.
append
(
node_and_package_import
)
wrong_import
=
first_party_not_ignored
or
local_not_ignored
if
wrong_import
and
not
nested
:
self
.
add_message
(
"wrong-import-order"
,
node
=
node
,
args
=
(
'third party import "%s"'
%
node
.
as_string
(
)
,
'"%s"'
%
wrong_import
[
0
]
[
0
]
.
as_string
(
)
,
)
,
)
elif
import_category
==
"FIRSTPARTY"
:
first_party_imports
.
append
(
node_and_package_import
)
external_imports
.
append
(
node_and_package_import
)
if
not
nested
and
not
ignore_for_import_order
:
first_party_not_ignored
.
append
(
node_and_package_import
)
wrong_import
=
local_not_ignored
if
wrong_import
and
not
nested
:
self
.
add_message
(
"wrong-import-order"
,
node
=
node
,
args
=
(
'first party import "%s"'
%
node
.
as_string
(
)
,
'"%s"'
%
wrong_import
[
0
]
[
0
]
.
as_string
(
)
,
)
,
)
elif
import_category
==
"LOCALFOLDER"
:
local_imports
.
append
(
(
node
,
package
)
)
if
not
nested
and
not
ignore_for_import_order
:
local_not_ignored
.
append
(
(
node
,
package
)
)
return
std_imports
,
external_imports
,
local_imports

Checks imports of module node are grouped by category


def _check_relative_import(
        self, modnode, importnode, importedmodnode, importedasname
    ):
        """check relative import. node is either an Import or From node, modname
        the imported module name.
        """
        if not self.linter.is_message_enabled("relative-import"):
            return None
        if importedmodnode.file is None:
            return False  # built-in module
        if modnode is importedmodnode:
            return False  # module importing itself
        if modnode.absolute_import_activated() or getattr(importnode, "level", None):
            return False
        if importedmodnode.name != importedasname:
            # this must be a relative import...
            self.add_message(
                "relative-import",
                args=(importedasname, importedmodnode.name),
                node=importnode,
            )
            return None
        return None

def _check_relative_import ( self , modnode , importnode , importedmodnode , importedasname ) : if not self . linter . is_message_enabled ( "relative-import" ) : return None if importedmodnode . file is None : return False if modnode is importedmodnode : return False if modnode . absolute_import_activated ( ) or getattr ( importnode , "level" , None ) : return False if importedmodnode . name != importedasname : self . add_message ( "relative-import" , args = ( importedasname , importedmodnode . name ) , node = importnode , ) return None return None

check relative import . node is either an Import or From node modname the imported module name .


def _add_imported_module(self, node, importedmodname):
        """notify an imported module, used to analyze dependencies"""
        module_file = node.root().file
        context_name = node.root().name
        base = os.path.splitext(os.path.basename(module_file))[0]

        try:
            importedmodname = astroid.modutils.get_module_part(
                importedmodname, module_file
            )
        except ImportError:
            pass

        if context_name == importedmodname:
            self.add_message("import-self", node=node)

        elif not astroid.modutils.is_standard_module(importedmodname):
            # if this is not a package __init__ module
            if base != "__init__" and context_name not in self._module_pkg:
                # record the module's parent, or the module itself if this is
                # a top level module, as the package it belongs to
                self._module_pkg[context_name] = context_name.rsplit(".", 1)[0]

            # handle dependencies
            importedmodnames = self.stats["dependencies"].setdefault(
                importedmodname, set()
            )
            if context_name not in importedmodnames:
                importedmodnames.add(context_name)

            # update import graph
            self.import_graph[context_name].add(importedmodname)
            if not self.linter.is_message_enabled("cyclic-import", line=node.lineno):
                self._excluded_edges[context_name].add(importedmodname)

def _add_imported_module ( self , node , importedmodname ) : module_file = node . root ( ) . file context_name = node . root ( ) . name base = os . path . splitext ( os . path . basename ( module_file ) ) [ 0 ] try : importedmodname = astroid . modutils . get_module_part ( importedmodname , module_file ) except ImportError : pass if context_name == importedmodname : self . add_message ( "import-self" , node = node ) elif not astroid . modutils . is_standard_module ( importedmodname ) : if base != "__init__" and context_name not in self . _module_pkg : self . _module_pkg [ context_name ] = context_name . rsplit ( "." , 1 ) [ 0 ] importedmodnames = self . stats [ "dependencies" ] . setdefault ( importedmodname , set ( ) ) if context_name not in importedmodnames : importedmodnames . add ( context_name ) self . import_graph [ context_name ] . add ( importedmodname ) if not self . linter . is_message_enabled ( "cyclic-import" , line = node . lineno ) : self . _excluded_edges [ context_name ] . add ( importedmodname )

notify an imported module used to analyze dependencies


def _check_deprecated_module(self, node, mod_path):
        """check if the module is deprecated"""
        for mod_name in self.config.deprecated_modules:
            if mod_path == mod_name or mod_path.startswith(mod_name + "."):
                self.add_message("deprecated-module", node=node, args=mod_path)

def _check_deprecated_module ( self , node , mod_path ) : for mod_name in self . config . deprecated_modules : if mod_path == mod_name or mod_path . startswith ( mod_name + "." ) : self . add_message ( "deprecated-module" , node = node , args = mod_path )


def _check_preferred_module(self, node, mod_path):
        """check if the module has a preferred replacement"""
        if mod_path in self.preferred_modules:
            self.add_message(
                "preferred-module",
                node=node,
                args=(self.preferred_modules[mod_path], mod_path),
            )

def _check_preferred_module ( self , node , mod_path ) : if mod_path in self . preferred_modules : self . add_message ( "preferred-module" , node = node , args = ( self . preferred_modules [ mod_path ] , mod_path ) , )


def _report_external_dependencies(self, sect, _, _dummy):
        """return a verbatim layout for displaying dependencies"""
        dep_info = _make_tree_defs(self._external_dependencies_info().items())
        if not dep_info:
            raise EmptyReportError()
        tree_str = _repr_tree_defs(dep_info)
        sect.append(VerbatimText(tree_str))

def _report_external_dependencies ( self , sect , _ , _dummy ) : dep_info = _make_tree_defs ( self . _external_dependencies_info ( ) . items ( ) ) if not dep_info : raise EmptyReportError ( ) tree_str = _repr_tree_defs ( dep_info ) sect . append ( VerbatimText ( tree_str ) )


def _filter_dependencies_graph(self, internal):
        """build the internal or the external depedency graph"""
        graph = collections.defaultdict(set)
        for importee, importers in self.stats["dependencies"].items():
            for importer in importers:
                package = self._module_pkg.get(importer, importer)
                is_inside = importee.startswith(package)
                if is_inside and internal or not is_inside and not internal:
                    graph[importee].add(importer)
        return graph

def _filter_dependencies_graph ( self , internal ) : graph = collections . defaultdict ( set ) for importee , importers in self . stats [ "dependencies" ] . items ( ) : for importer in importers : package = self . _module_pkg . get ( importer , importer ) is_inside = importee . startswith ( package ) if is_inside and internal or not is_inside and not internal : graph [ importee ] . add ( importer ) return graph


def get_default_options():
    """
    Read config file and return list of options
    """
    options = []
    home = os.environ.get("HOME", "")
    if home:
        rcfile = os.path.join(home, RCFILE)
        try:
            options = open(rcfile).read().split()
        except IOError:
            pass  # ignore if no config file found
    return options

def get_default_options ( ) : options = [ ] home = os . environ . get ( "HOME" , "" ) if home : rcfile = os . path . join ( home , RCFILE ) try : options = open ( rcfile ) . read ( ) . split ( ) except IOError : pass return options


def insert_default_options():
    """insert default options to sys.argv
    """
    options = get_default_options()
    options.reverse()
    for arg in options:
        sys.argv.insert(1, arg)

def insert_default_options ( ) : options = get_default_options ( ) options . reverse ( ) for arg in options : sys . argv . insert ( 1 , arg )


def show_attr(self, node):
        """return true if the node should be treated
        """
        visibility = get_visibility(getattr(node, "name", node))
        return not self.__mode & VIS_MOD[visibility]

def show_attr ( self , node ) : visibility = get_visibility ( getattr ( node , "name" , node ) ) return not self . __mode & VIS_MOD [ visibility ]


def get_callbacks(self, node):
        """get callbacks from handler for the visited node"""
        klass = node.__class__
        methods = self._cache.get(klass)
        if methods is None:
            handler = self.handler
            kid = klass.__name__.lower()
            e_method = getattr(
                handler, "visit_%s" % kid, getattr(handler, "visit_default", None)
            )
            l_method = getattr(
                handler, "leave_%s" % kid, getattr(handler, "leave_default", None)
            )
            self._cache[klass] = (e_method, l_method)
        else:
            e_method, l_method = methods
        return e_method, l_method

def get_callbacks ( self , node ) : klass = node . __class__ methods = self . _cache . get ( klass ) if methods is None : handler = self . handler kid = klass . __name__ . lower ( ) e_method = getattr ( handler , "visit_%s" % kid , getattr ( handler , "visit_default" , None ) ) l_method = getattr ( handler , "leave_%s" % kid , getattr ( handler , "leave_default" , None ) ) self . _cache [ klass ] = ( e_method , l_method ) else : e_method , l_method = methods return e_method , l_method


def visit(self, node):
        """launch the visit starting from the given node"""
        if node in self._visited:
            return None
        self._visited[node] = 1  # FIXME: use set ?
        methods = self.get_callbacks(node)
        if methods[0] is not None:
            methods[0](node)
        if hasattr(node, "locals"):  # skip Instance and other proxy
            for local_node in node.values():
                self.visit(local_node)
        if methods[1] is not None:
            return methods[1](node)
        return None

def visit ( self , node ) : if node in self . _visited : return None self . _visited [ node ] = 1 methods = self . get_callbacks ( node ) if methods [ 0 ] is not None : methods [ 0 ] ( node ) if hasattr ( node , "locals" ) : for local_node in node . values ( ) : self . visit ( local_node ) if methods [ 1 ] is not None : return methods [ 1 ] ( node ) return None


def check_consistency(self) -> None:
        """Check the consistency of msgid.

        msg ids for a checker should be a string of len 4, where the two first
        characters are the checker id and the two last the msg id in this
        checker.

        :raises InvalidMessageError: If the checker id in the messages are not
        always the same. """
        checker_id = None
        existing_ids = []
        for message in self.messages:
            if checker_id is not None and checker_id != message.msgid[1:3]:
                error_msg = "Inconsistent checker part in message id "
                error_msg += "'{}' (expected 'x{checker_id}xx' ".format(
                    message.msgid, checker_id=checker_id
                )
                error_msg += "because we already had {existing_ids}).".format(
                    existing_ids=existing_ids
                )
                raise InvalidMessageError(error_msg)
            checker_id = message.msgid[1:3]
            existing_ids.append(message.msgid)


def visit_call(self, node):
        """Visit a Call node."""
        try:
            for inferred in node.func.infer():
                if inferred is astroid.Uninferable:
                    continue
                elif inferred.root().name == OPEN_MODULE:
                    if getattr(node.func, "name", None) in OPEN_FILES:
                        self._check_open_mode(node)
                elif inferred.root().name == UNITTEST_CASE:
                    self._check_redundant_assert(node, inferred)
                elif isinstance(inferred, astroid.ClassDef):
                    if inferred.qname() == THREADING_THREAD:
                        self._check_bad_thread_instantiation(node)
                    elif inferred.qname() == SUBPROCESS_POPEN:
                        self._check_for_preexec_fn_in_popen(node)
                elif isinstance(inferred, astroid.FunctionDef):
                    name = inferred.qname()
                    if name == COPY_COPY:
                        self._check_shallow_copy_environ(node)
                    elif name in ENV_GETTERS:
                        self._check_env_function(node, inferred)
                    elif name == SUBPROCESS_RUN and PY35:
                        self._check_for_check_kw_in_run(node)
                self._check_deprecated_method(node, inferred)
        except astroid.InferenceError:
            return

def visit_call ( self , node ) : try : for inferred in node . func . infer ( ) : if inferred is astroid . Uninferable : continue elif inferred . root ( ) . name == OPEN_MODULE : if getattr ( node . func , "name" , None ) in OPEN_FILES : self . _check_open_mode ( node ) elif inferred . root ( ) . name == UNITTEST_CASE : self . _check_redundant_assert ( node , inferred ) elif isinstance ( inferred , astroid . ClassDef ) : if inferred . qname ( ) == THREADING_THREAD : self . _check_bad_thread_instantiation ( node ) elif inferred . qname ( ) == SUBPROCESS_POPEN : self . _check_for_preexec_fn_in_popen ( node ) elif isinstance ( inferred , astroid . FunctionDef ) : name = inferred . qname ( ) if name == COPY_COPY : self . _check_shallow_copy_environ ( node ) elif name in ENV_GETTERS : self . _check_env_function ( node , inferred ) elif name == SUBPROCESS_RUN and PY35 : self . _check_for_check_kw_in_run ( node ) self . _check_deprecated_method ( node , inferred ) except astroid . InferenceError : return


def _check_datetime(self, node):
        """ Check that a datetime was infered.
        If so, emit boolean-datetime warning.
        """
        try:
            infered = next(node.infer())
        except astroid.InferenceError:
            return
        if isinstance(infered, Instance) and infered.qname() == "datetime.time":
            self.add_message("boolean-datetime", node=node)

def _check_datetime ( self , node ) : try : infered = next ( node . infer ( ) ) except astroid . InferenceError : return if isinstance ( infered , Instance ) and infered . qname ( ) == "datetime.time" : self . add_message ( "boolean-datetime" , node = node )

Check that a datetime was infered . If so emit boolean - datetime warning .


def _check_open_mode(self, node):
        """Check that the mode argument of an open or file call is valid."""
        try:
            mode_arg = utils.get_argument_from_call(node, position=1, keyword="mode")
        except utils.NoSuchArgumentError:
            return
        if mode_arg:
            mode_arg = utils.safe_infer(mode_arg)
            if isinstance(mode_arg, astroid.Const) and not _check_mode_str(
                mode_arg.value
            ):
                self.add_message("bad-open-mode", node=node, args=mode_arg.value)

def _check_open_mode ( self , node ) : try : mode_arg = utils . get_argument_from_call ( node , position = 1 , keyword = "mode" ) except utils . NoSuchArgumentError : return if mode_arg : mode_arg = utils . safe_infer ( mode_arg ) if isinstance ( mode_arg , astroid . Const ) and not _check_mode_str ( mode_arg . value ) : self . add_message ( "bad-open-mode" , node = node , args = mode_arg . value )

Check that the mode argument of an open or file call is valid .


def handle_message(self, msg):
        """Manage message of different type and in the context of path."""
        self.messages.append(
            {
                "type": msg.category,
                "module": msg.module,
                "obj": msg.obj,
                "line": msg.line,
                "column": msg.column,
                "path": msg.path,
                "symbol": msg.symbol,
                "message": html.escape(msg.msg or "", quote=False),
                "message-id": msg.msg_id,
            }
        )

def handle_message ( self , msg ) : self . messages . append ( { "type" : msg . category , "module" : msg . module , "obj" : msg . obj , "line" : msg . line , "column" : msg . column , "path" : msg . path , "symbol" : msg . symbol , "message" : html . escape ( msg . msg or "" , quote = False ) , "message-id" : msg . msg_id , } )

Manage message of different type and in the context of path .


def display_messages(self, layout):
        """Launch layouts display"""
        print(json.dumps(self.messages, indent=4), file=self.out)

def display_messages ( self , layout ) : print ( json . dumps ( self . messages , indent = 4 ) , file = self . out )


def get_title(self, node):
        """get title for objects"""
        title = node.name
        if self.module_names:
            title = "%s.%s" % (node.root().name, title)
        return title

def get_title ( self , node ) : title = node . name if self . module_names : title = "%s.%s" % ( node . root ( ) . name , title ) return title


def _set_default_options(self):
        """set different default options with _default dictionary"""
        self.module_names = self._set_option(self.config.module_names)
        all_ancestors = self._set_option(self.config.all_ancestors)
        all_associated = self._set_option(self.config.all_associated)
        anc_level, association_level = (0, 0)
        if all_ancestors:
            anc_level = -1
        if all_associated:
            association_level = -1
        if self.config.show_ancestors is not None:
            anc_level = self.config.show_ancestors
        if self.config.show_associated is not None:
            association_level = self.config.show_associated
        self.anc_level, self.association_level = anc_level, association_level

def _set_default_options ( self ) : self . module_names = self . _set_option ( self . config . module_names ) all_ancestors = self . _set_option ( self . config . all_ancestors ) all_associated = self . _set_option ( self . config . all_associated ) anc_level , association_level = ( 0 , 0 ) if all_ancestors : anc_level = - 1 if all_associated : association_level = - 1 if self . config . show_ancestors is not None : anc_level = self . config . show_ancestors if self . config . show_associated is not None : association_level = self . config . show_associated self . anc_level , self . association_level = anc_level , association_level


def show_node(self, node):
        """true if builtins and not show_builtins"""
        if self.config.show_builtin:
            return True
        return node.root().name != BUILTINS_NAME

def show_node ( self , node ) : if self . config . show_builtin : return True return node . root ( ) . name != BUILTINS_NAME


def add_class(self, node):
        """visit one class and add it to diagram"""
        self.linker.visit(node)
        self.classdiagram.add_object(self.get_title(node), node)

def add_class ( self , node ) : self . linker . visit ( node ) self . classdiagram . add_object ( self . get_title ( node ) , node )


def get_ancestors(self, node, level):
        """return ancestor nodes of a class node"""
        if level == 0:
            return
        for ancestor in node.ancestors(recurs=False):
            if not self.show_node(ancestor):
                continue
            yield ancestor

def get_ancestors ( self , node , level ) : if level == 0 : return for ancestor in node . ancestors ( recurs = False ) : if not self . show_node ( ancestor ) : continue yield ancestor


def get_associated(self, klass_node, level):
        """return associated nodes of a class node"""
        if level == 0:
            return
        for association_nodes in list(klass_node.instance_attrs_type.values()) + list(
            klass_node.locals_type.values()
        ):
            for node in association_nodes:
                if isinstance(node, astroid.Instance):
                    node = node._proxied
                if not (isinstance(node, astroid.ClassDef) and self.show_node(node)):
                    continue
                yield node

def get_associated ( self , klass_node , level ) : if level == 0 : return for association_nodes in list ( klass_node . instance_attrs_type . values ( ) ) + list ( klass_node . locals_type . values ( ) ) : for node in association_nodes : if isinstance ( node , astroid . Instance ) : node = node . _proxied if not ( isinstance ( node , astroid . ClassDef ) and self . show_node ( node ) ) : continue yield node


def extract_classes(self, klass_node, anc_level, association_level):
        """extract recursively classes related to klass_node"""
        if self.classdiagram.has_node(klass_node) or not self.show_node(klass_node):
            return
        self.add_class(klass_node)

        for ancestor in self.get_ancestors(klass_node, anc_level):
            self.extract_classes(ancestor, anc_level - 1, association_level)

        for node in self.get_associated(klass_node, association_level):
            self.extract_classes(node, anc_level, association_level - 1)

def extract_classes ( self , klass_node , anc_level , association_level ) : if self . classdiagram . has_node ( klass_node ) or not self . show_node ( klass_node ) : return self . add_class ( klass_node ) for ancestor in self . get_ancestors ( klass_node , anc_level ) : self . extract_classes ( ancestor , anc_level - 1 , association_level ) for node in self . get_associated ( klass_node , association_level ) : self . extract_classes ( node , anc_level , association_level - 1 )


def leave_project(self, node):  # pylint: disable=unused-argument
        """leave the pyreverse.utils.Project node

        return the generated diagram definition
        """
        if self.pkgdiagram:
            return self.pkgdiagram, self.classdiagram
        return (self.classdiagram,)

def leave_project ( self , node ) : if self . pkgdiagram : return self . pkgdiagram , self . classdiagram return ( self . classdiagram , )

leave the pyreverse . utils . Project node


def visit_importfrom(self, node):
        """visit astroid.ImportFrom  and catch modules for package diagram
        """
        if self.pkgdiagram:
            self.pkgdiagram.add_from_depend(node, node.modname)

def visit_importfrom ( self , node ) : if self . pkgdiagram : self . pkgdiagram . add_from_depend ( node , node . modname )

visit astroid . ImportFrom and catch modules for package diagram


def class_diagram(self, project, klass):
        """return a class diagram definition for the given klass and its
        related klasses
        """

        self.classdiagram = ClassDiagram(klass, self.config.mode)
        if len(project.modules) > 1:
            module, klass = klass.rsplit(".", 1)
            module = project.get_module(module)
        else:
            module = project.modules[0]
            klass = klass.split(".")[-1]
        klass = next(module.ilookup(klass))

        anc_level, association_level = self._get_levels()
        self.extract_classes(klass, anc_level, association_level)
        return self.classdiagram

def class_diagram ( self , project , klass ) : self . classdiagram = ClassDiagram ( klass , self . config . mode ) if len ( project . modules ) > 1 : module , klass = klass . rsplit ( "." , 1 ) module = project . get_module ( module ) else : module = project . modules [ 0 ] klass = klass . split ( "." ) [ - 1 ] klass = next ( module . ilookup ( klass ) ) anc_level , association_level = self . _get_levels ( ) self . extract_classes ( klass , anc_level , association_level ) return self . classdiagram


def get_diadefs(self, project, linker):
        """Get the diagrams configuration data

        :param project:The pyreverse project
        :type project: pyreverse.utils.Project
        :param linker: The linker
        :type linker: pyreverse.inspector.Linker(IdGeneratorMixIn, LocalsVisitor)

        :returns: The list of diagram definitions
        :rtype: list(:class:`pylint.pyreverse.diagrams.ClassDiagram`)
        """

        #  read and interpret diagram definitions (Diadefs)
        diagrams = []
        generator = ClassDiadefGenerator(linker, self)
        for klass in self.config.classes:
            diagrams.append(generator.class_diagram(project, klass))
        if not diagrams:
            diagrams = DefaultDiadefGenerator(linker, self).visit(project)
        for diagram in diagrams:
            diagram.extract_relationships()
        return diagrams

def get_diadefs ( self , project , linker ) : diagrams = [ ] generator = ClassDiadefGenerator ( linker , self ) for klass in self . config . classes : diagrams . append ( generator . class_diagram ( project , klass ) ) if not diagrams : diagrams = DefaultDiadefGenerator ( linker , self ) . visit ( project ) for diagram in diagrams : diagram . extract_relationships ( ) return diagrams


def _is_owner_ignored(owner, name, ignored_classes, ignored_modules):
    """Check if the given owner should be ignored

    This will verify if the owner's module is in *ignored_modules*
    or the owner's module fully qualified name is in *ignored_modules*
    or if the *ignored_modules* contains a pattern which catches
    the fully qualified name of the module.

    Also, similar checks are done for the owner itself, if its name
    matches any name from the *ignored_classes* or if its qualified
    name can be found in *ignored_classes*.
    """
    ignored_modules = set(ignored_modules)
    module_name = owner.root().name
    module_qname = owner.root().qname()
    if any(
        module_name in ignored_modules
        or module_qname in ignored_modules
        or fnmatch.fnmatch(module_qname, ignore)
        for ignore in ignored_modules
    ):
        return True

    ignored_classes = set(ignored_classes)
    if hasattr(owner, "qname"):
        qname = owner.qname()
    else:
        qname = ""
    return any(ignore in (name, qname) for ignore in ignored_classes)

def _is_owner_ignored ( owner , name , ignored_classes , ignored_modules ) : ignored_modules = set ( ignored_modules ) module_name = owner . root ( ) . name module_qname = owner . root ( ) . qname ( ) if any ( module_name in ignored_modules or module_qname in ignored_modules or fnmatch . fnmatch ( module_qname , ignore ) for ignore in ignored_modules ) : return True ignored_classes = set ( ignored_classes ) if hasattr ( owner , "qname" ) : qname = owner . qname ( ) else : qname = "" return any ( ignore in ( name , qname ) for ignore in ignored_classes )


def _similar_names(owner, attrname, distance_threshold, max_choices):
    """Given an owner and a name, try to find similar names

    The similar names are searched given a distance metric and only
    a given number of choices will be returned.
    """
    possible_names = []
    names = _node_names(owner)

    for name in names:
        if name == attrname:
            continue

        distance = _string_distance(attrname, name)
        if distance <= distance_threshold:
            possible_names.append((name, distance))

    # Now get back the values with a minimum, up to the given
    # limit or choices.
    picked = [
        name
        for (name, _) in heapq.nsmallest(
            max_choices, possible_names, key=operator.itemgetter(1)
        )
    ]
    return sorted(picked)

def _similar_names ( owner , attrname , distance_threshold , max_choices ) : possible_names = [ ] names = _node_names ( owner ) for name in names : if name == attrname : continue distance = _string_distance ( attrname , name ) if distance <= distance_threshold : possible_names . append ( ( name , distance ) ) picked = [ name for ( name , _ ) in heapq . nsmallest ( max_choices , possible_names , key = operator . itemgetter ( 1 ) ) ] return sorted ( picked )

Given an owner and a name try to find similar names


def _emit_no_member(node, owner, owner_name, ignored_mixins=True, ignored_none=True):
    """Try to see if no-member should be emitted for the given owner.

    The following cases are ignored:

        * the owner is a function and it has decorators.
        * the owner is an instance and it has __getattr__, __getattribute__ implemented
        * the module is explicitly ignored from no-member checks
        * the owner is a class and the name can be found in its metaclass.
        * The access node is protected by an except handler, which handles
          AttributeError, Exception or bare except.
    """
    # pylint: disable=too-many-return-statements
    if node_ignores_exception(node, AttributeError):
        return False
    if ignored_none and isinstance(owner, astroid.Const) and owner.value is None:
        return False
    if is_super(owner) or getattr(owner, "type", None) == "metaclass":
        return False
    if ignored_mixins and owner_name[-5:].lower() == "mixin":
        return False
    if isinstance(owner, astroid.FunctionDef) and owner.decorators:
        return False
    if isinstance(owner, (astroid.Instance, astroid.ClassDef)):
        if owner.has_dynamic_getattr():
            # Issue #2565: Don't ignore enums, as they have a `__getattr__` but it's not
            # invoked at this point.
            try:
                metaclass = owner.metaclass()
            except exceptions.MroError:
                return False
            if metaclass:
                return metaclass.qname() == "enum.EnumMeta"
            return False
        if not has_known_bases(owner):
            return False
    if isinstance(owner, objects.Super):
        # Verify if we are dealing with an invalid Super object.
        # If it is invalid, then there's no point in checking that
        # it has the required attribute. Also, don't fail if the
        # MRO is invalid.
        try:
            owner.super_mro()
        except (exceptions.MroError, exceptions.SuperError):
            return False
        if not all(map(has_known_bases, owner.type.mro())):
            return False
    if isinstance(owner, astroid.Module):
        try:
            owner.getattr("__getattr__")
            return False
        except astroid.NotFoundError:
            pass
    if node.attrname.startswith("_" + owner_name):
        # Test if an attribute has been mangled ('private' attribute)
        unmangled_name = node.attrname.split("_" + owner_name)[-1]
        try:
            if owner.getattr(unmangled_name, context=None) is not None:
                return False
        except astroid.NotFoundError:
            return True
    return True

def _emit_no_member ( node , owner , owner_name , ignored_mixins = True , ignored_none = True ) : if node_ignores_exception ( node , AttributeError ) : return False if ignored_none and isinstance ( owner , astroid . Const ) and owner . value is None : return False if is_super ( owner ) or getattr ( owner , "type" , None ) == "metaclass" : return False if ignored_mixins and owner_name [ - 5 : ] . lower ( ) == "mixin" : return False if isinstance ( owner , astroid . FunctionDef ) and owner . decorators : return False if isinstance ( owner , ( astroid . Instance , astroid . ClassDef ) ) : if owner . has_dynamic_getattr ( ) : try : metaclass = owner . metaclass ( ) except exceptions . MroError : return False if metaclass : return metaclass . qname ( ) == "enum.EnumMeta" return False if not has_known_bases ( owner ) : return False if isinstance ( owner , objects . Super ) : try : owner . super_mro ( ) except ( exceptions . MroError , exceptions . SuperError ) : return False if not all ( map ( has_known_bases , owner . type . mro ( ) ) ) : return False if isinstance ( owner , astroid . Module ) : try : owner . getattr ( "__getattr__" ) return False except astroid . NotFoundError : pass if node . attrname . startswith ( "_" + owner_name ) : unmangled_name = node . attrname . split ( "_" + owner_name ) [ - 1 ] try : if owner . getattr ( unmangled_name , context = None ) is not None : return False except astroid . NotFoundError : return True return True

Try to see if no - member should be emitted for the given owner .


def _has_parent_of_type(node, node_type, statement):
    """Check if the given node has a parent of the given type."""
    parent = node.parent
    while not isinstance(parent, node_type) and statement.parent_of(parent):
        parent = parent.parent
    return isinstance(parent, node_type)

def _has_parent_of_type ( node , node_type , statement ) : parent = node . parent while not isinstance ( parent , node_type ) and statement . parent_of ( parent ) : parent = parent . parent return isinstance ( parent , node_type )

Check if the given node has a parent of the given type .


def _is_name_used_as_variadic(name, variadics):
    """Check if the given name is used as a variadic argument."""
    return any(
        variadic.value == name or variadic.value.parent_of(name)
        for variadic in variadics
    )

def _is_name_used_as_variadic ( name , variadics ) : return any ( variadic . value == name or variadic . value . parent_of ( name ) for variadic in variadics )

Check if the given name is used as a variadic argument .


def _no_context_variadic(node, variadic_name, variadic_type, variadics):
    """Verify if the given call node has variadic nodes without context

    This is a workaround for handling cases of nested call functions
    which don't have the specific call context at hand.
    Variadic arguments (variable positional arguments and variable
    keyword arguments) are inferred, inherently wrong, by astroid
    as a Tuple, respectively a Dict with empty elements.
    This can lead pylint to believe that a function call receives
    too few arguments.
    """
    statement = node.statement()
    for name in statement.nodes_of_class(astroid.Name):
        if name.name != variadic_name:
            continue

        inferred = safe_infer(name)
        if isinstance(inferred, (astroid.List, astroid.Tuple)):
            length = len(inferred.elts)
        elif isinstance(inferred, astroid.Dict):
            length = len(inferred.items)
        else:
            continue

        inferred_statement = inferred.statement()
        if not length and isinstance(inferred_statement, astroid.FunctionDef):
            is_in_starred_context = _has_parent_of_type(node, variadic_type, statement)
            used_as_starred_argument = _is_name_used_as_variadic(name, variadics)
            if is_in_starred_context or used_as_starred_argument:
                return True
    return False

def _no_context_variadic ( node , variadic_name , variadic_type , variadics ) : statement = node . statement ( ) for name in statement . nodes_of_class ( astroid . Name ) : if name . name != variadic_name : continue inferred = safe_infer ( name ) if isinstance ( inferred , ( astroid . List , astroid . Tuple ) ) : length = len ( inferred . elts ) elif isinstance ( inferred , astroid . Dict ) : length = len ( inferred . items ) else : continue inferred_statement = inferred . statement ( ) if not length and isinstance ( inferred_statement , astroid . FunctionDef ) : is_in_starred_context = _has_parent_of_type ( node , variadic_type , statement ) used_as_starred_argument = _is_name_used_as_variadic ( name , variadics ) if is_in_starred_context or used_as_starred_argument : return True return False


def visit_attribute(self, node):
        """check that the accessed attribute exists

        to avoid too much false positives for now, we'll consider the code as
        correct if a single of the inferred nodes has the accessed attribute.

        function/method, super call and metaclasses are ignored
        """
        for pattern in self.config.generated_members:
            # attribute is marked as generated, stop here
            if re.match(pattern, node.attrname):
                return
            if re.match(pattern, node.as_string()):
                return

        try:
            inferred = list(node.expr.infer())
        except exceptions.InferenceError:
            return

        # list of (node, nodename) which are missing the attribute
        missingattr = set()

        non_opaque_inference_results = [
            owner
            for owner in inferred
            if owner is not astroid.Uninferable
            and not isinstance(owner, astroid.nodes.Unknown)
        ]
        if (
            len(non_opaque_inference_results) != len(inferred)
            and self.config.ignore_on_opaque_inference
        ):
            # There is an ambiguity in the inference. Since we can't
            # make sure that we won't emit a false positive, we just stop
            # whenever the inference returns an opaque inference object.
            return

        for owner in non_opaque_inference_results:
            name = getattr(owner, "name", None)
            if _is_owner_ignored(
                owner, name, self.config.ignored_classes, self.config.ignored_modules
            ):
                continue

            try:
                if not [
                    n
                    for n in owner.getattr(node.attrname)
                    if not isinstance(n.statement(), astroid.AugAssign)
                ]:
                    missingattr.add((owner, name))
                    continue
            except AttributeError:
                # XXX method / function
                continue
            except exceptions.NotFoundError:
                # This can't be moved before the actual .getattr call,
                # because there can be more values inferred and we are
                # stopping after the first one which has the attribute in question.
                # The problem is that if the first one has the attribute,
                # but we continue to the next values which doesn't have the
                # attribute, then we'll have a false positive.
                # So call this only after the call has been made.
                if not _emit_no_member(
                    node,
                    owner,
                    name,
                    ignored_mixins=self.config.ignore_mixin_members,
                    ignored_none=self.config.ignore_none,
                ):
                    continue
                missingattr.add((owner, name))
                continue
            # stop on the first found
            break
        else:
            # we have not found any node with the attributes, display the
            # message for infered nodes
            done = set()
            for owner, name in missingattr:
                if isinstance(owner, astroid.Instance):
                    actual = owner._proxied
                else:
                    actual = owner
                if actual in done:
                    continue
                done.add(actual)

                msg, hint = self._get_nomember_msgid_hint(node, owner)
                self.add_message(
                    msg,
                    node=node,
                    args=(owner.display_type(), name, node.attrname, hint),
                    confidence=INFERENCE,
                )

def visit_attribute ( self , node ) : for pattern in self . config . generated_members : if re . match ( pattern , node . attrname ) : return if re . match ( pattern , node . as_string ( ) ) : return try : inferred = list ( node . expr . infer ( ) ) except exceptions . InferenceError : return missingattr = set ( ) non_opaque_inference_results = [ owner for owner in inferred if owner is not astroid . Uninferable and not isinstance ( owner , astroid . nodes . Unknown ) ] if ( len ( non_opaque_inference_results ) != len ( inferred ) and self . config . ignore_on_opaque_inference ) : return for owner in non_opaque_inference_results : name = getattr ( owner , "name" , None ) if _is_owner_ignored ( owner , name , self . config . ignored_classes , self . config . ignored_modules ) : continue try : if not [ n for n in owner . getattr ( node . attrname ) if not isinstance ( n . statement ( ) , astroid . AugAssign ) ] : missingattr . add ( ( owner , name ) ) continue except AttributeError : continue except exceptions . NotFoundError : if not _emit_no_member ( node , owner , name , ignored_mixins = self . config . ignore_mixin_members , ignored_none = self . config . ignore_none , ) : continue missingattr . add ( ( owner , name ) ) continue break else : done = set ( ) for owner , name in missingattr : if isinstance ( owner , astroid . Instance ) : actual = owner . _proxied else : actual = owner if actual in done : continue done . add ( actual ) msg , hint = self . _get_nomember_msgid_hint ( node , owner ) self . add_message ( msg , node = node , args = ( owner . display_type ( ) , name , node . attrname , hint ) , confidence = INFERENCE , )


def visit_assign(self, node):
        """check that if assigning to a function call, the function is
        possibly returning something valuable
        """
        if not isinstance(node.value, astroid.Call):
            return
        function_node = safe_infer(node.value.func)
        # skip class, generator and incomplete function definition
        funcs = (astroid.FunctionDef, astroid.UnboundMethod, astroid.BoundMethod)
        if not (
            isinstance(function_node, funcs)
            and function_node.root().fully_defined()
            and not function_node.decorators
        ):
            return
        if (
            function_node.is_generator()
            or function_node.is_abstract(pass_is_abstract=False)
            or isinstance(function_node, astroid.AsyncFunctionDef)
        ):
            return
        returns = list(
            function_node.nodes_of_class(astroid.Return, skip_klass=astroid.FunctionDef)
        )
        if not returns:
            self.add_message("assignment-from-no-return", node=node)
        else:
            for rnode in returns:
                if not (
                    isinstance(rnode.value, astroid.Const)
                    and rnode.value.value is None
                    or rnode.value is None
                ):
                    break
            else:
                self.add_message("assignment-from-none", node=node)

def visit_assign ( self , node ) : if not isinstance ( node . value , astroid . Call ) : return function_node = safe_infer ( node . value . func ) funcs = ( astroid . FunctionDef , astroid . UnboundMethod , astroid . BoundMethod ) if not ( isinstance ( function_node , funcs ) and function_node . root ( ) . fully_defined ( ) and not function_node . decorators ) : return if ( function_node . is_generator ( ) or function_node . is_abstract ( pass_is_abstract = False ) or isinstance ( function_node , astroid . AsyncFunctionDef ) ) : return returns = list ( function_node . nodes_of_class ( astroid . Return , skip_klass = astroid . FunctionDef ) ) if not returns : self . add_message ( "assignment-from-no-return" , node = node ) else : for rnode in returns : if not ( isinstance ( rnode . value , astroid . Const ) and rnode . value . value is None or rnode . value is None ) : break else : self . add_message ( "assignment-from-none" , node = node )

check that if assigning to a function call the function is possibly returning something valuable


def _check_uninferable_call(self, node):
        """
        Check that the given uninferable Call node does not
        call an actual function.
        """
        if not isinstance(node.func, astroid.Attribute):
            return

        # Look for properties. First, obtain
        # the lhs of the Attribute node and search the attribute
        # there. If that attribute is a property or a subclass of properties,
        # then most likely it's not callable.

        # TODO: since astroid doesn't understand descriptors very well
        # we will not handle them here, right now.

        expr = node.func.expr
        klass = safe_infer(expr)
        if (
            klass is None
            or klass is astroid.Uninferable
            or not isinstance(klass, astroid.Instance)
        ):
            return

        try:
            attrs = klass._proxied.getattr(node.func.attrname)
        except exceptions.NotFoundError:
            return

        for attr in attrs:
            if attr is astroid.Uninferable:
                continue
            if not isinstance(attr, astroid.FunctionDef):
                continue

            # Decorated, see if it is decorated with a property.
            # Also, check the returns and see if they are callable.
            if decorated_with_property(attr):

                try:
                    all_returns_are_callable = all(
                        return_node.callable() or return_node is astroid.Uninferable
                        for return_node in attr.infer_call_result(node)
                    )
                except astroid.InferenceError:
                    continue

                if not all_returns_are_callable:
                    self.add_message(
                        "not-callable", node=node, args=node.func.as_string()
                    )
                    break

def _check_uninferable_call ( self , node ) : if not isinstance ( node . func , astroid . Attribute ) : return expr = node . func . expr klass = safe_infer ( expr ) if ( klass is None or klass is astroid . Uninferable or not isinstance ( klass , astroid . Instance ) ) : return try : attrs = klass . _proxied . getattr ( node . func . attrname ) except exceptions . NotFoundError : return for attr in attrs : if attr is astroid . Uninferable : continue if not isinstance ( attr , astroid . FunctionDef ) : continue if decorated_with_property ( attr ) : try : all_returns_are_callable = all ( return_node . callable ( ) or return_node is astroid . Uninferable for return_node in attr . infer_call_result ( node ) ) except astroid . InferenceError : continue if not all_returns_are_callable : self . add_message ( "not-callable" , node = node , args = node . func . as_string ( ) ) break

Check that the given uninferable Call node does not call an actual function .


def visit_unaryop(self, node):
        """Detect TypeErrors for unary operands."""

        for error in node.type_errors():
            # Let the error customize its output.
            self.add_message("invalid-unary-operand-type", args=str(error), node=node)

def visit_unaryop ( self , node ) : for error in node . type_errors ( ) : self . add_message ( "invalid-unary-operand-type" , args = str ( error ) , node = node )


def interfaces(node, herited=True, handler_func=_iface_hdlr):
    """Return an iterator on interfaces implemented by the given class node."""
    # FIXME: what if __implements__ = (MyIFace, MyParent.__implements__)...
    try:
        implements = bases.Instance(node).getattr("__implements__")[0]
    except exceptions.NotFoundError:
        return
    if not herited and implements.frame() is not node:
        return
    found = set()
    missing = False
    for iface in node_classes.unpack_infer(implements):
        if iface is astroid.Uninferable:
            missing = True
            continue
        if iface not in found and handler_func(iface):
            found.add(iface)
            yield iface
    if missing:
        raise exceptions.InferenceError()

def interfaces ( node , herited = True , handler_func = _iface_hdlr ) : try : implements = bases . Instance ( node ) . getattr ( "__implements__" ) [ 0 ] except exceptions . NotFoundError : return if not herited and implements . frame ( ) is not node : return found = set ( ) missing = False for iface in node_classes . unpack_infer ( implements ) : if iface is astroid . Uninferable : missing = True continue if iface not in found and handler_func ( iface ) : found . add ( iface ) yield iface if missing : raise exceptions . InferenceError ( )

Return an iterator on interfaces implemented by the given class node .


def project_from_files(
    files, func_wrapper=_astroid_wrapper, project_name="no name", black_list=("CVS",)
):
    """return a Project from a list of files or modules"""
    # build the project representation
    astroid_manager = manager.AstroidManager()
    project = Project(project_name)
    for something in files:
        if not os.path.exists(something):
            fpath = modutils.file_from_modpath(something.split("."))
        elif os.path.isdir(something):
            fpath = os.path.join(something, "__init__.py")
        else:
            fpath = something
        ast = func_wrapper(astroid_manager.ast_from_file, fpath)
        if ast is None:
            continue
        # XXX why is first file defining the project.path ?
        project.path = project.path or ast.file
        project.add_module(ast)
        base_name = ast.name
        # recurse in package except if __init__ was explicitly given
        if ast.package and something.find("__init__") == -1:
            # recurse on others packages / modules if this is a package
            for fpath in modutils.get_module_files(
                os.path.dirname(ast.file), black_list
            ):
                ast = func_wrapper(astroid_manager.ast_from_file, fpath)
                if ast is None or ast.name == base_name:
                    continue
                project.add_module(ast)
    return project

def
project_from_files
(
files
,
func_wrapper
=
_astroid_wrapper
,
project_name
=
"no name"
,
black_list
=
(
"CVS"
,
)
)
:
astroid_manager
=
manager
.
AstroidManager
(
)
project
=
Project
(
project_name
)
for
something
in
files
:
if
not
os
.
path
.
exists
(
something
)
:
fpath
=
modutils
.
file_from_modpath
(
something
.
split
(
"."
)
)
elif
os
.
path
.
isdir
(
something
)
:
fpath
=
os
.
path
.
join
(
something
,
"__init__.py"
)
else
:
fpath
=
something
ast
=
func_wrapper
(
astroid_manager
.
ast_from_file
,
fpath
)
if
ast
is
:
continue
project
.
path
=
project
.
path
or
ast
.
file
project
.
add_module
(
ast
)
base_name
=
ast
.
name
if
ast
.
package
and
something
.
find
(
"__init__"
)
==
1
:
for
fpath
in
modutils
.
get_module_files
(
os
.
path
.
dirname
(
ast
.
file
)
,
black_list
)
:
ast
=
func_wrapper
(
astroid_manager
.
ast_from_file
,
fpath
)
if
ast
is
or
ast
.
name
==
base_name
:
continue
project
.
add_module
(
ast
)
return
project


def visit_package(self, node):
        """visit an astroid.Package node

         * optionally tag the node with a unique id
        """
        if self.tag:
            node.uid = self.generate_id()
        for subelmt in node.values():
            self.visit(subelmt)

def visit_package ( self , node ) : if self . tag : node . uid = self . generate_id ( ) for subelmt in node . values ( ) : self . visit ( subelmt )


def visit_functiondef(self, node):
        """visit an astroid.Function node

         * set the locals_type mapping
         * optionally tag the node with a unique id
        """
        if hasattr(node, "locals_type"):
            return
        node.locals_type = collections.defaultdict(list)
        if self.tag:
            node.uid = self.generate_id()

def visit_functiondef ( self , node ) : if hasattr ( node , "locals_type" ) : return node . locals_type = collections . defaultdict ( list ) if self . tag : node . uid = self . generate_id ( )


def visit_assignname(self, node):
        """visit an astroid.AssignName node

        handle locals_type
        """
        # avoid double parsing done by different Linkers.visit
        # running over the same project:
        if hasattr(node, "_handled"):
            return
        node._handled = True
        if node.name in node.frame():
            frame = node.frame()
        else:
            # the name has been defined as 'global' in the frame and belongs
            # there.
            frame = node.root()
        try:
            if not hasattr(frame, "locals_type"):
                # If the frame doesn't have a locals_type yet,
                # it means it wasn't yet visited. Visit it now
                # to add what's missing from it.
                if isinstance(frame, astroid.ClassDef):
                    self.visit_classdef(frame)
                elif isinstance(frame, astroid.FunctionDef):
                    self.visit_functiondef(frame)
                else:
                    self.visit_module(frame)

            current = frame.locals_type[node.name]
            values = set(node.infer())
            frame.locals_type[node.name] = list(set(current) | values)
        except astroid.InferenceError:
            pass

def visit_assignname ( self , node ) : if hasattr ( node , "_handled" ) : return node . _handled = True if node . name in node . frame ( ) : frame = node . frame ( ) else : frame = node . root ( ) try : if not hasattr ( frame , "locals_type" ) : if isinstance ( frame , astroid . ClassDef ) : self . visit_classdef ( frame ) elif isinstance ( frame , astroid . FunctionDef ) : self . visit_functiondef ( frame ) else : self . visit_module ( frame ) current = frame . locals_type [ node . name ] values = set ( node . infer ( ) ) frame . locals_type [ node . name ] = list ( set ( current ) | values ) except astroid . InferenceError : pass


def handle_assignattr_type(node, parent):
        """handle an astroid.assignattr node

        handle instance_attrs_type
        """
        try:
            values = set(node.infer())
            current = set(parent.instance_attrs_type[node.attrname])
            parent.instance_attrs_type[node.attrname] = list(current | values)
        except astroid.InferenceError:
            pass

def handle_assignattr_type ( node , parent ) : try : values = set ( node . infer ( ) ) current = set ( parent . instance_attrs_type [ node . attrname ] ) parent . instance_attrs_type [ node . attrname ] = list ( current | values ) except astroid . InferenceError : pass


def visit_import(self, node):
        """visit an astroid.Import node

        resolve module dependencies
        """
        context_file = node.root().file
        for name in node.names:
            relative = modutils.is_relative(name[0], context_file)
            self._imported_module(node, name[0], relative)

def visit_import ( self , node ) : context_file = node . root ( ) . file for name in node . names : relative = modutils . is_relative ( name [ 0 ] , context_file ) self . _imported_module ( node , name [ 0 ] , relative )


def visit_importfrom(self, node):
        """visit an astroid.ImportFrom node

        resolve module dependencies
        """
        basename = node.modname
        context_file = node.root().file
        if context_file is not None:
            relative = modutils.is_relative(basename, context_file)
        else:
            relative = False
        for name in node.names:
            if name[0] == "*":
                continue
            # analyze dependencies
            fullname = "%s.%s" % (basename, name[0])
            if fullname.find(".") > -1:
                try:
                    # TODO: don't use get_module_part,
                    # missing package precedence
                    fullname = modutils.get_module_part(fullname, context_file)
                except ImportError:
                    continue
            if fullname != basename:
                self._imported_module(node, fullname, relative)

def visit_importfrom ( self , node ) : basename = node . modname context_file = node . root ( ) . file if context_file is not None : relative = modutils . is_relative ( basename , context_file ) else : relative = False for name in node . names : if name [ 0 ] == "*" : continue fullname = "%s.%s" % ( basename , name [ 0 ] ) if fullname . find ( "." ) > - 1 : try : fullname = modutils . get_module_part ( fullname , context_file ) except ImportError : continue if fullname != basename : self . _imported_module ( node , fullname , relative )


def compute_module(self, context_name, mod_path):
        """return true if the module should be added to dependencies"""
        package_dir = os.path.dirname(self.project.path)
        if context_name == mod_path:
            return 0
        if modutils.is_standard_module(mod_path, (package_dir,)):
            return 1
        return 0

def compute_module ( self , context_name , mod_path ) : package_dir = os . path . dirname ( self . project . path ) if context_name == mod_path : return 0 if modutils . is_standard_module ( mod_path , ( package_dir , ) ) : return 1 return 0


def _imported_module(self, node, mod_path, relative):
        """Notify an imported module, used to analyze dependencies"""
        module = node.root()
        context_name = module.name
        if relative:
            mod_path = "%s.%s" % (".".join(context_name.split(".")[:-1]), mod_path)
        if self.compute_module(context_name, mod_path):
            # handle dependencies
            if not hasattr(module, "depends"):
                module.depends = []
            mod_paths = module.depends
            if mod_path not in mod_paths:
                mod_paths.append(mod_path)

def _imported_module ( self , node , mod_path , relative ) : module = node . root ( ) context_name = module . name if relative : mod_path = "%s.%s" % ( "." . join ( context_name . split ( "." ) [ : - 1 ] ) , mod_path ) if self . compute_module ( context_name , mod_path ) : if not hasattr ( module , "depends" ) : module . depends = [ ] mod_paths = module . depends if mod_path not in mod_paths : mod_paths . append ( mod_path )

Notify an imported module used to analyze dependencies


def _get_ansi_code(color=None, style=None):
    """return ansi escape code corresponding to color and style

    :type color: str or None
    :param color:
      the color name (see `ANSI_COLORS` for available values)
      or the color number when 256 colors are available

    :type style: str or None
    :param style:
      style string (see `ANSI_COLORS` for available values). To get
      several style effects at the same time, use a coma as separator.

    :raise KeyError: if an unexistent color or style identifier is given

    :rtype: str
    :return: the built escape code
    """
    ansi_code = []
    if style:
        style_attrs = utils._splitstrip(style)
        for effect in style_attrs:
            ansi_code.append(ANSI_STYLES[effect])
    if color:
        if color.isdigit():
            ansi_code.extend(["38", "5"])
            ansi_code.append(color)
        else:
            ansi_code.append(ANSI_COLORS[color])
    if ansi_code:
        return ANSI_PREFIX + ";".join(ansi_code) + ANSI_END
    return ""

def _get_ansi_code ( color = None , style = None ) : ansi_code = [ ] if style : style_attrs = utils . _splitstrip ( style ) for effect in style_attrs : ansi_code . append ( ANSI_STYLES [ effect ] ) if color : if color . isdigit ( ) : ansi_code . extend ( [ "38" , "5" ] ) ansi_code . append ( color ) else : ansi_code . append ( ANSI_COLORS [ color ] ) if ansi_code : return ANSI_PREFIX + ";" . join ( ansi_code ) + ANSI_END return ""


def colorize_ansi(msg, color=None, style=None):
    """colorize message by wrapping it with ansi escape codes

    :type msg: str or unicode
    :param msg: the message string to colorize

    :type color: str or None
    :param color:
      the color identifier (see `ANSI_COLORS` for available values)

    :type style: str or None
    :param style:
      style string (see `ANSI_COLORS` for available values). To get
      several style effects at the same time, use a coma as separator.

    :raise KeyError: if an unexistent color or style identifier is given

    :rtype: str or unicode
    :return: the ansi escaped string
    """
    # If both color and style are not defined, then leave the text as is
    if color is None and style is None:
        return msg
    escape_code = _get_ansi_code(color, style)
    # If invalid (or unknown) color, don't wrap msg with ansi codes
    if escape_code:
        return "%s%s%s" % (escape_code, msg, ANSI_RESET)
    return msg

def colorize_ansi ( msg , color = None , style = None ) : if color is None and style is None : return msg escape_code = _get_ansi_code ( color , style ) if escape_code : return "%s%s%s" % ( escape_code , msg , ANSI_RESET ) return msg


def register(linter):
    """Register the reporter classes with the linter."""
    linter.register_reporter(TextReporter)
    linter.register_reporter(ParseableTextReporter)
    linter.register_reporter(VSTextReporter)
    linter.register_reporter(ColorizedTextReporter)

def register ( linter ) : linter . register_reporter ( TextReporter ) linter . register_reporter ( ParseableTextReporter ) linter . register_reporter ( VSTextReporter ) linter . register_reporter ( ColorizedTextReporter )

Register the reporter classes with the linter .


def handle_message(self, msg):
        """manage message of different type and in the context of path"""
        if msg.module not in self._modules:
            if msg.module:
                self.writeln("************* Module %s" % msg.module)
                self._modules.add(msg.module)
            else:
                self.writeln("************* ")
        self.write_message(msg)

def
handle_message
(
self
,
msg
)
:
if
msg
.
module
not
in
self
.
_modules
:
if
msg
.
module
:
self
.
writeln
(
"************* Module %s"
%
msg
.
module
)
self
.
_modules
.
add
(
msg
.
module
)
else
:
self
.
writeln
(
"************* "
)
self
.
write_message
(
msg
)


def _display(self, layout):
        """launch layouts display"""
        print(file=self.out)
        TextWriter().format(layout, self.out)

def _display ( self , layout ) : print ( file = self . out ) TextWriter ( ) . format ( layout , self . out )


def handle_message(self, msg):
        """manage message of different types, and colorize output
        using ansi escape codes
        """
        if msg.module not in self._modules:
            color, style = self._get_decoration("S")
            if msg.module:
                modsep = colorize_ansi(
                    "************* Module %s" % msg.module, color, style
                )
            else:
                modsep = colorize_ansi("************* %s" % msg.module, color, style)
            self.writeln(modsep)
            self._modules.add(msg.module)
        color, style = self._get_decoration(msg.C)

        msg = msg._replace(
            **{
                attr: colorize_ansi(getattr(msg, attr), color, style)
                for attr in ("msg", "symbol", "category", "C")
            }
        )
        self.write_message(msg)

def
handle_message
(
self
,
msg
)
:
if
msg
.
module
not
in
self
.
_modules
:
color
,
style
=
self
.
_get_decoration
(
"S"
)
if
msg
.
module
:
modsep
=
colorize_ansi
(
"************* Module %s"
%
msg
.
module
,
color
,
style
)
else
:
modsep
=
colorize_ansi
(
"************* %s"
%
msg
.
module
,
color
,
style
)
self
.
writeln
(
modsep
)
self
.
_modules
.
add
(
msg
.
module
)
color
,
style
=
self
.
_get_decoration
(
msg
.
C
)
msg
=
msg
.
_replace
(
**
{
attr
:
colorize_ansi
(
getattr
(
msg
,
attr
)
,
color
,
style
)
for
attr
in
(
"msg"
,
"symbol"
,
"category"
,
"C"
)
}
)
self
.
write_message
(
msg
)

manage message of different types and colorize output using ansi escape codes


def open_graph(self, **args):
        """open a vcg graph
        """
        self._stream.write("%sgraph:{\n" % self._indent)
        self._inc_indent()
        self._write_attributes(GRAPH_ATTRS, **args)

def open_graph ( self , ** args ) : self . _stream . write ( "%sgraph:{\n" % self . _indent ) self . _inc_indent ( ) self . _write_attributes ( GRAPH_ATTRS , ** args )


def node(self, title, **args):
        """draw a node
        """
        self._stream.write('%snode: {title:"%s"' % (self._indent, title))
        self._write_attributes(NODE_ATTRS, **args)
        self._stream.write("}\n")

def
node
(
self
,
title
,
**
args
)
:
self
.
_stream
.
write
(
'%snode: {title:"%s"'
%
(
self
.
_indent
,
title
)
)
self
.
_write_attributes
(
NODE_ATTRS
,
**
args
)
self
.
_stream
.
write
(
"}\n"
)


def edge(self, from_node, to_node, edge_type="", **args):
        """draw an edge from a node to another.
        """
        self._stream.write(
            '%s%sedge: {sourcename:"%s" targetname:"%s"'
            % (self._indent, edge_type, from_node, to_node)
        )
        self._write_attributes(EDGE_ATTRS, **args)
        self._stream.write("}\n")


def _check_new_format(self, node, func):
        """ Check the new string formatting. """
        # TODO: skip (for now) format nodes which don't have
        #       an explicit string on the left side of the format operation.
        #       We do this because our inference engine can't properly handle
        #       redefinitions of the original string.
        #       For more details, see issue 287.
        #
        # Note that there may not be any left side at all, if the format method
        # has been assigned to another variable. See issue 351. For example:
        #
        #    fmt = 'some string {}'.format
        #    fmt('arg')
        if isinstance(node.func, astroid.Attribute) and not isinstance(
            node.func.expr, astroid.Const
        ):
            return
        if node.starargs or node.kwargs:
            return
        try:
            strnode = next(func.bound.infer())
        except astroid.InferenceError:
            return
        if not (isinstance(strnode, astroid.Const) and isinstance(strnode.value, str)):
            return
        try:
            call_site = CallSite.from_call(node)
        except astroid.InferenceError:
            return

        try:
            fields, num_args, manual_pos = utils.parse_format_method_string(
                strnode.value
            )
        except utils.IncompleteFormatString:
            self.add_message("bad-format-string", node=node)
            return

        positional_arguments = call_site.positional_arguments
        named_arguments = call_site.keyword_arguments
        named_fields = {field[0] for field in fields if isinstance(field[0], str)}
        if num_args and manual_pos:
            self.add_message("format-combined-specification", node=node)
            return

        check_args = False
        # Consider "{[0]} {[1]}" as num_args.
        num_args += sum(1 for field in named_fields if field == "")
        if named_fields:
            for field in named_fields:
                if field and field not in named_arguments:
                    self.add_message(
                        "missing-format-argument-key", node=node, args=(field,)
                    )
            for field in named_arguments:
                if field not in named_fields:
                    self.add_message(
                        "unused-format-string-argument", node=node, args=(field,)
                    )
            # num_args can be 0 if manual_pos is not.
            num_args = num_args or manual_pos
            if positional_arguments or num_args:
                empty = any(True for field in named_fields if field == "")
                if named_arguments or empty:
                    # Verify the required number of positional arguments
                    # only if the .format got at least one keyword argument.
                    # This means that the format strings accepts both
                    # positional and named fields and we should warn
                    # when one of the them is missing or is extra.
                    check_args = True
        else:
            check_args = True
        if check_args:
            # num_args can be 0 if manual_pos is not.
            num_args = num_args or manual_pos
            if len(positional_arguments) > num_args:
                self.add_message("too-many-format-args", node=node)
            elif len(positional_arguments) < num_args:
                self.add_message("too-few-format-args", node=node)

        self._detect_vacuous_formatting(node, positional_arguments)
        self._check_new_format_specifiers(node, fields, named_arguments)

def _check_new_format ( self , node , func ) : if isinstance ( node . func , astroid . Attribute ) and not isinstance ( node . func . expr , astroid . Const ) : return if node . starargs or node . kwargs : return try : strnode = next ( func . bound . infer ( ) ) except astroid . InferenceError : return if not ( isinstance ( strnode , astroid . Const ) and isinstance ( strnode . value , str ) ) : return try : call_site = CallSite . from_call ( node ) except astroid . InferenceError : return try : fields , num_args , manual_pos = utils . parse_format_method_string ( strnode . value ) except utils . IncompleteFormatString : self . add_message ( "bad-format-string" , node = node ) return positional_arguments = call_site . positional_arguments named_arguments = call_site . keyword_arguments named_fields = { field [ 0 ] for field in fields if isinstance ( field [ 0 ] , str ) } if num_args and manual_pos : self . add_message ( "format-combined-specification" , node = node ) return check_args = False num_args += sum ( 1 for field in named_fields if field == "" ) if named_fields : for field in named_fields : if field and field not in named_arguments : self . add_message ( "missing-format-argument-key" , node = node , args = ( field , ) ) for field in named_arguments : if field not in named_fields : self . add_message ( "unused-format-string-argument" , node = node , args = ( field , ) ) num_args = num_args or manual_pos if positional_arguments or num_args : empty = any ( True for field in named_fields if field == "" ) if named_arguments or empty : check_args = True else : check_args = True if check_args : num_args = num_args or manual_pos if len ( positional_arguments ) > num_args : self . add_message ( "too-many-format-args" , node = node ) elif len ( positional_arguments ) < num_args : self . add_message ( "too-few-format-args" , node = node ) self . _detect_vacuous_formatting ( node , positional_arguments ) self . _check_new_format_specifiers ( node , fields , named_arguments )


def process_non_raw_string_token(self, prefix, string_body, start_row):
        """check for bad escapes in a non-raw string.

        prefix: lowercase string of eg 'ur' string prefix markers.
        string_body: the un-parsed body of the string, not including the quote
        marks.
        start_row: integer line number in the source.
        """
        # Walk through the string; if we see a backslash then escape the next
        # character, and skip over it.  If we see a non-escaped character,
        # alert, and continue.
        #
        # Accept a backslash when it escapes a backslash, or a quote, or
        # end-of-line, or one of the letters that introduce a special escape
        # sequence <http://docs.python.org/reference/lexical_analysis.html>
        #
        # TODO(mbp): Maybe give a separate warning about the rarely-used
        # \a \b \v \f?
        #
        # TODO(mbp): We could give the column of the problem character, but
        # add_message doesn't seem to have a way to pass it through at present.
        i = 0
        while True:
            i = string_body.find("\\", i)
            if i == -1:
                break
            # There must be a next character; having a backslash at the end
            # of the string would be a SyntaxError.
            next_char = string_body[i + 1]
            match = string_body[i : i + 2]
            if next_char in self.UNICODE_ESCAPE_CHARACTERS:
                if "u" in prefix:
                    pass
                elif (_PY3K or self._unicode_literals) and "b" not in prefix:
                    pass  # unicode by default
                else:
                    self.add_message(
                        "anomalous-unicode-escape-in-string",
                        line=start_row,
                        args=(match,),
                    )
            elif next_char not in self.ESCAPE_CHARACTERS:
                self.add_message(
                    "anomalous-backslash-in-string", line=start_row, args=(match,)
                )
            # Whether it was a valid escape or not, backslash followed by
            # another character can always be consumed whole: the second
            # character can never be the start of a new backslash escape.
            i += 2

def process_non_raw_string_token ( self , prefix , string_body , start_row ) : i = 0 while True : i = string_body . find ( "\\" , i ) if i == - 1 : break next_char = string_body [ i + 1 ] match = string_body [ i : i + 2 ] if next_char in self . UNICODE_ESCAPE_CHARACTERS : if "u" in prefix : pass elif ( _PY3K or self . _unicode_literals ) and "b" not in prefix : pass else : self . add_message ( "anomalous-unicode-escape-in-string" , line = start_row , args = ( match , ) , ) elif next_char not in self . ESCAPE_CHARACTERS : self . add_message ( "anomalous-backslash-in-string" , line = start_row , args = ( match , ) ) i += 2

check for bad escapes in a non - raw string .


def visit_section(self, layout):
        """display a section as text
        """
        self.section += 1
        self.writeln()
        self.format_children(layout)
        self.section -= 1
        self.writeln()

def visit_section ( self , layout ) : self . section += 1 self . writeln ( ) self . format_children ( layout ) self . section -= 1 self . writeln ( )


def visit_evaluationsection(self, layout):
        """Display an evaluation section as a text."""
        self.section += 1
        self.format_children(layout)
        self.section -= 1
        self.writeln()

def visit_evaluationsection ( self , layout ) : self . section += 1 self . format_children ( layout ) self . section -= 1 self . writeln ( )

Display an evaluation section as a text .


def visit_table(self, layout):
        """display a table as text"""
        table_content = self.get_table_content(layout)
        # get columns width
        cols_width = [0] * len(table_content[0])
        for row in table_content:
            for index, col in enumerate(row):
                cols_width[index] = max(cols_width[index], len(col))
        self.default_table(layout, table_content, cols_width)
        self.writeln()

def visit_table ( self , layout ) : table_content = self . get_table_content ( layout ) cols_width = [ 0 ] * len ( table_content [ 0 ] ) for row in table_content : for index , col in enumerate ( row ) : cols_width [ index ] = max ( cols_width [ index ] , len ( col ) ) self . default_table ( layout , table_content , cols_width ) self . writeln ( )


def default_table(self, layout, table_content, cols_width):
        """format a table"""
        cols_width = [size + 1 for size in cols_width]
        format_strings = " ".join(["%%-%ss"] * len(cols_width))
        format_strings = format_strings % tuple(cols_width)
        format_strings = format_strings.split(" ")
        table_linesep = "\n+" + "+".join(["-" * w for w in cols_width]) + "+\n"
        headsep = "\n+" + "+".join(["=" * w for w in cols_width]) + "+\n"
        # FIXME: layout.cheaders
        self.write(table_linesep)
        for index, line in enumerate(table_content):
            self.write("|")
            for line_index, at_index in enumerate(line):
                self.write(format_strings[line_index] % at_index)
                self.write("|")
            if index == 0 and layout.rheaders:
                self.write(headsep)
            else:
                self.write(table_linesep)

def
default_table
(
self
,
layout
,
table_content
,
cols_width
)
:
cols_width
=
[
size
+
1
for
size
in
cols_width
]
format_strings
=
" "
.
join
(
[
"%%-%ss"
]
*
len
(
cols_width
)
)
format_strings
=
format_strings
%
tuple
(
cols_width
)
format_strings
=
format_strings
.
split
(
" "
)
table_linesep
=
"\n+"
+
"+"
.
join
(
[
"-"
*
w
for
w
in
cols_width
]
)
+
"+\n"
headsep
=
"\n+"
+
"+"
.
join
(
[
"="
*
w
for
w
in
cols_width
]
)
+
"+\n"
self
.
write
(
table_linesep
)
for
index
,
line
in
enumerate
(
table_content
)
:
self
.
write
(
"|"
)
for
line_index
,
at_index
in
enumerate
(
line
)
:
self
.
write
(
format_strings
[
line_index
]
%
at_index
)
self
.
write
(
"|"
)
if
index
==
0
and
layout
.
rheaders
:
self
.
write
(
headsep
)
else
:
self
.
write
(
table_linesep
)


def add_renamed_message(self, old_id, old_symbol, new_symbol):
        """Register the old ID and symbol for a warning that was renamed.

        This allows users to keep using the old ID/symbol in suppressions.
        """
        message_definition = self.get_message_definitions(new_symbol)[0]
        message_definition.old_names.append((old_id, old_symbol))
        self._register_alternative_name(message_definition, old_id, old_symbol)

Register the old ID and symbol for a warning that was renamed .


def register_messages_from_checker(self, checker):
        """Register all messages from a checker.

        :param BaseChecker checker:
        """
        checker.check_consistency()
        for message in checker.messages:
            self.register_message(message)

def register_messages_from_checker ( self , checker ) : checker . check_consistency ( ) for message in checker . messages : self . register_message ( message )


def register_message(self, message):
        """Register a MessageDefinition with consistency in mind.

        :param MessageDefinition message: The message definition being added.
        """
        self._check_id_and_symbol_consistency(message.msgid, message.symbol)
        self._check_symbol(message.msgid, message.symbol)
        self._check_msgid(message.msgid, message.symbol)
        for old_name in message.old_names:
            self._check_symbol(message.msgid, old_name[1])
        self._messages_definitions[message.symbol] = message
        self._register_alternative_name(message, message.msgid, message.symbol)
        for old_id, old_symbol in message.old_names:
            self._register_alternative_name(message, old_id, old_symbol)
        self._msgs_by_category[message.msgid[0]].append(message.msgid)

def register_message ( self , message ) : self . _check_id_and_symbol_consistency ( message . msgid , message . symbol ) self . _check_symbol ( message . msgid , message . symbol ) self . _check_msgid ( message . msgid , message . symbol ) for old_name in message . old_names : self . _check_symbol ( message . msgid , old_name [ 1 ] ) self . _messages_definitions [ message . symbol ] = message self . _register_alternative_name ( message , message . msgid , message . symbol ) for old_id , old_symbol in message . old_names : self . _register_alternative_name ( message , old_id , old_symbol ) self . _msgs_by_category [ message . msgid [ 0 ] ] . append ( message . msgid )

Register a MessageDefinition with consistency in mind .


def _check_symbol(self, msgid, symbol):
        """Check that a symbol is not already used. """
        other_message = self._messages_definitions.get(symbol)
        if other_message:
            self._raise_duplicate_msg_id(symbol, msgid, other_message.msgid)
        else:
            alternative_msgid = None
        alternative_message = self._alternative_names.get(symbol)
        if alternative_message:
            if alternative_message.symbol == symbol:
                alternative_msgid = alternative_message.msgid
            else:
                for old_msgid, old_symbol in alternative_message.old_names:
                    if old_symbol == symbol:
                        alternative_msgid = old_msgid
                        break
            if msgid != alternative_msgid:
                self._raise_duplicate_msg_id(symbol, msgid, alternative_msgid)

def _check_symbol ( self , msgid , symbol ) : other_message = self . _messages_definitions . get ( symbol ) if other_message : self . _raise_duplicate_msg_id ( symbol , msgid , other_message . msgid ) else : alternative_msgid = None alternative_message = self . _alternative_names . get ( symbol ) if alternative_message : if alternative_message . symbol == symbol : alternative_msgid = alternative_message . msgid else : for old_msgid , old_symbol in alternative_message . old_names : if old_symbol == symbol : alternative_msgid = old_msgid break if msgid != alternative_msgid : self . _raise_duplicate_msg_id ( symbol , msgid , alternative_msgid )

Check that a symbol is not already used .


def _raise_duplicate_symbol(msgid, symbol, other_symbol):
        """Raise an error when a symbol is duplicated.

        :param str msgid: The msgid corresponding to the symbols
        :param str symbol: Offending symbol
        :param str other_symbol: Other offending symbol
        :raises InvalidMessageError: when a symbol is duplicated.
        """
        symbols = [symbol, other_symbol]
        symbols.sort()
        error_message = "Message id '{msgid}' cannot have both ".format(msgid=msgid)
        error_message += "'{other_symbol}' and '{symbol}' as symbolic name.".format(
            other_symbol=symbols[0], symbol=symbols[1]
        )
        raise InvalidMessageError(error_message)

Raise an error when a symbol is duplicated .


def _raise_duplicate_msg_id(symbol, msgid, other_msgid):
        """Raise an error when a msgid is duplicated.

        :param str symbol: The symbol corresponding to the msgids
        :param str msgid: Offending msgid
        :param str other_msgid: Other offending msgid
        :raises InvalidMessageError: when a msgid is duplicated.
        """
        msgids = [msgid, other_msgid]
        msgids.sort()
        error_message = "Message symbol '{symbol}' cannot be used for ".format(
            symbol=symbol
        )
        error_message += "'{other_msgid}' and '{msgid}' at the same time.".format(
            other_msgid=msgids[0], msgid=msgids[1]
        )
        raise InvalidMessageError(error_message)

Raise an error when a msgid is duplicated .


def get_message_definitions(self, msgid_or_symbol: str) -> list:
        """Returns the Message object for this message.

        :param str msgid_or_symbol: msgid_or_symbol may be either a numeric or symbolic id.
        :raises UnknownMessageError: if the message id is not defined.
        :rtype: List of MessageDefinition
        :return: A message definition corresponding to msgid_or_symbol
        """
        if msgid_or_symbol[1:].isdigit():
            msgid_or_symbol = msgid_or_symbol.upper()
        for source in (self._alternative_names, self._messages_definitions):
            try:
                return [source[msgid_or_symbol]]
            except KeyError:
                pass
        error_msg = "No such message id or symbol '{msgid_or_symbol}'.".format(
            msgid_or_symbol=msgid_or_symbol
        )
        raise UnknownMessageError(error_msg)

Returns the Message object for this message .


def get_msg_display_string(self, msgid):
        """Generates a user-consumable representation of a message.

        Can be just the message ID or the ID and the symbol.
        """
        message_definitions = self.get_message_definitions(msgid)
        if len(message_definitions) == 1:
            return repr(message_definitions[0].symbol)
        return repr([md.symbol for md in message_definitions])

def get_msg_display_string ( self , msgid ) : message_definitions = self . get_message_definitions ( msgid ) if len ( message_definitions ) == 1 : return repr ( message_definitions [ 0 ] . symbol ) return repr ( [ md . symbol for md in message_definitions ] )

Generates a user - consumable representation of a message .


def help_message(self, msgids):
        """Display help messages for the given message identifiers"""
        for msgid in msgids:
            try:
                for message_definition in self.get_message_definitions(msgid):
                    print(message_definition.format_help(checkerref=True))
                    print("")
            except UnknownMessageError as ex:
                print(ex)
                print("")
                continue

def help_message ( self , msgids ) : for msgid in msgids : try : for message_definition in self . get_message_definitions ( msgid ) : print ( message_definition . format_help ( checkerref = True ) ) print ( "" ) except UnknownMessageError as ex : print ( ex ) print ( "" ) continue


def list_messages(self):
        """Output full messages list documentation in ReST format. """
        messages = sorted(self._messages_definitions.values(), key=lambda m: m.msgid)
        for message in messages:
            if not message.may_be_emitted():
                continue
            print(message.format_help(checkerref=False))
        print("")

def list_messages ( self ) : messages = sorted ( self . _messages_definitions . values ( ) , key = lambda m : m . msgid ) for message in messages : if not message . may_be_emitted ( ) : continue print ( message . format_help ( checkerref = False ) ) print ( "" )

Output full messages list documentation in ReST format .


def builder_inited(app):
    """Output full documentation in ReST format for all extension modules"""
    # PACKAGE/docs/exts/pylint_extensions.py --> PACKAGE/
    base_path = os.path.dirname(
        os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    )
    # PACKAGE/ --> PACKAGE/pylint/extensions
    ext_path = os.path.join(base_path, "pylint", "extensions")
    modules = []
    doc_files = {}
    for filename in os.listdir(ext_path):
        name, ext = os.path.splitext(filename)
        if name[0] == "_" or name in DEPRECATED_MODULES:
            continue
        if ext == ".py":
            modules.append("pylint.extensions.%s" % name)
        elif ext == ".rst":
            doc_files["pylint.extensions." + name] = os.path.join(ext_path, filename)
    modules.sort()
    if not modules:
        sys.exit("No Pylint extensions found?")

    linter = PyLinter()
    linter.load_plugin_modules(modules)

    extensions_doc = os.path.join(
        base_path, "doc", "technical_reference", "extensions.rst"
    )
    with open(extensions_doc, "w") as stream:
        stream.write("Optional Pylint checkers in the extensions module\n")
        stream.write("=================================================\n\n")
        stream.write("Pylint provides the following optional plugins:\n\n")
        for module in modules:
            stream.write("- :ref:`{}`\n".format(module))
        stream.write("\n")
        stream.write(
            "You can activate any or all of these extensions "
            "by adding a ``load-plugins`` line to the ``MASTER`` "
            "section of your ``.pylintrc``, for example::\n"
        )
        stream.write(
            "\n    load-plugins=pylint.extensions.docparams,"
            "pylint.extensions.docstyle\n\n"
        )
        by_module = get_plugins_info(linter, doc_files)
        for module, info in sorted(by_module.items()):
            linter._print_checker_doc(info["name"], info, stream=stream)


def _cpu_count() -> int:
    """Use sched_affinity if available for virtualized or containerized environments."""
    sched_getaffinity = getattr(os, "sched_getaffinity", None)
    # pylint: disable=not-callable,using-constant-test
    if sched_getaffinity:
        return len(sched_getaffinity(0))
    if multiprocessing:
        return multiprocessing.cpu_count()
    return 1

def _cpu_count ( ) -> int : sched_getaffinity = getattr ( os , "sched_getaffinity" , None ) if sched_getaffinity : return len ( sched_getaffinity ( 0 ) ) if multiprocessing : return multiprocessing . cpu_count ( ) return 1

Use sched_affinity if available for virtualized or containerized environments .


def report_messages_stats(sect, stats, _):
    """make messages type report"""
    if not stats["by_msg"]:
        # don't print this report when we didn't detected any errors
        raise exceptions.EmptyReportError()
    in_order = sorted(
        [
            (value, msg_id)
            for msg_id, value in stats["by_msg"].items()
            if not msg_id.startswith("I")
        ]
    )
    in_order.reverse()
    lines = ("message id", "occurrences")
    for value, msg_id in in_order:
        lines += (msg_id, str(value))
    sect.append(report_nodes.Table(children=lines, cols=2, rheaders=1))

def
report_messages_stats
(
sect
,
stats
,
_
)
:
if
not
stats
[
"by_msg"
]
:
raise
exceptions
.
EmptyReportError
(
)
in_order
=
sorted
(
[
(
value
,
msg_id
)
for
msg_id
,
value
in
stats
[
"by_msg"
]
.
items
(
)
if
not
msg_id
.
startswith
(
"I"
)
]
)
in_order
.
reverse
(
)
lines
=
(
"message id"
,
"occurrences"
)
for
value
,
msg_id
in
in_order
:
lines
+=
(
msg_id
,
str
(
value
)
)
sect
.
append
(
report_nodes
.
Table
(
children
=
lines
,
cols
=
2
,
rheaders
=
1
)
)


def fix_import_path(args):
    """Prepare sys.path for running the linter checks.

    Within this context, each of the given arguments is importable.
    Paths are added to sys.path in corresponding order to the arguments.
    We avoid adding duplicate directories to sys.path.
    `sys.path` is reset to its original value upon exiting this context.
    """
    orig = list(sys.path)
    changes = []
    for arg in args:
        path = _get_python_path(arg)
        if path in changes:
            continue
        else:
            changes.append(path)
    sys.path[:] = changes + ["."] + sys.path
    try:
        yield
    finally:
        sys.path[:] = orig

def fix_import_path ( args ) : orig = list ( sys . path ) changes = [ ] for arg in args : path = _get_python_path ( arg ) if path in changes : continue else : changes . append ( path ) sys . path [ : ] = changes + [ "." ] + sys . path try : yield finally : sys . path [ : ] = orig

Prepare sys . path for running the linter checks .


def load_plugin_modules(self, modnames):
        """take a list of module names which are pylint plugins and load
        and register them
        """
        for modname in modnames:
            if modname in self._dynamic_plugins:
                continue
            self._dynamic_plugins.add(modname)
            module = modutils.load_module_from_name(modname)
            module.register(self)

def load_plugin_modules ( self , modnames ) : for modname in modnames : if modname in self . _dynamic_plugins : continue self . _dynamic_plugins . add ( modname ) module = modutils . load_module_from_name ( modname ) module . register ( self )


def load_plugin_configuration(self):
        """Call the configuration hook for plugins

        This walks through the list of plugins, grabs the "load_configuration"
        hook, if exposed, and calls it to allow plugins to configure specific
        settings.
        """
        for modname in self._dynamic_plugins:
            module = modutils.load_module_from_name(modname)
            if hasattr(module, "load_configuration"):
                module.load_configuration(self)

def load_plugin_configuration ( self ) : for modname in self . _dynamic_plugins : module = modutils . load_module_from_name ( modname ) if hasattr ( module , "load_configuration" ) : module . load_configuration ( self )


def set_option(self, optname, value, action=None, optdict=None):
        """overridden from config.OptionsProviderMixin to handle some
        special options
        """
        if optname in self._options_methods or optname in self._bw_options_methods:
            if value:
                try:
                    meth = self._options_methods[optname]
                except KeyError:
                    meth = self._bw_options_methods[optname]
                    warnings.warn(
                        "%s is deprecated, replace it by %s"
                        % (optname, optname.split("-")[0]),
                        DeprecationWarning,
                    )
                value = utils._check_csv(value)
                if isinstance(value, (list, tuple)):
                    for _id in value:
                        meth(_id, ignore_unknown=True)
                else:
                    meth(value)
                return  # no need to call set_option, disable/enable methods do it
        elif optname == "output-format":
            self._reporter_name = value
            # If the reporters are already available, load
            # the reporter class.
            if self._reporters:
                self._load_reporter()

        try:
            checkers.BaseTokenChecker.set_option(self, optname, value, action, optdict)
        except config.UnsupportedAction:
            print("option %s can't be read from config file" % optname, file=sys.stderr)

overridden from config . OptionsProviderMixin to handle some special options