From 8bab5b2ed348a9ee7d8cbb80dcab4310ad8e1178 Mon Sep 17 00:00:00 2001 From: Florent Gallaire Date: Fri, 27 Jun 2025 03:14:32 +0200 Subject: [PATCH 1/5] Extra arg for "method" (self) and "classmethod" (cls) --- pylint/checkers/design_analysis.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pylint/checkers/design_analysis.py b/pylint/checkers/design_analysis.py index 5c1adbc888..c588fd7ee1 100644 --- a/pylint/checkers/design_analysis.py +++ b/pylint/checkers/design_analysis.py @@ -561,11 +561,15 @@ 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: + if node.type in {"function", "staticmethod"}: + max_args = self.linter.config.max_args + elif node.type in {"method", "classmethod"}: + max_args = self.linter.config.max_args + 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 From cc6462db870240c9811c92adef1eb834c81e2be6 Mon Sep 17 00:00:00 2001 From: Florent Gallaire Date: Tue, 1 Jul 2025 02:54:31 +0200 Subject: [PATCH 2/5] Fix max_positional_arguments, fix tests --- pylint/checkers/design_analysis.py | 8 ++++++-- .../functional/t/too/too_many_positional_arguments.py | 8 ++++---- .../functional/t/too/too_many_positional_arguments.txt | 10 +++++----- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/pylint/checkers/design_analysis.py b/pylint/checkers/design_analysis.py index c588fd7ee1..d8fd75dfe9 100644 --- a/pylint/checkers/design_analysis.py +++ b/pylint/checkers/design_analysis.py @@ -563,8 +563,12 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None: argnum = len(args) - ignored_args_num if node.type in {"function", "staticmethod"}: max_args = self.linter.config.max_args + max_positional_arguments = self.linter.config.max_positional_arguments elif node.type in {"method", "classmethod"}: max_args = self.linter.config.max_args + 1 + max_positional_arguments = ( + self.linter.config.max_positional_arguments + 1 + ) if argnum > max_args: self.add_message( "too-many-arguments", @@ -574,11 +578,11 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None: 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..3bd6be4f8c 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] + """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..185e5c2f30 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:FiveArgumentMethods.fail1:Too many arguments (7/6):UNDEFINED +too-many-positional-arguments:4:4:4:13:FiveArgumentMethods.fail1:Too many positional arguments (7/6):HIGH +too-many-arguments:6:4:6:13:FiveArgumentMethods.fail2:Too many arguments (7/6):UNDEFINED +too-many-positional-arguments:6:4:6:13:FiveArgumentMethods.fail2:Too many positional arguments (7/6):HIGH +too-many-arguments:8:4:8:13:FiveArgumentMethods.okay1:Too many arguments (7/6):UNDEFINED From d4e05ff821ca2db5cf0d5a219645f1890d5d050a Mon Sep 17 00:00:00 2001 From: Florent Gallaire Date: Tue, 1 Jul 2025 04:23:11 +0200 Subject: [PATCH 3/5] Fix FiveArgumentMethods class name --- .../functional/t/too/too_many_positional_arguments.py | 2 +- .../functional/t/too/too_many_positional_arguments.txt | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/functional/t/too/too_many_positional_arguments.py b/tests/functional/t/too/too_many_positional_arguments.py index 3bd6be4f8c..6a5ddb4da4 100644 --- a/tests/functional/t/too/too_many_positional_arguments.py +++ b/tests/functional/t/too/too_many_positional_arguments.py @@ -1,5 +1,5 @@ # pylint: disable=missing-function-docstring, missing-module-docstring -class FiveArgumentMethods: +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 diff --git a/tests/functional/t/too/too_many_positional_arguments.txt b/tests/functional/t/too/too_many_positional_arguments.txt index 185e5c2f30..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 (7/6):UNDEFINED -too-many-positional-arguments:4:4:4:13:FiveArgumentMethods.fail1:Too many positional arguments (7/6):HIGH -too-many-arguments:6:4:6:13:FiveArgumentMethods.fail2:Too many arguments (7/6):UNDEFINED -too-many-positional-arguments:6:4:6:13:FiveArgumentMethods.fail2:Too many positional arguments (7/6):HIGH -too-many-arguments:8:4:8:13:FiveArgumentMethods.okay1:Too many arguments (7/6):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 From 03b7c786a2729f7a151f743cd89613d719b3eebb Mon Sep 17 00:00:00 2001 From: Florent Gallaire Date: Fri, 4 Jul 2025 04:34:00 +0200 Subject: [PATCH 4/5] Add a new fragment (#8675) --- doc/whatsnew/fragments/8675.false_negative | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 doc/whatsnew/fragments/8675.false_negative 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 From 32d8cdb2410252b5f586f64f82ed5dc0970d9a8c Mon Sep 17 00:00:00 2001 From: Florent Gallaire Date: Mon, 7 Jul 2025 03:13:14 +0200 Subject: [PATCH 5/5] Fix (false positive) E0606 --- pylint/checkers/design_analysis.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/pylint/checkers/design_analysis.py b/pylint/checkers/design_analysis.py index d8fd75dfe9..5154e7a535 100644 --- a/pylint/checkers/design_analysis.py +++ b/pylint/checkers/design_analysis.py @@ -561,14 +561,11 @@ 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 node.type in {"function", "staticmethod"}: - max_args = self.linter.config.max_args - max_positional_arguments = self.linter.config.max_positional_arguments - elif node.type in {"method", "classmethod"}: - max_args = self.linter.config.max_args + 1 - max_positional_arguments = ( - self.linter.config.max_positional_arguments + 1 - ) + 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",