diff options
author | Dani Alcala <112832187+clavedeluna@users.noreply.github.com> | 2022-10-31 05:34:02 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-31 08:34:02 +0000 |
commit | 004fc7483ff6cd99ddd19dd6a572011797b138b0 (patch) | |
tree | 2dd9df64e75ce456ad7e384eb9db6fe88165b29e /pylint/extensions | |
parent | 5c7f98099c719038fa07eba61f288c0a7cc48f92 (diff) | |
download | pylint-git-004fc7483ff6cd99ddd19dd6a572011797b138b0.tar.gz |
Add `bad-dunder-name` extension checker (#7642)
With a 'good-dunder-name' option
Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
Diffstat (limited to 'pylint/extensions')
-rw-r--r-- | pylint/extensions/dunder.py | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/pylint/extensions/dunder.py b/pylint/extensions/dunder.py new file mode 100644 index 000000000..e0e9af316 --- /dev/null +++ b/pylint/extensions/dunder.py @@ -0,0 +1,77 @@ +# 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 + +from __future__ import annotations + +from typing import TYPE_CHECKING + +from astroid import nodes + +from pylint.checkers import BaseChecker +from pylint.constants import DUNDER_METHODS, DUNDER_PROPERTIES, EXTRA_DUNDER_METHODS +from pylint.interfaces import HIGH + +if TYPE_CHECKING: + from pylint.lint import PyLinter + + +class DunderChecker(BaseChecker): + """Checks related to dunder methods.""" + + name = "dunder" + priority = -1 + msgs = { + "W3201": ( + "Bad or misspelled dunder method name %s.", + "bad-dunder-name", + "Used when a dunder method is misspelled or defined with a name " + "not within the predefined list of dunder names.", + ), + } + options = ( + ( + "good-dunder-names", + { + "default": [], + "type": "csv", + "metavar": "<comma-separated names>", + "help": "Good dunder names which should always be accepted.", + }, + ), + ) + + def open(self) -> None: + self._dunder_methods = ( + EXTRA_DUNDER_METHODS + + DUNDER_PROPERTIES + + self.linter.config.good_dunder_names + ) + for since_vers, dunder_methods in DUNDER_METHODS.items(): + if since_vers <= self.linter.config.py_version: + self._dunder_methods.extend(list(dunder_methods.keys())) + + def visit_functiondef(self, node: nodes.FunctionDef) -> None: + """Check if known dunder method is misspelled or dunder name is not one + of the pre-defined names. + """ + # ignore module-level functions + if not node.is_method(): + return + + # Detect something that could be a bad dunder method + if ( + node.name.startswith("_") + and node.name.endswith("_") + and node.name not in self._dunder_methods + ): + self.add_message( + "bad-dunder-name", + node=node, + args=(node.name), + confidence=HIGH, + ) + + +def register(linter: PyLinter) -> None: + linter.register_checker(DunderChecker(linter)) |