summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Shao <p.yushao2@gmail.com>2021-11-18 18:26:41 +0800
committerYu Shao, Pang <p.yushao2@gmail.com>2021-11-29 00:26:16 +0800
commit554801a89de6cf88382fc02290fdebb8fa0c8f04 (patch)
tree78099d8f255976bc73f2d83b004c7c37f851fecd
parent2b3ed7e32d96653e82509e8159da28375c5102a6 (diff)
downloadpylint-git-554801a89de6cf88382fc02290fdebb8fa0c8f04.tar.gz
added util functions and changed code according to pr comments
-rw-r--r--pylint/checkers/refactoring/recommendation_checker.py31
-rw-r--r--pylint/checkers/utils.py14
-rw-r--r--tests/functional/c/consider/consider_iterating_dictionary.py10
-rw-r--r--tests/functional/c/consider/consider_iterating_dictionary.txt8
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