diff --git a/doc/whatsnew/fragments/8675.false_negative b/doc/whatsnew/fragments/8675.false_negative new file mode 100644 index 0000000000..8bbdd558e9 --- /dev/null +++ b/doc/whatsnew/fragments/8675.false_negative @@ -0,0 +1,3 @@ +Fix a false positive for `too-many-arguments` in (non static) method and classmethod. + +Closes #8675 diff --git a/pylint/checkers/design_analysis.py b/pylint/checkers/design_analysis.py index 5c1adbc888..5154e7a535 100644 --- a/pylint/checkers/design_analysis.py +++ b/pylint/checkers/design_analysis.py @@ -561,20 +561,25 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None: ignored_args_num = ignored_pos_args_num + ignored_kwonly_args_num argnum = len(args) - ignored_args_num - if argnum > self.linter.config.max_args: + max_args = self.linter.config.max_args + max_positional_arguments = self.linter.config.max_positional_arguments + if node.type in {"method", "classmethod"}: + max_args = max_args + 1 + max_positional_arguments = max_positional_arguments + 1 + if argnum > max_args: self.add_message( "too-many-arguments", node=node, - args=(len(args), self.linter.config.max_args), + args=(len(args), max_args), ) pos_args_count = ( len(args) - len(node.args.kwonlyargs) - ignored_pos_args_num ) - if pos_args_count > self.linter.config.max_positional_arguments: + if pos_args_count > max_positional_arguments: self.add_message( "too-many-positional-arguments", node=node, - args=(pos_args_count, self.linter.config.max_positional_arguments), + args=(pos_args_count, max_positional_arguments), confidence=HIGH, ) else: diff --git a/tests/functional/t/too/too_many_positional_arguments.py b/tests/functional/t/too/too_many_positional_arguments.py index e373324818..6a5ddb4da4 100644 --- a/tests/functional/t/too/too_many_positional_arguments.py +++ b/tests/functional/t/too/too_many_positional_arguments.py @@ -1,9 +1,9 @@ # pylint: disable=missing-function-docstring, missing-module-docstring -class FiveArgumentMethods: - """The max positional arguments default is 5.""" - def fail1(self, a, b, c, d, e): # [too-many-arguments, too-many-positional-arguments] +class SixArgumentMethods: + """The max positional arguments default is 5, so 6 for a method because of self.""" + def fail1(self, a, b, c, d, e, f): # [too-many-arguments, too-many-positional-arguments] pass - def fail2(self, a, b, c, d, /, e): # [too-many-arguments, too-many-positional-arguments] + def fail2(self, a, b, c, d, e, /, f): # [too-many-arguments, too-many-positional-arguments] pass - def okay1(self, a, b, c, d, *, e=True): # [too-many-arguments] + def okay1(self, a, b, c, d, e, *, f=True): # [too-many-arguments] pass diff --git a/tests/functional/t/too/too_many_positional_arguments.txt b/tests/functional/t/too/too_many_positional_arguments.txt index 80591cd371..a310ad8fcd 100644 --- a/tests/functional/t/too/too_many_positional_arguments.txt +++ b/tests/functional/t/too/too_many_positional_arguments.txt @@ -1,5 +1,5 @@ -too-many-arguments:4:4:4:13:FiveArgumentMethods.fail1:Too many arguments (6/5):UNDEFINED -too-many-positional-arguments:4:4:4:13:FiveArgumentMethods.fail1:Too many positional arguments (6/5):HIGH -too-many-arguments:6:4:6:13:FiveArgumentMethods.fail2:Too many arguments (6/5):UNDEFINED -too-many-positional-arguments:6:4:6:13:FiveArgumentMethods.fail2:Too many positional arguments (6/5):HIGH -too-many-arguments:8:4:8:13:FiveArgumentMethods.okay1:Too many arguments (6/5):UNDEFINED +too-many-arguments:4:4:4:13:SixArgumentMethods.fail1:Too many arguments (7/6):UNDEFINED +too-many-positional-arguments:4:4:4:13:SixArgumentMethods.fail1:Too many positional arguments (7/6):HIGH +too-many-arguments:6:4:6:13:SixArgumentMethods.fail2:Too many arguments (7/6):UNDEFINED +too-many-positional-arguments:6:4:6:13:SixArgumentMethods.fail2:Too many positional arguments (7/6):HIGH +too-many-arguments:8:4:8:13:SixArgumentMethods.okay1:Too many arguments (7/6):UNDEFINED