diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2016-03-25 14:36:31 +0000 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2016-03-25 14:36:31 +0000 |
commit | ad7c2cd38f7213edd1ff37aaead86d5ae8390df4 (patch) | |
tree | 476baae95554a44ca82c92be355af795c559ecbc /pylint | |
parent | 62a15879d84651490e00a0dfe97d20c2d9818e50 (diff) | |
download | pylint-git-ad7c2cd38f7213edd1ff37aaead86d5ae8390df4.tar.gz |
Add a new option, 'redefining-builtins-modules'.
The option can be used for controlling the modules
which can redefine builtins, such as six.moves and future.builtins.
Close #464.
Diffstat (limited to 'pylint')
-rw-r--r-- | pylint/checkers/variables.py | 19 | ||||
-rw-r--r-- | pylint/test/unittest_checker_variables.py | 34 |
2 files changed, 50 insertions, 3 deletions
diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index db03e3a9d..ee2a55792 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -339,7 +339,13 @@ class VariablesChecker(BaseChecker): 'help' : 'List of strings which can identify a callback ' 'function by name. A callback name must start or ' 'end with one of those strings.'} - ) + ), + ("redefining-builtins-modules", + {'default': ('six.moves', 'future.builtins'), 'type': 'csv', + 'metavar': '<comma separated list>', + 'help': 'List of qualified module names which can have objects ' + 'that can redefine builtins.'} + ), ) def __init__(self, linter=None): BaseChecker.__init__(self, linter) @@ -353,7 +359,8 @@ class VariablesChecker(BaseChecker): self._to_consume = [(copy(node.locals), {}, 'module')] for name, stmts in six.iteritems(node.locals): if is_builtin(name) and not is_inside_except(stmts[0]): - # do not print Redefining builtin for additional builtins + if self._should_ignore_redefined_builtin(stmts[0]): + continue self.add_message('redefined-builtin', args=name, node=stmts[0]) @check_messages('unused-import', 'unused-wildcard-import', @@ -552,7 +559,8 @@ class VariablesChecker(BaseChecker): if not dummy_rgx.match(name): self.add_message('redefined-outer-name', args=(name, line), node=stmt) - elif is_builtin(name): + + elif is_builtin(name) and not self._should_ignore_redefined_builtin(stmt): # do not print Redefining builtin for additional builtins self.add_message('redefined-builtin', args=name, node=stmt) @@ -737,6 +745,11 @@ class VariablesChecker(BaseChecker): and assign.statement() is not node.statement()): self.add_message('undefined-loop-variable', args=name, node=node) + def _should_ignore_redefined_builtin(self, stmt): + if not isinstance(stmt, astroid.ImportFrom): + return False + return stmt.modname in self.config.redefining_builtins_modules + @check_messages('redefine-in-handler') def visit_excepthandler(self, node): for name in get_all_elements(node.name): diff --git a/pylint/test/unittest_checker_variables.py b/pylint/test/unittest_checker_variables.py index e42dffcfd..141a34071 100644 --- a/pylint/test/unittest_checker_variables.py +++ b/pylint/test/unittest_checker_variables.py @@ -89,6 +89,40 @@ class VariablesCheckerTC(CheckerTestCase): self.checker.visit_functiondef(node) self.checker.leave_functiondef(node) + def test_redefined_builtin_ignored(self): + node = astroid.parse(''' + from future.builtins import open + ''') + with self.assertNoMessages(): + self.checker.visit_module(node) + + @set_config(redefining_builtins_modules=('os',)) + def test_redefined_builtin_custom_modules(self): + node = astroid.parse(''' + from os import open + ''') + with self.assertNoMessages(): + self.checker.visit_module(node) + + @set_config(redefining_builtins_modules=('os',)) + def test_redefined_builtin_modname_not_ignored(self): + node = astroid.parse(''' + from future.builtins import open + ''') + with self.assertAddsMessages( + Message('redefined-builtin', node=node.body[0], args='open')): + self.checker.visit_module(node) + + @set_config(redefining_builtins_modules=('os',)) + def test_redefined_builtin_in_function(self): + node = test_utils.extract_node(''' + def test(): + from os import open + ''') + with self.assertNoMessages(): + self.checker.visit_module(node.root()) + self.checker.visit_functiondef(node) + class MissingSubmoduleTest(CheckerTestCase): CHECKER_CLASS = variables.VariablesChecker |