Skip to content

Commit 7a1fbb9

Browse files
mbyrnepr2Pierre-Sassoulas
authored andcommitted
Fix false positive for too-many-function-args when a function call is assigned to a class attribute inside the class where the function is defined. (#7395)
Closes #6592
1 parent a10406a commit 7a1fbb9

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix false positive for ``too-many-function-args`` when a function call is assigned to a class attribute inside the class where the function is defined.
2+
3+
Closes #6592

pylint/checkers/typecheck.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,6 +1458,19 @@ def visit_call(self, node: nodes.Call) -> None:
14581458
keyword_args += list(already_filled_keywords)
14591459
num_positional_args += implicit_args + already_filled_positionals
14601460

1461+
# Decrement `num_positional_args` by 1 when a function call is assigned to a class attribute
1462+
# inside the class where the function is defined.
1463+
# This avoids emitting `too-many-function-args` since `num_positional_args`
1464+
# includes an implicit `self` argument which is not present in `called.args`.
1465+
if (
1466+
isinstance(node.frame(), nodes.ClassDef)
1467+
and isinstance(node.parent, (nodes.Assign, nodes.AnnAssign))
1468+
and isinstance(called, nodes.FunctionDef)
1469+
and called in node.frame().body
1470+
and num_positional_args > 0
1471+
):
1472+
num_positional_args -= 1
1473+
14611474
# Analyze the list of formal parameters.
14621475
args = list(itertools.chain(called.args.posonlyargs or (), called.args.args))
14631476
num_mandatory_parameters = len(args) - len(called.args.defaults)

tests/functional/a/arguments.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# pylint: disable=too-few-public-methods, missing-docstring,import-error,wrong-import-position
22
# pylint: disable=wrong-import-order, unnecessary-lambda, consider-using-f-string
3-
# pylint: disable=unnecessary-lambda-assignment
3+
# pylint: disable=unnecessary-lambda-assignment, no-self-argument, unused-argument
44

55
def decorator(fun):
66
"""Decorator"""
@@ -261,3 +261,20 @@ def func(one, two, three):
261261

262262

263263
CALL = lambda *args: func(*args)
264+
265+
266+
# Ensure `too-many-function-args` is not emitted when a function call is assigned
267+
# to a class attribute inside the class where the function is defined.
268+
# Reference: https://github.com/PyCQA/pylint/issues/6592
269+
class FruitPicker:
270+
def _pick_fruit(fruit):
271+
def _print_selection(self):
272+
print(f"Selected: {fruit}!")
273+
return _print_selection
274+
275+
pick_apple = _pick_fruit("apple")
276+
pick_pear = _pick_fruit("pear")
277+
278+
picker = FruitPicker()
279+
picker.pick_apple()
280+
picker.pick_pear()

0 commit comments

Comments
 (0)