diff options
author | Claudiu Popa <cpopa@cloudbasesolutions.com> | 2015-07-14 16:22:00 +0300 |
---|---|---|
committer | Claudiu Popa <cpopa@cloudbasesolutions.com> | 2015-07-14 16:22:00 +0300 |
commit | 72cd3b2d573b6a1331d2cfd4c52f230da76f8f84 (patch) | |
tree | 0d77076cbbe52c0802db34360a42c6853ae0cc5e | |
parent | c90eae70b2d8974027b749f6996488a0b1a8903b (diff) | |
download | pylint-72cd3b2d573b6a1331d2cfd4c52f230da76f8f84.tar.gz |
Improve detection of relative imports in non-packages, as well as importing missing modules with a relative import from a package.
The change improves how relative imports are shown when they are missing,
with the absolute name, instead of the relative one.
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | pylint/checkers/imports.py | 24 | ||||
-rw-r--r-- | pylint/checkers/variables.py | 2 | ||||
-rw-r--r-- | pylint/test/functional/import_error.py | 2 | ||||
-rw-r--r-- | pylint/test/functional/import_error.txt | 5 | ||||
-rw-r--r-- | pylint/test/functional/no_name_in_module.py | 4 | ||||
-rw-r--r-- | pylint/test/functional/no_name_in_module.txt | 4 | ||||
-rw-r--r-- | pylint/test/test_functional.py | 1 | ||||
-rw-r--r-- | pylint/test/test_regr.py | 2 |
9 files changed, 39 insertions, 9 deletions
@@ -219,6 +219,10 @@ ChangeLog for Pylint * ignored-modules can work with qualified names as well as with Unix pattern matching for recursive ignoring. Closes issues #244. + + * Improve detection of relative imports in non-packages, as well as importing + missing modules with a relative import from a package. + diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py index 9e2af7e..b45cabc 100644 --- a/pylint/checkers/imports.py +++ b/pylint/checkers/imports.py @@ -33,6 +33,23 @@ from pylint.checkers import BaseChecker from pylint.checkers.utils import check_messages, node_ignores_exception +def _get_import_name(importnode, modname): + """Get a prepared module name from the given import node + + In the case of relative imports, this will return the + absolute qualified module name, which might be useful + for debugging. Otherwise, the initial module name + is returned unchanged. + """ + if isinstance(importnode, astroid.From): + if importnode.level: + root = importnode.root() + if isinstance(root, astroid.Module): + modname = root.relative_to_absolute_name( + modname, level=importnode.level) + return modname + + def get_first_import(node, context, name, base, level): """return the node where [base.]<name> is imported or None if not found """ @@ -280,11 +297,12 @@ given file (report RP0402 must not be disabled)'} try: return importnode.do_import_module(modname) except astroid.InferenceError as ex: + dotted_modname = _get_import_name(importnode, modname) if str(ex) != modname: - args = '%r (%s)' % (modname, ex) + args = '%r (%s)' % (dotted_modname, ex) else: - args = repr(modname) - + args = repr(dotted_modname) + for submodule in self._qualified_names(modname): if submodule in self._ignored_modules: return None diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index 3156f6f..2821283 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -1009,7 +1009,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' name_parts = node.modname.split('.') level = getattr(node, 'level', None) try: - module = node.root().import_module(name_parts[0], level=level) + module = node.do_import_module(name_parts[0]) except Exception: return module = self._check_module_attrs(node, module, name_parts[1:]) diff --git a/pylint/test/functional/import_error.py b/pylint/test/functional/import_error.py index f7a024d..b715377 100644 --- a/pylint/test/functional/import_error.py +++ b/pylint/test/functional/import_error.py @@ -32,3 +32,5 @@ try: import really_missing
except ImportError:
pass
+
+from .collections import missing # [import-error]
diff --git a/pylint/test/functional/import_error.txt b/pylint/test/functional/import_error.txt index 0602d2a..82ca0d4 100644 --- a/pylint/test/functional/import_error.txt +++ b/pylint/test/functional/import_error.txt @@ -1,2 +1,3 @@ -import-error:3::Unable to import 'totally_missing' -import-error:16::Unable to import 'maybe_missing_2' +import-error:3::"Unable to import 'totally_missing'" +import-error:16::"Unable to import 'maybe_missing_2'" +import-error:36::"Unable to import 'functional.collections'" diff --git a/pylint/test/functional/no_name_in_module.py b/pylint/test/functional/no_name_in_module.py index a59327b..47e8c5f 100644 --- a/pylint/test/functional/no_name_in_module.py +++ b/pylint/test/functional/no_name_in_module.py @@ -60,3 +60,7 @@ try: import collections.please_dont_emit except Exception: pass + +from .no_self_use import Super +from .no_self_use import lala # [no-name-in-module] +from .no_self_use.bla import lala1 # [no-name-in-module] diff --git a/pylint/test/functional/no_name_in_module.txt b/pylint/test/functional/no_name_in_module.txt index dd78c1b..aa26791 100644 --- a/pylint/test/functional/no_name_in_module.txt +++ b/pylint/test/functional/no_name_in_module.txt @@ -8,4 +8,6 @@ no-name-in-module:23::No name 'compiile' in module 're' no-name-in-module:23::No name 'findiiter' in module 're' pointless-statement:26::Statement seems to have no effect no-name-in-module:34::No name 'anything' in module 'collections' -no-name-in-module:44::No name 'indeed_missing' in module 'collections'
\ No newline at end of file +no-name-in-module:44::No name 'indeed_missing' in module 'collections' +no-name-in-module:65::No name 'lala' in module 'functional.no_self_use' +no-name-in-module:66::No name 'bla' in module 'functional.no_self_use'
\ No newline at end of file diff --git a/pylint/test/test_functional.py b/pylint/test/test_functional.py index ddf737d..e9d6a9a 100644 --- a/pylint/test/test_functional.py +++ b/pylint/test/test_functional.py @@ -1,5 +1,4 @@ """Functional full-module tests for PyLint.""" -from __future__ import unicode_literals import csv import collections import io diff --git a/pylint/test/test_regr.py b/pylint/test/test_regr.py index 34b43f6..94085c3 100644 --- a/pylint/test/test_regr.py +++ b/pylint/test/test_regr.py @@ -139,7 +139,7 @@ class NonRegrTC(unittest.TestCase): self.assertEqual(got, "") def test_no_context_file(self): - expected = "E: 5: No name 'missing' in module ''\n" + expected = "Unused import missing" linter.check(join(REGR_DATA, 'bad_package')) got = linter.reporter.finalize().strip() self.assertIn(expected, got) |