summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Morgensen <james.morgensen@gmail.com>2015-05-01 02:52:23 -0700
committerJames Morgensen <james.morgensen@gmail.com>2015-05-01 02:52:23 -0700
commitf1ec472ac772527ad3f21a75c5f2a933f1ba2e99 (patch)
treedd519072fbda35898c7f798ceb9c097f8f06d982
parentd4c467eaa089112c06d7ddf944ea0c4446476e20 (diff)
downloadpylint-f1ec472ac772527ad3f21a75c5f2a933f1ba2e99.tar.gz
Make fix for #223 more readable; add a test and a ChangeLog line.
-rw-r--r--ChangeLog4
-rw-r--r--pylint/checkers/imports.py21
-rw-r--r--pylint/test/unittest_checker_imports.py60
3 files changed, 82 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 6db44aa..d32c9f8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,10 @@ ChangeLog for Pylint
--------------------
--
+ * Don't emit import-error for ignored modules. PyLint will not emit import
+ errors for any import which is, or is a subpackage of, a module in
+ the ignored-modules list. Closes issue #223.
+
* Fix unused-import false positive when the import is used in a
class assignment. Closes issue #475
diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py
index eb93b4f..20f8db9 100644
--- a/pylint/checkers/imports.py
+++ b/pylint/checkers/imports.py
@@ -291,12 +291,27 @@ given file (report RP0402 must not be disabled)'}
args = '%r (%s)' % (modname, ex)
else:
args = repr(modname)
+
ignored_modules = get_global_option(self, 'ignored-modules', default=[])
- while modname and modname not in ignored_modules:
- modname = modname.rpartition('.')[0]
- if not modname and not _except_import_error(importnode.parent):
+ for submodule in self._module_hierarchy(modname):
+ if submodule in ignored_modules:
+ return None
+
+ if not _except_import_error(importnode.parent):
self.add_message("import-error", args=args, node=importnode)
+ def _module_hierarchy(self, modname):
+ """Returns a list representing the module heirarchy, where each element
+ is the fullly qualified name of the parent of the next element.
+
+ For example,
+ _module_hierarchy('pylint.checkers.ImportsChecker')
+ returns
+ ['pylint', 'pylint.checkers', 'pylint.checkers.ImportsChecker']
+ """
+ names = modname.split('.')
+ return ['.'.join(names[0:i+1]) for i in range(len(names))]
+
def _check_relative_import(self, modnode, importnode, importedmodnode,
importedasname):
"""check relative import. node is either an Import or From node, modname
diff --git a/pylint/test/unittest_checker_imports.py b/pylint/test/unittest_checker_imports.py
new file mode 100644
index 0000000..55948ec
--- /dev/null
+++ b/pylint/test/unittest_checker_imports.py
@@ -0,0 +1,60 @@
+"""Unit tests for the imports checker."""
+import unittest
+
+from astroid import test_utils
+from pylint.checkers import imports
+from pylint.testutils import CheckerTestCase, set_config
+
+class ImportsCheckerTC(CheckerTestCase):
+
+ CHECKER_CLASS = imports.ImportsChecker
+
+ def test_bitbucket_issue_78(self):
+ """ Issue 78 report a false positive for unused-module """
+ module = test_utils.build_module("""
+ from sys import path
+ path += ['stuff']
+ def func():
+ other = 1
+ return len(other)
+ """)
+ with self.assertNoMessages():
+ self.walk(module)
+
+ @set_config(ignored_modules=('external_module', 'fake_module.submodule'))
+ def test_import_error_skipped(self):
+ """Make sure that imports do not emit a 'import-error' when the
+ module is configured to be ignored."""
+
+ node = test_utils.extract_node("""
+ from external_module import anything
+ """)
+ with self.assertNoMessages():
+ self.checker.visit_from(node)
+
+ node = test_utils.extract_node("""
+ from external_module.another_module import anything
+ """)
+ with self.assertNoMessages():
+ self.checker.visit_from(node)
+
+ node = test_utils.extract_node("""
+ import external_module
+ """)
+ with self.assertNoMessages():
+ self.checker.visit_import(node)
+
+ node = test_utils.extract_node("""
+ from fake_module.submodule import anything
+ """)
+ with self.assertNoMessages():
+ self.checker.visit_from(node)
+
+ node = test_utils.extract_node("""
+ from fake_module.submodule.deeper import anything
+ """)
+ with self.assertNoMessages():
+ self.checker.visit_from(node)
+
+if __name__ == '__main__':
+ unittest.main()