diff --git a/doc/whatsnew/2/2.15/index.rst b/doc/whatsnew/2/2.15/index.rst index 6a285fe028..5d718f12c7 100644 --- a/doc/whatsnew/2/2.15/index.rst +++ b/doc/whatsnew/2/2.15/index.rst @@ -15,7 +15,6 @@ Summary -- Release highlights New checkers ============ - Removed checkers ================ @@ -23,6 +22,10 @@ Removed checkers Extensions ========== +* ``NoDictSubscriptChecker`` + + * Added optional extension ``no-dict-subscript`` to emit messages when the ``[]`` operator is used + to access a dictionary value. False positives fixed ===================== diff --git a/pylint/extensions/dictionary_subscript.py b/pylint/extensions/dictionary_subscript.py new file mode 100644 index 0000000000..7fb5e79b27 --- /dev/null +++ b/pylint/extensions/dictionary_subscript.py @@ -0,0 +1,31 @@ +# 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 dictionary read-access via subscript.""" + +from astroid import Assign, Dict, nodes + +from pylint.checkers import BaseChecker, utils +from pylint.lint import PyLinter + + +class NoDictSubscriptChecker(BaseChecker): + name = "no-dict-subscript" + msgs = { + "R5701": ( + "Using dict operator [], consider using get() instead", + "dict-subscript", + "Used to warn when subscripting a dictionary instead of using the get() function", + ), + } + + def visit_subscript(self, node: nodes.Subscript) -> None: + if isinstance(utils.safe_infer(node.value), Dict) and not isinstance( + node.parent, Assign + ): + self.add_message("dict-subscript", node=node) + + +def register(linter: PyLinter) -> None: + linter.register_checker(NoDictSubscriptChecker(linter)) diff --git a/tests/functional/ext/check_dictionary_subscript/check_dictionary_subscript.py b/tests/functional/ext/check_dictionary_subscript/check_dictionary_subscript.py new file mode 100644 index 0000000000..7ce034895b --- /dev/null +++ b/tests/functional/ext/check_dictionary_subscript/check_dictionary_subscript.py @@ -0,0 +1,8 @@ +"""Checks the use of dictionary subscripts""" + +mydict = {"foo": 3} + +print(mydict["foo"]) +print(mydict.get("foo")) + +mydict["foo"] = 4 diff --git a/tests/functional/ext/check_dictionary_subscript/check_dictionary_subscript.rc b/tests/functional/ext/check_dictionary_subscript/check_dictionary_subscript.rc new file mode 100644 index 0000000000..3bd5028778 --- /dev/null +++ b/tests/functional/ext/check_dictionary_subscript/check_dictionary_subscript.rc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins=pylint.extensions.dictionary_subscript, diff --git a/tests/functional/ext/check_dictionary_subscript/check_dictionary_subscript.txt b/tests/functional/ext/check_dictionary_subscript/check_dictionary_subscript.txt new file mode 100644 index 0000000000..a032e1a152 --- /dev/null +++ b/tests/functional/ext/check_dictionary_subscript/check_dictionary_subscript.txt @@ -0,0 +1 @@ +dict-subscript:5:6:5:19::"Using dict operator [], consider using get() instead":UNDEFINED