summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Sassoulas <pierre.sassoulas@gmail.com>2022-03-08 11:01:40 +0100
committerGitHub <noreply@github.com>2022-03-08 11:01:40 +0100
commit444e9e1a6e67dba23d050e638ae027ee44414a08 (patch)
treefb4eb437a85546e9839927f5d5db3968387d60ca
parent4649153dae5d55b3ac01787a7a61b25624077526 (diff)
downloadpylint-git-444e9e1a6e67dba23d050e638ae027ee44414a08.tar.gz
Restore the useful part of the python3 checker (#5843)
* Reinstate checks from the python3 checker that are still useful for py3 Closes #5025 Co-authored-by: Daniƫl van Noord <13665637+DanielNoord@users.noreply.github.com>
-rw-r--r--ChangeLog6
-rw-r--r--doc/whatsnew/2.13.rst6
-rw-r--r--pylint/constants.py5
-rw-r--r--pylint/extensions/__init__.py2
-rw-r--r--pylint/extensions/code_style.py2
-rw-r--r--pylint/extensions/eq_without_hash.py39
-rw-r--r--tests/functional/ext/eq_without_hash/eq_without_hash.py11
-rw-r--r--tests/functional/ext/eq_without_hash/eq_without_hash.rc2
-rw-r--r--tests/functional/ext/eq_without_hash/eq_without_hash.txt1
9 files changed, 68 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 76c92a0b7..51bc84fc5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -53,6 +53,12 @@ Release date: TBA
Closes #5486
+* Reinstated checks from the python3 checker that are still useful for python 3
+ (``eq-without-hash``). This is now in the ``pylint.extensions.eq_without_hash`` optional
+ extension.
+
+ Closes #5025
+
* Added several checkers to deal with unicode security issues
(see `Trojan Sources <https://trojansource.codes/>`_ and
`PEP 672 <https://www.python.org/dev/peps/pep-0672/>`_ for details) that also
diff --git a/doc/whatsnew/2.13.rst b/doc/whatsnew/2.13.rst
index e7fc63b88..6fe17d995 100644
--- a/doc/whatsnew/2.13.rst
+++ b/doc/whatsnew/2.13.rst
@@ -110,6 +110,12 @@ Other Changes
Closes #352
+* Reinstated checks from the python3 checker that are still useful for python 3
+ (``eq-without-hash``). This is now in the ``pylint.extensions.eq_without_hash`` optional
+ extension.
+
+ Closes #5025
+
* Fix false-negative for ``assignment-from-none`` checker with list.sort() method.
Closes #5722
diff --git a/pylint/constants.py b/pylint/constants.py
index c3b94863d..1a06ea832 100644
--- a/pylint/constants.py
+++ b/pylint/constants.py
@@ -80,9 +80,7 @@ class DeletedMessage(NamedTuple):
old_names: List[Tuple[str, str]] = []
-DELETED_MSGID_PREFIXES = [
- 16, # the PY3K+ checker, see https://github.com/PyCQA/pylint/pull/4942
-]
+DELETED_MSGID_PREFIXES: List[int] = []
DELETED_MESSAGES = [
# Everything until the next comment is from the
@@ -139,7 +137,6 @@ DELETED_MESSAGES = [
DeletedMessage("W1638", "range-builtin-not-iterating"),
DeletedMessage("W1639", "filter-builtin-not-iterating"),
DeletedMessage("W1640", "using-cmp-argument"),
- DeletedMessage("W1641", "eq-without-hash"),
DeletedMessage("W1642", "div-method"),
DeletedMessage("W1643", "idiv-method"),
DeletedMessage("W1644", "rdiv-method"),
diff --git a/pylint/extensions/__init__.py b/pylint/extensions/__init__.py
index c34836101..4af3aefb1 100644
--- a/pylint/extensions/__init__.py
+++ b/pylint/extensions/__init__.py
@@ -10,7 +10,7 @@ if TYPE_CHECKING:
def initialize(linter: "PyLinter") -> None:
- """Initialize linter with checkers in the extensions directory."""
+ """Initialize linter with checkers in the extensions' directory."""
register_plugins(linter, __path__[0])
diff --git a/pylint/extensions/code_style.py b/pylint/extensions/code_style.py
index 7082c991c..5a3e3ba17 100644
--- a/pylint/extensions/code_style.py
+++ b/pylint/extensions/code_style.py
@@ -28,7 +28,7 @@ class CodeStyleChecker(BaseChecker):
i.e. detect a common issue or improve performance
=> it should probably be part of the core checker classes
2. Is it something that would improve code consistency,
- maybe because it's slightly better with regards to performance
+ maybe because it's slightly better with regard to performance
and therefore preferred => this is the right place
3. Everything else should go into another extension
"""
diff --git a/pylint/extensions/eq_without_hash.py b/pylint/extensions/eq_without_hash.py
new file mode 100644
index 000000000..b0dd6ce46
--- /dev/null
+++ b/pylint/extensions/eq_without_hash.py
@@ -0,0 +1,39 @@
+# 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
+
+"""This is the remnant of the python3 checker. It was removed because
+the transition from python 2 to python3 is behind us, but some checks
+are still useful in python3 after all.
+See https://github.com/PyCQA/pylint/issues/5025
+"""
+
+from astroid import nodes
+
+from pylint import checkers, interfaces
+from pylint.checkers import utils
+from pylint.lint import PyLinter
+
+
+class EqWithoutHash(checkers.BaseChecker):
+
+ __implements__ = interfaces.IAstroidChecker
+ name = "eq-without-hash"
+
+ msgs = {
+ "W1641": (
+ "Implementing __eq__ without also implementing __hash__",
+ "eq-without-hash",
+ "Used when a class implements __eq__ but not __hash__. Objects get "
+ "None as their default __hash__ implementation if they also implement __eq__.",
+ ),
+ }
+
+ @utils.check_messages("eq-without-hash")
+ def visit_classdef(self, node: nodes.ClassDef) -> None:
+ locals_and_methods = set(node.locals).union(x.name for x in node.mymethods())
+ if "__eq__" in locals_and_methods and "__hash__" not in locals_and_methods:
+ self.add_message("eq-without-hash", node=node, confidence=interfaces.HIGH)
+
+
+def register(linter: PyLinter) -> None:
+ linter.register_checker(EqWithoutHash(linter))
diff --git a/tests/functional/ext/eq_without_hash/eq_without_hash.py b/tests/functional/ext/eq_without_hash/eq_without_hash.py
new file mode 100644
index 000000000..a28afc97b
--- /dev/null
+++ b/tests/functional/ext/eq_without_hash/eq_without_hash.py
@@ -0,0 +1,11 @@
+"""Regression test for #5025"""
+
+# pylint: disable=invalid-name, missing-docstring, too-few-public-methods
+
+
+class AClass: # [eq-without-hash]
+ def __init__(self) -> None:
+ self.x = 5
+
+ def __eq__(self, other: object) -> bool:
+ return isinstance(other, AClass) and other.x == self.x
diff --git a/tests/functional/ext/eq_without_hash/eq_without_hash.rc b/tests/functional/ext/eq_without_hash/eq_without_hash.rc
new file mode 100644
index 000000000..5a4c9fcce
--- /dev/null
+++ b/tests/functional/ext/eq_without_hash/eq_without_hash.rc
@@ -0,0 +1,2 @@
+[MASTER]
+load-plugins=pylint.extensions.eq_without_hash,
diff --git a/tests/functional/ext/eq_without_hash/eq_without_hash.txt b/tests/functional/ext/eq_without_hash/eq_without_hash.txt
new file mode 100644
index 000000000..b7e2dc46d
--- /dev/null
+++ b/tests/functional/ext/eq_without_hash/eq_without_hash.txt
@@ -0,0 +1 @@
+eq-without-hash:6:0:11:62:AClass:Implementing __eq__ without also implementing __hash__:HIGH