diff options
author | Yu Shao <p.yushao2@gmail.com> | 2021-11-18 18:26:41 +0800 |
---|---|---|
committer | Yu Shao, Pang <p.yushao2@gmail.com> | 2021-11-29 00:26:16 +0800 |
commit | 554801a89de6cf88382fc02290fdebb8fa0c8f04 (patch) | |
tree | 78099d8f255976bc73f2d83b004c7c37f851fecd | |
parent | 2b3ed7e32d96653e82509e8159da28375c5102a6 (diff) | |
download | pylint-git-554801a89de6cf88382fc02290fdebb8fa0c8f04.tar.gz |
added util functions and changed code according to pr comments
-rw-r--r-- | pylint/checkers/refactoring/recommendation_checker.py | 31 | ||||
-rw-r--r-- | pylint/checkers/utils.py | 14 | ||||
-rw-r--r-- | tests/functional/c/consider/consider_iterating_dictionary.py | 10 | ||||
-rw-r--r-- | tests/functional/c/consider/consider_iterating_dictionary.txt | 8 |
4 files changed, 40 insertions, 23 deletions
diff --git a/pylint/checkers/refactoring/recommendation_checker.py b/pylint/checkers/refactoring/recommendation_checker.py index a767794fa..1c484bb59 100644 --- a/pylint/checkers/refactoring/recommendation_checker.py +++ b/pylint/checkers/refactoring/recommendation_checker.py @@ -83,23 +83,22 @@ class RecommendationChecker(checkers.BaseChecker): return if node.func.attrname != "keys": return - inferred = utils.safe_infer(node.func) - if not isinstance(inferred, astroid.BoundMethod) or not isinstance( - inferred.bound, nodes.Dict - ): - return - - if isinstance(node.parent, (nodes.For, nodes.Comprehension)): - self.add_message("consider-iterating-dictionary", node=node) - - while not isinstance(node.parent, (nodes.Compare, nodes.Module)): - node = node.parent - - if isinstance(node.parent, nodes.Compare) and any( - op - for op, comparator in node.parent.ops - if op in ["in", "not in"] and comparator is node + comp_ancestor = utils.get_node_first_ancestor_of_type(node, nodes.Compare) + if ( + isinstance(node.parent, (nodes.For, nodes.Comprehension)) + or isinstance(comp_ancestor, nodes.Compare) + and any( + op + for op, comparator in comp_ancestor.ops + if op in ["in", "not in"] + and (comparator in node.node_ancestors() or comparator is node) + ) ): + inferred = utils.safe_infer(node.func) + if not isinstance(inferred, astroid.BoundMethod) or not isinstance( + inferred.bound, nodes.Dict + ): + return self.add_message("consider-iterating-dictionary", node=node) def _check_use_maxsplit_arg(self, node: nodes.Call) -> None: diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py index c7f2cec92..9b0fc7ed4 100644 --- a/pylint/checkers/utils.py +++ b/pylint/checkers/utils.py @@ -75,6 +75,7 @@ from typing import ( Set, Tuple, Type, + TypeVar, Union, ) @@ -1690,3 +1691,16 @@ def returns_bool(node: nodes.NodeNG) -> bool: and isinstance(node.value, nodes.Const) and node.value.value in {True, False} ) + + +T_Node = TypeVar("T_Node", bound=nodes.NodeNG) + + +def get_node_first_ancestor_of_type( + node: nodes.NodeNG, ancestor_type: Tuple[Type[T_Node]] +) -> Optional[T_Node]: + """Return the first parent node that is any of the provided types (or None)""" + for ancestor in node.node_ancestors(): + if isinstance(ancestor, ancestor_type): + return ancestor + return None diff --git a/tests/functional/c/consider/consider_iterating_dictionary.py b/tests/functional/c/consider/consider_iterating_dictionary.py index 8392e2837..70a5d3187 100644 --- a/tests/functional/c/consider/consider_iterating_dictionary.py +++ b/tests/functional/c/consider/consider_iterating_dictionary.py @@ -85,10 +85,10 @@ class AClass: class InnerClass: def another_function(self): def inner_function(): - metadata = {} - print("a" not in list(metadata.keys())) # [consider-iterating-dictionary] - print("a" not in metadata.keys()) # [consider-iterating-dictionary] - print("a" in list(metadata.keys())) # [consider-iterating-dictionary] - print("a" in metadata.keys()) # [consider-iterating-dictionary] + another_metadata = {} + print("a" not in list(another_metadata.keys())) # [consider-iterating-dictionary] + print("a" not in another_metadata.keys()) # [consider-iterating-dictionary] + print("a" in list(another_metadata.keys())) # [consider-iterating-dictionary] + print("a" in another_metadata.keys()) # [consider-iterating-dictionary] return inner_function() return InnerClass().another_function() diff --git a/tests/functional/c/consider/consider_iterating_dictionary.txt b/tests/functional/c/consider/consider_iterating_dictionary.txt index c2187aed7..676480a71 100644 --- a/tests/functional/c/consider/consider_iterating_dictionary.txt +++ b/tests/functional/c/consider/consider_iterating_dictionary.txt @@ -16,7 +16,11 @@ consider-iterating-dictionary:40:60:None:None::Consider iterating the dictionary consider-iterating-dictionary:43:8:None:None::Consider iterating the dictionary directly instead of calling .keys():UNDEFINED consider-iterating-dictionary:45:8:None:None::Consider iterating the dictionary directly instead of calling .keys():UNDEFINED consider-iterating-dictionary:65:11:None:None::Consider iterating the dictionary directly instead of calling .keys():UNDEFINED -consider-iterating-dictionary:73:14:None:None::Consider iterating the dictionary directly instead of calling .keys():UNDEFINED +consider-iterating-dictionary:73:19:None:None::Consider iterating the dictionary directly instead of calling .keys():UNDEFINED consider-iterating-dictionary:75:14:None:None::Consider iterating the dictionary directly instead of calling .keys():UNDEFINED -consider-iterating-dictionary:77:10:None:None::Consider iterating the dictionary directly instead of calling .keys():UNDEFINED +consider-iterating-dictionary:77:15:None:None::Consider iterating the dictionary directly instead of calling .keys():UNDEFINED consider-iterating-dictionary:79:10:None:None::Consider iterating the dictionary directly instead of calling .keys():UNDEFINED +consider-iterating-dictionary:89:42:None:None:AClass.a_function.InnerClass.another_function.inner_function:Consider iterating the dictionary directly instead of calling .keys():UNDEFINED +consider-iterating-dictionary:90:37:None:None:AClass.a_function.InnerClass.another_function.inner_function:Consider iterating the dictionary directly instead of calling .keys():UNDEFINED +consider-iterating-dictionary:91:38:None:None:AClass.a_function.InnerClass.another_function.inner_function:Consider iterating the dictionary directly instead of calling .keys():UNDEFINED +consider-iterating-dictionary:92:33:None:None:AClass.a_function.InnerClass.another_function.inner_function:Consider iterating the dictionary directly instead of calling .keys():UNDEFINED |