diff options
author | Robert Hofer <hofrob@protonmail.com> | 2022-10-30 16:26:07 +0100 |
---|---|---|
committer | Daniƫl van Noord <13665637+DanielNoord@users.noreply.github.com> | 2022-11-09 20:39:00 +0100 |
commit | 0507ee37f45cb3c9dcaf64036dd1b7f3c88ae690 (patch) | |
tree | 7ec3b2adc6e9841ec73d7f4aa5ac58ce36e24808 /pylint/checkers/refactoring/refactoring_checker.py | |
parent | 5ae5842fa02021e086d66218d326c708e6433318 (diff) | |
download | pylint-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.py | 48 |
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. |