| Index: third_party/pylint/checkers/imports.py
|
| diff --git a/third_party/pylint/checkers/imports.py b/third_party/pylint/checkers/imports.py
|
| index 5964a266049103b2f713b6e149191a03f43b0e5f..1969eeb1baee2de80a62d04efa8213845b4433d6 100644
|
| --- a/third_party/pylint/checkers/imports.py
|
| +++ b/third_party/pylint/checkers/imports.py
|
| @@ -16,6 +16,10 @@
|
| """imports checkers for Python code"""
|
|
|
| import sys
|
| +from collections import defaultdict
|
| +
|
| +import six
|
| +from six.moves import map # pylint: disable=redefined-builtin
|
|
|
| from logilab.common.graph import get_cycles, DotBackend
|
| from logilab.common.ureports import VerbatimText, Paragraph
|
| @@ -27,8 +31,16 @@ from astroid.modutils import get_module_part, is_standard_module
|
| from pylint.interfaces import IAstroidChecker
|
| from pylint.utils import EmptyReport
|
| from pylint.checkers import BaseChecker
|
| -from pylint.checkers.utils import check_messages
|
| +from pylint.checkers.utils import check_messages, is_import_error
|
|
|
| +def _except_import_error(node):
|
| + """
|
| + Check if the try-except node has an ImportError handler.
|
| + Return True if an ImportError handler was infered, False otherwise.
|
| + """
|
| + if not isinstance(node, astroid.TryExcept):
|
| + return
|
| + return any(map(is_import_error, node.handlers))
|
|
|
| def get_first_import(node, context, name, base, level):
|
| """return the node where [base.]<name> is imported or None if not found
|
| @@ -98,14 +110,14 @@ def dependencies_graph(filename, dep_info):
|
| done = {}
|
| printer = DotBackend(filename[:-4], rankdir='LR')
|
| printer.emit('URL="." node[shape="box"]')
|
| - for modname, dependencies in sorted(dep_info.iteritems()):
|
| + for modname, dependencies in sorted(six.iteritems(dep_info)):
|
| done[modname] = 1
|
| printer.emit_node(modname)
|
| for modname in dependencies:
|
| if modname not in done:
|
| done[modname] = 1
|
| printer.emit_node(modname)
|
| - for depmodname, dependencies in sorted(dep_info.iteritems()):
|
| + for depmodname, dependencies in sorted(six.iteritems(dep_info)):
|
| for modname in dependencies:
|
| printer.emit_edge(modname, depmodname)
|
| printer.generate(filename)
|
| @@ -220,20 +232,21 @@ given file (report RP0402 must not be disabled)'}
|
| self.linter.add_stats(dependencies={})
|
| self.linter.add_stats(cycles=[])
|
| self.stats = self.linter.stats
|
| - self.import_graph = {}
|
| + self.import_graph = defaultdict(set)
|
|
|
| def close(self):
|
| """called before visiting project (i.e set of modules)"""
|
| # don't try to compute cycles if the associated message is disabled
|
| if self.linter.is_message_enabled('cyclic-import'):
|
| - for cycle in get_cycles(self.import_graph):
|
| + vertices = list(self.import_graph)
|
| + for cycle in get_cycles(self.import_graph, vertices=vertices):
|
| self.add_message('cyclic-import', args=' -> '.join(cycle))
|
|
|
| def visit_import(self, node):
|
| """triggered when an import statement is seen"""
|
| modnode = node.root()
|
| for name, _ in node.names:
|
| - importedmodnode = self.get_imported_module(modnode, node, name)
|
| + importedmodnode = self.get_imported_module(node, name)
|
| if importedmodnode is None:
|
| continue
|
| self._check_relative_import(modnode, node, importedmodnode, name)
|
| @@ -260,7 +273,7 @@ given file (report RP0402 must not be disabled)'}
|
| if name == '*':
|
| self.add_message('wildcard-import', args=basename, node=node)
|
| modnode = node.root()
|
| - importedmodnode = self.get_imported_module(modnode, node, basename)
|
| + importedmodnode = self.get_imported_module(node, basename)
|
| if importedmodnode is None:
|
| return
|
| self._check_relative_import(modnode, node, importedmodnode, basename)
|
| @@ -270,15 +283,16 @@ given file (report RP0402 must not be disabled)'}
|
| self._add_imported_module(node, '%s.%s' % (importedmodnode.name, name))
|
| self._check_reimport(node, name, basename, node.level)
|
|
|
| - def get_imported_module(self, modnode, importnode, modname):
|
| + def get_imported_module(self, importnode, modname):
|
| try:
|
| return importnode.do_import_module(modname)
|
| - except astroid.InferenceError, ex:
|
| + except astroid.InferenceError as ex:
|
| if str(ex) != modname:
|
| args = '%r (%s)' % (modname, ex)
|
| else:
|
| args = repr(modname)
|
| - self.add_message("import-error", args=args, node=importnode)
|
| + if not _except_import_error(importnode.parent):
|
| + self.add_message("import-error", args=args, node=importnode)
|
|
|
| def _check_relative_import(self, modnode, importnode, importedmodnode,
|
| importedasname):
|
| @@ -295,7 +309,8 @@ given file (report RP0402 must not be disabled)'}
|
| return False
|
| if importedmodnode.name != importedasname:
|
| # this must be a relative import...
|
| - self.add_message('relative-import', args=(importedasname, importedmodnode.name),
|
| + self.add_message('relative-import',
|
| + args=(importedasname, importedmodnode.name),
|
| node=importnode)
|
|
|
| def _add_imported_module(self, node, importedmodname):
|
| @@ -315,8 +330,8 @@ given file (report RP0402 must not be disabled)'}
|
| if not context_name in importedmodnames:
|
| importedmodnames.add(context_name)
|
| # update import graph
|
| - mgraph = self.import_graph.setdefault(context_name, set())
|
| - if not importedmodname in mgraph:
|
| + mgraph = self.import_graph[context_name]
|
| + if importedmodname not in mgraph:
|
| mgraph.add(importedmodname)
|
|
|
| def _check_deprecated_module(self, node, mod_path):
|
| @@ -343,7 +358,7 @@ given file (report RP0402 must not be disabled)'}
|
|
|
| def report_external_dependencies(self, sect, _, dummy):
|
| """return a verbatim layout for displaying dependencies"""
|
| - dep_info = make_tree_defs(self._external_dependencies_info().iteritems())
|
| + dep_info = make_tree_defs(six.iteritems(self._external_dependencies_info()))
|
| if not dep_info:
|
| raise EmptyReport()
|
| tree_str = repr_tree_defs(dep_info)
|
| @@ -375,7 +390,7 @@ given file (report RP0402 must not be disabled)'}
|
| if self.__ext_dep_info is None:
|
| package = self.linter.current_name
|
| self.__ext_dep_info = result = {}
|
| - for importee, importers in self.stats['dependencies'].iteritems():
|
| + for importee, importers in six.iteritems(self.stats['dependencies']):
|
| if not importee.startswith(package):
|
| result[importee] = importers
|
| return self.__ext_dep_info
|
| @@ -387,7 +402,7 @@ given file (report RP0402 must not be disabled)'}
|
| if self.__int_dep_info is None:
|
| package = self.linter.current_name
|
| self.__int_dep_info = result = {}
|
| - for importee, importers in self.stats['dependencies'].iteritems():
|
| + for importee, importers in six.iteritems(self.stats['dependencies']):
|
| if importee.startswith(package):
|
| result[importee] = importers
|
| return self.__int_dep_info
|
|
|