Skip to content

Commit 1dc3174

Browse files
Emplisgithub-actions[bot]
authored andcommitted
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 #3670 (cherry picked from commit 156da64)
1 parent de0147e commit 1dc3174

File tree

4 files changed

+36
-0
lines changed

4 files changed

+36
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix `unused-argument` false positive when `__new__` does not use all the arguments of `__init__`.
2+
3+
Closes #3670

pylint/checkers/variables.py

+10
Original file line numberDiff line numberDiff line change
@@ -2602,6 +2602,16 @@ def _check_is_unused(
26022602
argnames = node.argnames()
26032603
# Care about functions with unknown argument (builtins)
26042604
if name in argnames:
2605+
if node.name == "__new__":
2606+
is_init_def = False
2607+
# Look for the `__init__` method in all the methods of the same class.
2608+
for n in node.parent.get_children():
2609+
is_init_def = hasattr(n, "name") and (n.name == "__init__")
2610+
if is_init_def:
2611+
break
2612+
# Ignore unused arguments check for `__new__` if `__init__` is defined.
2613+
if is_init_def:
2614+
return
26052615
self._check_unused_arguments(name, node, stmt, argnames, nonlocal_names)
26062616
else:
26072617
if stmt.parent and isinstance(

tests/functional/u/unused/unused_argument.py

+21
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,24 @@ class Descendant(Ancestor):
107107
def set_thing(self, thing, *, other=None):
108108
"""Subclass does not raise unused-argument"""
109109
self.thing = thing
110+
111+
112+
# Test that Class with both `__init__` and `__new__` don't check
113+
# on `__new__` for unused arguments
114+
115+
# pylint: disable=invalid-name
116+
117+
class TestClassWithInitAndNew:
118+
def __init__(self, argA, argB):
119+
self.argA = argA
120+
self.argB = argB
121+
122+
def __new__(cls, argA, argB):
123+
return object.__new__(cls)
124+
125+
# Test that `__new__` method is checked for unused arguments
126+
# when `__init__` is not in the Class
127+
128+
class TestClassWithOnlyNew:
129+
def __new__(cls, argA, argB): # [unused-argument, unused-argument]
130+
return object.__new__(cls)

tests/functional/u/unused/unused_argument.txt

+2
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ unused-argument:73:0:None:None:AAAA.selected:Unused argument 'args':INFERENCE
77
unused-argument:73:0:None:None:AAAA.selected:Unused argument 'kwargs':INFERENCE
88
unused-argument:92:23:92:26:BBBB.__init__:Unused argument 'arg':INFERENCE
99
unused-argument:103:34:103:39:Ancestor.set_thing:Unused argument 'other':INFERENCE
10+
unused-argument:129:21:129:25:TestClassWithOnlyNew.__new__:Unused argument 'argA':INFERENCE
11+
unused-argument:129:27:129:31:TestClassWithOnlyNew.__new__:Unused argument 'argB':INFERENCE

0 commit comments

Comments
 (0)