summaryrefslogtreecommitdiff
path: root/pylint
diff options
context:
space:
mode:
authorDani Alcala <112832187+clavedeluna@users.noreply.github.com>2022-11-23 14:11:20 -0300
committerGitHub <noreply@github.com>2022-11-23 18:11:20 +0100
commitf7d681b5a79e5781ab8072fe64459b199955a1f6 (patch)
tree57e5c051cf7384ae01d50007386b73b1dab616e1 /pylint
parented404d361f24f068693d59619961e575810af3d9 (diff)
downloadpylint-git-f7d681b5a79e5781ab8072fe64459b199955a1f6.tar.gz
Add a new check `dict-init-mutate` (#7794)
Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
Diffstat (limited to 'pylint')
-rw-r--r--pylint/extensions/dict_init_mutate.py66
1 files changed, 66 insertions, 0 deletions
diff --git a/pylint/extensions/dict_init_mutate.py b/pylint/extensions/dict_init_mutate.py
new file mode 100644
index 000000000..fb4c83647
--- /dev/null
+++ b/pylint/extensions/dict_init_mutate.py
@@ -0,0 +1,66 @@
+# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
+# Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt
+
+"""Check for use of dictionary mutation after initialization."""
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from astroid import nodes
+
+from pylint.checkers import BaseChecker
+from pylint.checkers.utils import only_required_for_messages
+from pylint.interfaces import HIGH
+
+if TYPE_CHECKING:
+ from pylint.lint.pylinter import PyLinter
+
+
+class DictInitMutateChecker(BaseChecker):
+ name = "dict-init-mutate"
+ msgs = {
+ "C3401": (
+ "Declare all known key/values when initializing the dictionary.",
+ "dict-init-mutate",
+ "Dictionaries can be initialized with a single statement "
+ "using dictionary literal syntax.",
+ )
+ }
+
+ @only_required_for_messages("dict-init-mutate")
+ def visit_assign(self, node: nodes.Assign) -> None:
+ """
+ Detect dictionary mutation immediately after initialization.
+
+ At this time, detecting nested mutation is not supported.
+ """
+ if not isinstance(node.value, nodes.Dict):
+ return
+
+ dict_name = node.targets[0]
+ if len(node.targets) != 1 or not isinstance(dict_name, nodes.AssignName):
+ return
+
+ first_sibling = node.next_sibling()
+ if (
+ not first_sibling
+ or not isinstance(first_sibling, nodes.Assign)
+ or len(first_sibling.targets) != 1
+ ):
+ return
+
+ sibling_target = first_sibling.targets[0]
+ if not isinstance(sibling_target, nodes.Subscript):
+ return
+
+ sibling_name = sibling_target.value
+ if not isinstance(sibling_name, nodes.Name):
+ return
+
+ if sibling_name.name == dict_name.name:
+ self.add_message("dict-init-mutate", node=node, confidence=HIGH)
+
+
+def register(linter: PyLinter) -> None:
+ linter.register_checker(DictInitMutateChecker(linter))