summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThéo Battrel <theo.util@protonmail.ch>2023-04-06 17:42:52 +0200
committerGitHub <noreply@github.com>2023-04-06 17:42:52 +0200
commit156da64d0fb4c06e15c5b619b91ce550d594a770 (patch)
tree30bf003979e4af1212746a2da015d52e1fbfb07c
parent82cee3719df2c799cf5b94bf5fb8058c297bc607 (diff)
downloadpylint-git-156da64d0fb4c06e15c5b619b91ce550d594a770.tar.gz
Fix check unused arguments false positive bug (#8542)
Problem: the special method `__new__` must match the arguments of the `__init__` method even if `__new__` method does not use them. This generate `unused-argument` for the `__new__` method. Fix: the unused arguments check should not be done on the `__new__` method if the `__init__` method is defined in the same class. Update `unused-argument` test to include a check for the case of `__init__` and `__new__` being defined in a class but `__new__` does not use all of the argument. This is fine because `__new__` must have the same argument of `__init__`. Update with a second check in case of `__init__` being not defined in a class. Then the unused arguments check must be done on `__new__`. Fixes https://github.com/pylint-dev/pylint/issues/3670
-rw-r--r--doc/whatsnew/fragments/3670.false_positive3
-rw-r--r--pylint/checkers/variables.py10
-rw-r--r--tests/functional/u/unused/unused_argument.py21
-rw-r--r--tests/functional/u/unused/unused_argument.txt2
4 files changed, 36 insertions, 0 deletions
diff --git a/doc/whatsnew/fragments/3670.false_positive b/doc/whatsnew/fragments/3670.false_positive
new file mode 100644
index 000000000..562a41de2
--- /dev/null
+++ b/doc/whatsnew/fragments/3670.false_positive
@@ -0,0 +1,3 @@
+Fix `unused-argument` false positive when `__new__` does not use all the arguments of `__init__`.
+
+Closes #3670
diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py
index 79bdb6a97..8647cc8a6 100644
--- a/pylint/checkers/variables.py
+++ b/pylint/checkers/variables.py
@@ -2593,6 +2593,16 @@ class VariablesChecker(BaseChecker):
argnames = node.argnames()
# Care about functions with unknown argument (builtins)
if name in argnames:
+ if node.name == "__new__":
+ is_init_def = False
+ # Look for the `__init__` method in all the methods of the same class.
+ for n in node.parent.get_children():
+ is_init_def = hasattr(n, "name") and (n.name == "__init__")
+ if is_init_def:
+ break
+ # Ignore unused arguments check for `__new__` if `__init__` is defined.
+ if is_init_def:
+ return
self._check_unused_arguments(name, node, stmt, argnames, nonlocal_names)
else:
if stmt.parent and isinstance(
diff --git a/tests/functional/u/unused/unused_argument.py b/tests/functional/u/unused/unused_argument.py
index 9e52de77a..1d072f21b 100644
--- a/tests/functional/u/unused/unused_argument.py
+++ b/tests/functional/u/unused/unused_argument.py
@@ -107,3 +107,24 @@ class Descendant(Ancestor):
def set_thing(self, thing, *, other=None):
"""Subclass does not raise unused-argument"""
self.thing = thing
+
+
+# Test that Class with both `__init__` and `__new__` don't check
+# on `__new__` for unused arguments
+
+# pylint: disable=invalid-name
+
+class TestClassWithInitAndNew:
+ def __init__(self, argA, argB):
+ self.argA = argA
+ self.argB = argB
+
+ def __new__(cls, argA, argB):
+ return object.__new__(cls)
+
+# Test that `__new__` method is checked for unused arguments
+# when `__init__` is not in the Class
+
+class TestClassWithOnlyNew:
+ def __new__(cls, argA, argB): # [unused-argument, unused-argument]
+ return object.__new__(cls)
diff --git a/tests/functional/u/unused/unused_argument.txt b/tests/functional/u/unused/unused_argument.txt
index 19c439304..bca2700ac 100644
--- a/tests/functional/u/unused/unused_argument.txt
+++ b/tests/functional/u/unused/unused_argument.txt
@@ -7,3 +7,5 @@ unused-argument:73:0:None:None:AAAA.selected:Unused argument 'args':INFERENCE
unused-argument:73:0:None:None:AAAA.selected:Unused argument 'kwargs':INFERENCE
unused-argument:92:23:92:26:BBBB.__init__:Unused argument 'arg':INFERENCE
unused-argument:103:34:103:39:Ancestor.set_thing:Unused argument 'other':INFERENCE
+unused-argument:129:21:129:25:TestClassWithOnlyNew.__new__:Unused argument 'argA':INFERENCE
+unused-argument:129:27:129:31:TestClassWithOnlyNew.__new__:Unused argument 'argB':INFERENCE