summaryrefslogtreecommitdiff
path: root/pylint/checkers/refactoring/refactoring_checker.py
diff options
context:
space:
mode:
authorRobert Hofer <hofrob@protonmail.com>2022-10-30 16:26:07 +0100
committerDaniƫl van Noord <13665637+DanielNoord@users.noreply.github.com>2022-11-09 20:39:00 +0100
commit0507ee37f45cb3c9dcaf64036dd1b7f3c88ae690 (patch)
tree7ec3b2adc6e9841ec73d7f4aa5ac58ce36e24808 /pylint/checkers/refactoring/refactoring_checker.py
parent5ae5842fa02021e086d66218d326c708e6433318 (diff)
downloadpylint-git-0507ee37f45cb3c9dcaf64036dd1b7f3c88ae690.tar.gz
Add R1737 use-dict-literal-without-kwargs
Diffstat (limited to 'pylint/checkers/refactoring/refactoring_checker.py')
-rw-r--r--pylint/checkers/refactoring/refactoring_checker.py48
1 files changed, 40 insertions, 8 deletions
diff --git a/pylint/checkers/refactoring/refactoring_checker.py b/pylint/checkers/refactoring/refactoring_checker.py
index 34856749f..df3c3bccc 100644
--- a/pylint/checkers/refactoring/refactoring_checker.py
+++ b/pylint/checkers/refactoring/refactoring_checker.py
@@ -464,9 +464,9 @@ class RefactoringChecker(checkers.BaseTokenChecker):
"The literal is faster as it avoids an additional function call.",
),
"R1735": (
- "Consider using {} instead of dict()",
+ "Consider using '%s' instead of a call to 'dict'.",
"use-dict-literal",
- "Emitted when using dict() to create an empty dictionary instead of the literal {}. "
+ "Emitted when using dict() to create a dictionary instead of a literal '{ ... }'. "
"The literal is faster as it avoids an additional function call.",
),
"R1736": (
@@ -1074,7 +1074,8 @@ class RefactoringChecker(checkers.BaseTokenChecker):
self._check_super_with_arguments(node)
self._check_consider_using_generator(node)
self._check_consider_using_with(node)
- self._check_use_list_or_dict_literal(node)
+ self._check_use_list_literal(node)
+ self._check_use_dict_literal(node)
@staticmethod
def _has_exit_in_scope(scope: nodes.LocalsDictNodeNG) -> bool:
@@ -1590,15 +1591,46 @@ class RefactoringChecker(checkers.BaseTokenChecker):
if could_be_used_in_with and not _will_be_released_automatically(node):
self.add_message("consider-using-with", node=node)
- def _check_use_list_or_dict_literal(self, node: nodes.Call) -> None:
- """Check if empty list or dict is created by using the literal [] or {}."""
- if node.as_string() in {"list()", "dict()"}:
+ def _check_use_list_literal(self, node: nodes.Call) -> None:
+ """Check if empty list is created by using the literal []."""
+ if node.as_string() == "list()":
inferred = utils.safe_infer(node.func)
if isinstance(inferred, nodes.ClassDef) and not node.args:
if inferred.qname() == "builtins.list":
self.add_message("use-list-literal", node=node)
- elif inferred.qname() == "builtins.dict" and not node.keywords:
- self.add_message("use-dict-literal", node=node)
+
+ def _check_use_dict_literal(self, node: nodes.Call) -> None:
+ """Check if dict is created by using the literal {}."""
+ if not isinstance(node.func, astroid.Name) or node.func.name != "dict":
+ return
+ inferred = utils.safe_infer(node.func)
+ if (
+ isinstance(inferred, nodes.ClassDef)
+ and inferred.qname() == "builtins.dict"
+ and not node.args
+ ):
+ self.add_message(
+ "use-dict-literal",
+ args=(self._dict_literal_suggestion(node),),
+ node=node,
+ confidence=INFERENCE,
+ )
+
+ @staticmethod
+ def _dict_literal_suggestion(node: nodes.Call) -> str:
+ """Return a suggestion of reasonable length."""
+ elements: list[str] = []
+ for keyword in node.keywords:
+ if len(", ".join(elements)) >= 64:
+ break
+ if keyword not in node.kwargs:
+ elements.append(f'"{keyword.arg}": {keyword.value.as_string()}')
+ for keyword in node.kwargs:
+ if len(", ".join(elements)) >= 64:
+ break
+ elements.append(f"**{keyword.value.as_string()}")
+ suggestion = ", ".join(elements)
+ return f"{{{suggestion}{', ... ' if len(suggestion) > 64 else ''}}}"
def _check_consider_using_join(self, aug_assign: nodes.AugAssign) -> None:
"""We start with the augmented assignment and work our way upwards.