summaryrefslogtreecommitdiff
path: root/pylint/extensions
diff options
context:
space:
mode:
authorDani Alcala <112832187+clavedeluna@users.noreply.github.com>2022-10-31 05:34:02 -0300
committerGitHub <noreply@github.com>2022-10-31 08:34:02 +0000
commit004fc7483ff6cd99ddd19dd6a572011797b138b0 (patch)
tree2dd9df64e75ce456ad7e384eb9db6fe88165b29e /pylint/extensions
parent5c7f98099c719038fa07eba61f288c0a7cc48f92 (diff)
downloadpylint-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.py77
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))