From d07a5fd7e25f9517c8100f1d77dd5640eb3755fa Mon Sep 17 00:00:00 2001 From: Claudiu Popa Date: Mon, 17 Nov 2014 20:39:29 +0200 Subject: Add 'implicit-map-evaluation' to Python 3 porting checker. This warning is emitted when encountering the use of map builtin, without explicit evaluation, as in "map(func, args)" on a single line. This behaviour is removed in Python 3, where map is a generator and must be explicitly evaluated. --- ChangeLog | 3 +++ checkers/python3.py | 16 ++++++++++++++++ test/unittest_checker_python3.py | 10 ++++++++++ 3 files changed, 29 insertions(+) diff --git a/ChangeLog b/ChangeLog index a877b66..cc970e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -182,6 +182,9 @@ ChangeLog for Pylint * Add 'old-octal-literal' to Python 3 porting checker, emitted when encountering octals with the old syntax. + + * Add 'implicit-map-evaluation' to Python 3 porting checker, emitted + when encountering the use of map builtin, without explicit evaluation. diff --git a/checkers/python3.py b/checkers/python3.py index e428a60..472e328 100644 --- a/checkers/python3.py +++ b/checkers/python3.py @@ -237,6 +237,14 @@ class Python3Checker(checkers.BaseChecker): 'Used when a __cmp__ method is defined ' '(method is not used by Python 3)', {'maxversion': (3, 0)}), + 'W1631': ('map is used as implicitly evaluated call', + 'implicit-map-evaluation', + 'Used when the map builtin is used as implicitly ' + 'evaluated call, as in "map(func, args)" on a single line. ' + 'This behaviour will not work in Python 3, where ' + 'map is a generator and must be evaluated. ' + 'Prefer a for-loop as alternative.', + {'maxversion': (3, 0)}), } _missing_builtins = frozenset([ @@ -285,6 +293,14 @@ class Python3Checker(checkers.BaseChecker): if isinstance(arg, astroid.Tuple): self.add_message('parameter-unpacking', node=arg) + @utils.check_messages('implicit-map-evaluation') + def visit_discard(self, node): + if (isinstance(node.value, astroid.CallFunc) and + node.value.func.name == 'map'): + module = node.value.func.lookup('map')[0] + if getattr(module, 'name', None) == '__builtin__': + self.add_message('implicit-map-evaluation', node=node) + def visit_name(self, node): """Detect when a built-in that is missing in Python 3 is referenced.""" found_node = node.lookup(node.name)[0] diff --git a/test/unittest_checker_python3.py b/test/unittest_checker_python3.py index b57fc96..f7eead9 100644 --- a/test/unittest_checker_python3.py +++ b/test/unittest_checker_python3.py @@ -200,6 +200,16 @@ class Python3CheckerTest(testutils.CheckerTestCase): with self.assertAddsMessages(message): self.checker.visit_callfunc(node) + @python2_only + def test_implicit_map_evaluation(self): + node = test_utils.extract_node('map(str, [1, 2, 3])') + discard = node.parent + message = testutils.Message('implicit-map-evaluation', node=discard) + with self.assertAddsMessages(message): + # Use node.parent because extract_node returns the value + # of a discard node, not the discard itself. + self.checker.visit_discard(discard) + def test_not_next_method(self): arg_node = test_utils.extract_node('x.next(x) #@') stararg_node = test_utils.extract_node('x.next(*x) #@') -- cgit v1.2.1