diff options
author | cpopa <devnull@localhost> | 2014-01-03 22:16:12 +0200 |
---|---|---|
committer | cpopa <devnull@localhost> | 2014-01-03 22:16:12 +0200 |
commit | 842ee1710db77e200b248f29f66df5707527e82f (patch) | |
tree | eddb92f9df49c27e4f017ac98a4a829fa5c6acde | |
parent | e099a5685de2fd625de831d060d0b4a91ed4481d (diff) | |
download | pylint-842ee1710db77e200b248f29f66df5707527e82f.tar.gz |
Add missing-submodule check for fixing issue #126.
-rw-r--r-- | checkers/imports.py | 4 | ||||
-rw-r--r-- | checkers/variables.py | 25 | ||||
-rw-r--r-- | test/regrtest_data/package_all/__init__.py | 3 | ||||
-rw-r--r-- | test/regrtest_data/package_all/notmissing.py | 2 | ||||
-rw-r--r-- | test/test_func.py | 5 | ||||
-rw-r--r-- | test/test_misc.py | 15 |
6 files changed, 47 insertions, 7 deletions
diff --git a/checkers/imports.py b/checkers/imports.py index b0a9872..b3cea23 100644 --- a/checkers/imports.py +++ b/checkers/imports.py @@ -149,6 +149,10 @@ MSGS = { 'misplaced-future', 'Python 2.5 and greater require __future__ import to be the \ first non docstring statement in the module.'), + 'W0407': ('Missing submodule: %s', + 'missing-submodule', + 'Used when trying to import a submodule from a package ' + 'and the submodule is missing.'), } class ImportsChecker(BaseChecker): diff --git a/checkers/variables.py b/checkers/variables.py index 90b7fe7..a0bf796 100644 --- a/checkers/variables.py +++ b/checkers/variables.py @@ -15,13 +15,15 @@ # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """variables checkers for Python code """ - +import os import sys from copy import copy import astroid from astroid import are_exclusive, builtin_lookup, AstroidBuildingException +from logilab.common.modutils import load_module_from_name + from pylint.interfaces import IAstroidChecker from pylint.checkers import BaseChecker from pylint.checkers.utils import (PYMETHODS, is_ancestor_name, is_builtin, @@ -192,7 +194,8 @@ builtins. Remember that you should avoid to define new builtins when possible.' # do not print Redefining builtin for additional builtins self.add_message('W0622', args=name, node=stmts[0]) - @check_messages('W0611', 'W0614', 'W0622', 'E0603', 'E0604') + @check_messages('W0611', 'W0614', 'W0622', 'E0603', 'E0604', + 'missing-submodule') def leave_module(self, node): """leave module: check globals """ @@ -217,7 +220,23 @@ builtins. Remember that you should avoid to define new builtins when possible.' del not_consumed[elt_name] continue if elt_name not in node.locals: - self.add_message('E0603', args=elt_name, node=elt) + if not node.package: + self.add_message('E0603', args=elt_name, node=elt) + else: + basename = os.path.splitext(node.file)[0] + if os.path.basename(basename) == '__init__': + name = node.name + "." + elt_name + try: + load_module_from_name(name) + except ImportError: + self.add_message('missing-submodule', + args=elt_name, + node=elt) + except SyntaxError as exc: + # don't yield an syntax-error warning, + # because it will be later yielded + # when the file will be checked + pass # don't check unused imports in __init__ files if not self.config.init_import and node.package: return diff --git a/test/regrtest_data/package_all/__init__.py b/test/regrtest_data/package_all/__init__.py new file mode 100644 index 0000000..a00d416 --- /dev/null +++ b/test/regrtest_data/package_all/__init__.py @@ -0,0 +1,3 @@ +""" Check for missing-submodule """
+__revision__ = 1
+__all__ = ['notmissing', 'missing']
diff --git a/test/regrtest_data/package_all/notmissing.py b/test/regrtest_data/package_all/notmissing.py new file mode 100644 index 0000000..7cf8543 --- /dev/null +++ b/test/regrtest_data/package_all/notmissing.py @@ -0,0 +1,2 @@ +""" empty """
+__revision__ = 1
diff --git a/test/test_func.py b/test/test_func.py index e8c746d..3b98209 100644 --- a/test/test_func.py +++ b/test/test_func.py @@ -58,12 +58,13 @@ class TestTests(testlib.TestCase): rest = ['I0001', # XXX : no use case for now : 'W0402', # deprecated module - 'W0403', # implicit relative import + 'W0403', # implicit relative import, + 'W0407', # tested in test_misc.py 'W0410', # __future__ import not first statement ] self.assertEqual(todo, rest) else: - self.assertEqual(todo, ['I0001']) + self.assertEqual(todo, ['I0001', 'W0407']) class LintBuiltinModuleTest(LintTestUsingModule): output = join(MSG_DIR, 'builtin_module.txt') diff --git a/test/test_misc.py b/test/test_misc.py index a2cba9b..b77510f 100644 --- a/test/test_misc.py +++ b/test/test_misc.py @@ -22,8 +22,12 @@ import contextlib from logilab.common.testlib import unittest_main from astroid import test_utils -from pylint.checkers import misc -from pylint.testutils import CheckerTestCase, Message +from pylint.checkers import misc, variables +from pylint.testutils import CheckerTestCase, Message, linter + +REGR_DATA = os.path.join(os.path.dirname(os.path.abspath(__file__)), + 'regrtest_data') +sys.path.insert(1, REGR_DATA) @contextlib.contextmanager def create_file_backed_module(code): @@ -66,6 +70,13 @@ class FixmeTest(CheckerTestCase): with self.assertNoMessages(): self.checker.process_module(module) +class MissingSubmoduleTest(CheckerTestCase): + CHECKER_CLASS = variables.VariablesChecker + + def test_package_all(self): + linter.check(os.path.join(REGR_DATA, 'package_all')) + got = linter.reporter.finalize().strip() + self.assertEqual(got, 'W: 3: Missing submodule: missing') if __name__ == '__main__': unittest_main() |