diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2018-04-18 08:34:21 +0200 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2018-04-18 08:34:21 +0200 |
commit | 37129d948d336e9a617520a91393646f7c7aff6e (patch) | |
tree | 27d966261dd2e26a5fe86854330a7f45d833c188 | |
parent | 50e28f28a3785cc9fa6cdb6efec1daf7f38f09ed (diff) | |
download | pylint-git-37129d948d336e9a617520a91393646f7c7aff6e.tar.gz |
defaultdict and subclasses of dict are now handled for dict-iter-* checks
Close #2005
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | doc/whatsnew/1.9.rst | 11 | ||||
-rw-r--r-- | pylint/checkers/python3.py | 11 | ||||
-rw-r--r-- | pylint/test/unittest_checker_python3.py | 32 |
4 files changed, 48 insertions, 10 deletions
@@ -7,6 +7,10 @@ What's New in Pylint 1.9.0? Release date: + * defaultdict and subclasses of dict are now handled for dict-iter-* checks + + Close #2005 + * Added a new Python 2/3 check for invalid raise syntax. Close #1937 diff --git a/doc/whatsnew/1.9.rst b/doc/whatsnew/1.9.rst index 954a22f20..e71a277d8 100644 --- a/doc/whatsnew/1.9.rst +++ b/doc/whatsnew/1.9.rst @@ -47,3 +47,14 @@ New checkers Other Changes ============= + +* `defaultdict` and subclasses of `dict` are now handled for `dict-iter-*` checks. That + means that the following code will now emit warnings for when `iteritems` and friends + are accessed: + + .. code-block:: python + + some_dict = defaultdict(list) + ... + some_dict.iterkeys() + diff --git a/pylint/checkers/python3.py b/pylint/checkers/python3.py index 1556bf0da..315d2d7da 100644 --- a/pylint/checkers/python3.py +++ b/pylint/checkers/python3.py @@ -62,8 +62,15 @@ def _check_dict_node(node): inferred_types.add(inferred_node) except astroid.InferenceError: pass - return (not inferred_types - or any(isinstance(x, astroid.Dict) for x in inferred_types)) + + if not inferred_types: + return True + for elem in inferred_types: + if isinstance(elem, astroid.Dict): + return True + if isinstance(elem, astroid.Instance) and 'dict' in elem.basenames: + return True + return False def _is_builtin(node): diff --git a/pylint/test/unittest_checker_python3.py b/pylint/test/unittest_checker_python3.py index 98c56e89e..76b8adff7 100644 --- a/pylint/test/unittest_checker_python3.py +++ b/pylint/test/unittest_checker_python3.py @@ -384,10 +384,18 @@ class TestPython3Checker(testutils.CheckerTestCase): self.checker.visit_call(node) def test_dict_iter_method_on_dict(self): - node = astroid.extract_node('{}.iterkeys()') - message = testutils.Message('dict-iter-method', node=node) - with self.assertAddsMessages(message): - self.checker.visit_call(node) + nodes = astroid.extract_node(''' + from collections import defaultdict + {}.iterkeys() #@ + defaultdict(list).iterkeys() #@ + class Someclass(dict): + pass + Someclass().iterkeys() #@ + ''') + for node in nodes: + message = testutils.Message('dict-iter-method', node=node) + with self.assertAddsMessages(message): + self.checker.visit_call(node) def test_dict_not_iter_method(self): arg_node = astroid.extract_node('x.iterkeys(x) #@') @@ -406,10 +414,18 @@ class TestPython3Checker(testutils.CheckerTestCase): self.checker.visit_call(node) def test_dict_view_method_on_dict(self): - node = astroid.extract_node('{}.viewkeys()') - message = testutils.Message('dict-view-method', node=node) - with self.assertAddsMessages(message): - self.checker.visit_call(node) + nodes = astroid.extract_node(''' + from collections import defaultdict + {}.viewkeys() #@ + defaultdict(list).viewkeys() #@ + class Someclass(dict): + pass + Someclass().viewkeys() #@ + ''') + for node in nodes: + message = testutils.Message('dict-view-method', node=node) + with self.assertAddsMessages(message): + self.checker.visit_call(node) def test_dict_not_view_method(self): arg_node = astroid.extract_node('x.viewkeys(x) #@') |