Skip to content

Commit c1c1e17

Browse files
RomanValovpylint-backport[bot]
authored andcommitted
Fix treatment of "self" arg for too-many-arguments message (#10885)
(cherry picked from commit 8faa924)
1 parent 0fa1065 commit c1c1e17

6 files changed

Lines changed: 184 additions & 29 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a false positive for ``too-many-arguments`` in (non-static) methods and classmethods.
2+
3+
Closes #8675

pylint/checkers/design_analysis.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -542,11 +542,13 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
542542
# init branch and returns counters
543543
self._returns.append(0)
544544
# check number of arguments
545-
args = node.args.args + node.args.posonlyargs + node.args.kwonlyargs
546-
pos_args = node.args.args + node.args.posonlyargs
545+
pos_args = node.args.posonlyargs + node.args.args
546+
if node.type in {"method", "classmethod"}:
547+
pos_args = pos_args[1:]
548+
args = pos_args + node.args.kwonlyargs
547549
ignored_argument_names = self.linter.config.ignored_argument_names
548-
if args is not None:
549-
ignored_args_num = 0
550+
ignored_args_num = 0
551+
if args:
550552
if ignored_argument_names:
551553
ignored_pos_args_num = sum(
552554
1 for arg in pos_args if ignored_argument_names.match(arg.name)
@@ -558,25 +560,22 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
558560
)
559561
ignored_args_num = ignored_pos_args_num + ignored_kwonly_args_num
560562

561-
argnum = len(args) - ignored_args_num
562-
if argnum > self.linter.config.max_args:
563+
args_num = len(args) - ignored_args_num
564+
if args_num > self.linter.config.max_args:
563565
self.add_message(
564566
"too-many-arguments",
565567
node=node,
566-
args=(len(args), self.linter.config.max_args),
568+
args=(args_num, self.linter.config.max_args),
567569
)
568-
pos_args_count = (
569-
len(args) - len(node.args.kwonlyargs) - ignored_pos_args_num
570-
)
571-
if pos_args_count > self.linter.config.max_positional_arguments:
570+
pos_args_num = len(pos_args) - ignored_pos_args_num
571+
if pos_args_num > self.linter.config.max_positional_arguments:
572572
self.add_message(
573573
"too-many-positional-arguments",
574574
node=node,
575-
args=(pos_args_count, self.linter.config.max_positional_arguments),
575+
args=(pos_args_num, self.linter.config.max_positional_arguments),
576576
confidence=HIGH,
577577
)
578-
else:
579-
ignored_args_num = 0
578+
580579
# check number of local variables
581580
locnum = len(node.locals) - ignored_args_num
582581

pylint/config/argument.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,6 @@ class _StoreArgument(_BaseStoreArgument):
229229
https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.add_argument
230230
"""
231231

232-
# pylint: disable-next=too-many-arguments
233232
def __init__(
234233
self,
235234
*,
@@ -307,7 +306,6 @@ class _DeprecationArgument(_Argument):
307306
https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.add_argument
308307
"""
309308

310-
# pylint: disable-next=too-many-arguments
311309
def __init__(
312310
self,
313311
*,
@@ -397,7 +395,6 @@ class _StoreOldNamesArgument(_DeprecationArgument):
397395
https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.add_argument
398396
"""
399397

400-
# pylint: disable-next=too-many-arguments
401398
def __init__(
402399
self,
403400
*,
@@ -435,7 +432,6 @@ class _StoreNewNamesArgument(_DeprecationArgument):
435432
https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.add_argument
436433
"""
437434

438-
# pylint: disable-next=too-many-arguments
439435
def __init__(
440436
self,
441437
*,

tests/functional/a/async_functions.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ redefined-builtin:5:0:5:14:next:Redefining built-in 'next':UNDEFINED
22
unused-argument:8:30:8:34:some_function:Unused argument 'arg2':HIGH
33
bad-super-call:22:8:22:31:Class.some_method:Bad first argument 'OtherClass' given to super():UNDEFINED
44
line-too-long:26:0:None:None::Line too long (104/100):UNDEFINED
5-
too-many-arguments:27:0:27:26:complex_function:Too many arguments (10/5):UNDEFINED
5+
too-many-arguments:27:0:27:26:complex_function:Too many arguments (9/5):UNDEFINED
66
too-many-branches:27:0:27:26:complex_function:Too many branches (13/12):UNDEFINED
77
too-many-positional-arguments:27:0:27:26:complex_function:Too many positional arguments (9/5):HIGH
88
too-many-return-statements:27:0:27:26:complex_function:Too many return statements (10/6):UNDEFINED
Lines changed: 138 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,142 @@
11
# pylint: disable=missing-function-docstring, missing-module-docstring
2-
class FiveArgumentMethods:
3-
"""The max positional arguments default is 5."""
4-
def fail1(self, a, b, c, d, e): # [too-many-arguments, too-many-positional-arguments]
2+
class RegularMethods:
3+
"""The max positional arguments default is 5. Regular methods don't count `self`."""
4+
5+
# +1: [too-many-arguments, too-many-positional-arguments]
6+
def regular_fail1(self, a, b, c, d, e, f):
57
pass
6-
def fail2(self, a, b, c, d, /, e): # [too-many-arguments, too-many-positional-arguments]
8+
# +1: [too-many-arguments, too-many-positional-arguments]
9+
def regular_fail2(self, a, b, c, d, e, /, f):
710
pass
8-
def okay1(self, a, b, c, d, *, e=True): # [too-many-arguments]
11+
# +1: [too-many-arguments, too-many-positional-arguments]
12+
def regular_fail3(self, /, a, b, c, d, e, f):
13+
pass
14+
# +1: [too-many-arguments]
15+
def regular_soso1(self, a, b, c, d, e, *, f=True):
16+
pass
17+
# +1: [too-many-arguments]
18+
def regular_soso2(self, a, b, c, d, e, /, *, f=True):
19+
pass
20+
# +1: [too-many-arguments]
21+
def regular_soso3(self, /, a, b, c, d, e, *, f=True):
22+
pass
23+
# +1: [too-many-arguments]
24+
def regular_soso4(self, a, b, c, d, e, /, _f, *, g=True):
25+
pass
26+
# +1: [too-many-arguments]
27+
def regular_soso5(self, /, _a, b, c, d, e, f, *, g=True):
28+
pass
29+
def regular_okay1(self, a, b, c, d, e):
30+
pass
31+
def regular_okay2(self, a, b, c, d, e, /):
32+
pass
33+
def regular_okay3(self, *, a, b, c, d, e):
34+
pass
35+
def regular_okay4(self, a, b, c, d, e, /, _f):
36+
pass
37+
def regular_okay5(self, _a, b, c, d, e, /, f):
38+
pass
39+
def regular_okay6(self, /, _a, b, c, d, e, f):
40+
pass
41+
def regular_okay7(self, /, a, b, c, d, e, _f):
42+
pass
43+
44+
45+
# pylint: disable=missing-function-docstring, missing-module-docstring
46+
class StaticMethods:
47+
"""The max positional arguments default is 5. Static methods count them all."""
48+
49+
@staticmethod
50+
# +1: [too-many-arguments, too-many-positional-arguments]
51+
def static_fail1(a, b, c, d, e, f):
52+
pass
53+
@staticmethod
54+
# +1: [too-many-arguments, too-many-positional-arguments]
55+
def static_fail2(a, b, c, d, e, /, f):
56+
pass
57+
@staticmethod
58+
# +1: [too-many-arguments]
59+
def static_soso1(a, b, c, d, e, *, f=True):
60+
pass
61+
@staticmethod
62+
# +1: [too-many-arguments]
63+
def static_soso2(a, b, c, d, e, /, *, f=True):
64+
pass
65+
@staticmethod
66+
# +1: [too-many-arguments]
67+
def static_soso3(a, b, c, d, e, /, _f, *, g=True):
68+
pass
69+
@staticmethod
70+
def static_okay1(a, b, c, d, e):
71+
pass
72+
@staticmethod
73+
def static_okay2(a, b, c, d, e, /):
74+
pass
75+
@staticmethod
76+
def static_okay3(*, a, b, c, d, e):
77+
pass
78+
@staticmethod
79+
def static_okay4(a, b, c, d, e, /, _f):
80+
pass
81+
@staticmethod
82+
def static_okay5(_a, b, c, d, e, /, f):
83+
pass
84+
85+
86+
# pylint: disable=missing-function-docstring, missing-module-docstring
87+
class ClassMethods:
88+
"""The max positional arguments default is 5. Class methods don't count `cls`."""
89+
90+
@classmethod
91+
# +1: [too-many-arguments, too-many-positional-arguments]
92+
def class_fail1(cls, a, b, c, d, e, f):
93+
pass
94+
@classmethod
95+
# +1: [too-many-arguments, too-many-positional-arguments]
96+
def class_fail2(cls, a, b, c, d, e, /, f):
97+
pass
98+
@classmethod
99+
# +1: [too-many-arguments, too-many-positional-arguments]
100+
def class_fail3(cls, /, a, b, c, d, e, f):
101+
pass
102+
@classmethod
103+
# +1: [too-many-arguments]
104+
def class_soso1(cls, a, b, c, d, e, *, f=True):
105+
pass
106+
@classmethod
107+
# +1: [too-many-arguments]
108+
def class_soso2(cls, a, b, c, d, e, /, *, f=True):
109+
pass
110+
@classmethod
111+
# +1: [too-many-arguments]
112+
def class_soso3(cls, /, a, b, c, d, e, *, f=True):
113+
pass
114+
@classmethod
115+
# +1: [too-many-arguments]
116+
def class_soso4(cls, a, b, c, d, e, /, _f, *, g=True):
117+
pass
118+
@classmethod
119+
# +1: [too-many-arguments]
120+
def class_soso5(cls, /, _a, b, c, d, e, f, *, g=True):
121+
pass
122+
@classmethod
123+
def class_okay1(cls, a, b, c, d, e):
124+
pass
125+
@classmethod
126+
def class_okay2(cls, a, b, c, d, e, /):
127+
pass
128+
@classmethod
129+
def class_okay3(cls, *, a, b, c, d, e):
130+
pass
131+
@classmethod
132+
def class_okay4(cls, a, b, c, d, e, /, _f):
133+
pass
134+
@classmethod
135+
def class_okay5(cls, _a, b, c, d, e, /, f):
136+
pass
137+
@classmethod
138+
def class_okay6(cls, /, _a, b, c, d, e, f):
139+
pass
140+
@classmethod
141+
def class_okay7(cls, /, a, b, c, d, e, _f):
9142
pass
Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
1-
too-many-arguments:4:4:4:13:FiveArgumentMethods.fail1:Too many arguments (6/5):UNDEFINED
2-
too-many-positional-arguments:4:4:4:13:FiveArgumentMethods.fail1:Too many positional arguments (6/5):HIGH
3-
too-many-arguments:6:4:6:13:FiveArgumentMethods.fail2:Too many arguments (6/5):UNDEFINED
4-
too-many-positional-arguments:6:4:6:13:FiveArgumentMethods.fail2:Too many positional arguments (6/5):HIGH
5-
too-many-arguments:8:4:8:13:FiveArgumentMethods.okay1:Too many arguments (6/5):UNDEFINED
1+
too-many-arguments:6:4:6:21:RegularMethods.regular_fail1:Too many arguments (6/5):UNDEFINED
2+
too-many-positional-arguments:6:4:6:21:RegularMethods.regular_fail1:Too many positional arguments (6/5):HIGH
3+
too-many-arguments:9:4:9:21:RegularMethods.regular_fail2:Too many arguments (6/5):UNDEFINED
4+
too-many-positional-arguments:9:4:9:21:RegularMethods.regular_fail2:Too many positional arguments (6/5):HIGH
5+
too-many-arguments:12:4:12:21:RegularMethods.regular_fail3:Too many arguments (6/5):UNDEFINED
6+
too-many-positional-arguments:12:4:12:21:RegularMethods.regular_fail3:Too many positional arguments (6/5):HIGH
7+
too-many-arguments:15:4:15:21:RegularMethods.regular_soso1:Too many arguments (6/5):UNDEFINED
8+
too-many-arguments:18:4:18:21:RegularMethods.regular_soso2:Too many arguments (6/5):UNDEFINED
9+
too-many-arguments:21:4:21:21:RegularMethods.regular_soso3:Too many arguments (6/5):UNDEFINED
10+
too-many-arguments:24:4:24:21:RegularMethods.regular_soso4:Too many arguments (6/5):UNDEFINED
11+
too-many-arguments:27:4:27:21:RegularMethods.regular_soso5:Too many arguments (6/5):UNDEFINED
12+
too-many-arguments:51:4:51:20:StaticMethods.static_fail1:Too many arguments (6/5):UNDEFINED
13+
too-many-positional-arguments:51:4:51:20:StaticMethods.static_fail1:Too many positional arguments (6/5):HIGH
14+
too-many-arguments:55:4:55:20:StaticMethods.static_fail2:Too many arguments (6/5):UNDEFINED
15+
too-many-positional-arguments:55:4:55:20:StaticMethods.static_fail2:Too many positional arguments (6/5):HIGH
16+
too-many-arguments:59:4:59:20:StaticMethods.static_soso1:Too many arguments (6/5):UNDEFINED
17+
too-many-arguments:63:4:63:20:StaticMethods.static_soso2:Too many arguments (6/5):UNDEFINED
18+
too-many-arguments:67:4:67:20:StaticMethods.static_soso3:Too many arguments (6/5):UNDEFINED
19+
too-many-arguments:92:4:92:19:ClassMethods.class_fail1:Too many arguments (6/5):UNDEFINED
20+
too-many-positional-arguments:92:4:92:19:ClassMethods.class_fail1:Too many positional arguments (6/5):HIGH
21+
too-many-arguments:96:4:96:19:ClassMethods.class_fail2:Too many arguments (6/5):UNDEFINED
22+
too-many-positional-arguments:96:4:96:19:ClassMethods.class_fail2:Too many positional arguments (6/5):HIGH
23+
too-many-arguments:100:4:100:19:ClassMethods.class_fail3:Too many arguments (6/5):UNDEFINED
24+
too-many-positional-arguments:100:4:100:19:ClassMethods.class_fail3:Too many positional arguments (6/5):HIGH
25+
too-many-arguments:104:4:104:19:ClassMethods.class_soso1:Too many arguments (6/5):UNDEFINED
26+
too-many-arguments:108:4:108:19:ClassMethods.class_soso2:Too many arguments (6/5):UNDEFINED
27+
too-many-arguments:112:4:112:19:ClassMethods.class_soso3:Too many arguments (6/5):UNDEFINED
28+
too-many-arguments:116:4:116:19:ClassMethods.class_soso4:Too many arguments (6/5):UNDEFINED
29+
too-many-arguments:120:4:120:19:ClassMethods.class_soso5:Too many arguments (6/5):UNDEFINED

0 commit comments

Comments
 (0)