diff options
-rw-r--r-- | doc/whatsnew/fragments/3670.false_positive | 3 | ||||
-rw-r--r-- | pylint/checkers/variables.py | 10 | ||||
-rw-r--r-- | tests/functional/u/unused/unused_argument.py | 21 | ||||
-rw-r--r-- | tests/functional/u/unused/unused_argument.txt | 2 |
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 f55b71264..79d9ded08 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -2602,6 +2602,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 b46c1e4d7..69c37feef 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 |