Skip to content

Commit 75ae5cc

Browse files
committed
typing.overload functions are exempted from too-many-function-args
Close #3170
1 parent 3d6ddbe commit 75ae5cc

File tree

4 files changed

+58
-12
lines changed

4 files changed

+58
-12
lines changed

ChangeLog

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ Release date: TBA
4141

4242
Close #3148
4343

44-
4544
* ``import-outside-toplevel`` is emitted for ``ImportFrom`` nodes as well.
4645

4746
Close #3175
@@ -63,6 +62,10 @@ Release date: TBA
6362

6463
Closes #3185
6564

65+
* ``typing.overload`` functions are exempted from ``too-many-function-args``
66+
67+
Close #3170
68+
6669

6770
What's New in Pylint 2.4.2?
6871
===========================

pylint/checkers/typecheck.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
is_inside_abstract_class,
6666
is_iterable,
6767
is_mapping,
68+
is_overload_stub,
6869
is_super,
6970
node_ignores_exception,
7071
safe_infer,
@@ -1185,6 +1186,7 @@ def visit_call(self, node):
11851186

11861187
num_positional_args = len(call_site.positional_arguments)
11871188
keyword_args = list(call_site.keyword_arguments.keys())
1189+
overload_function = is_overload_stub(called)
11881190

11891191
# Determine if we don't have a context for our call and we use variadics.
11901192
node_scope = node.scope()
@@ -1251,11 +1253,12 @@ def visit_call(self, node):
12511253
# parameter.
12521254
break
12531255
else:
1254-
# Too many positional arguments.
1255-
self.add_message(
1256-
"too-many-function-args", node=node, args=(callable_name,)
1257-
)
1258-
break
1256+
if not overload_function:
1257+
# Too many positional arguments.
1258+
self.add_message(
1259+
"too-many-function-args", node=node, args=(callable_name,)
1260+
)
1261+
break
12591262

12601263
# 2. Match the keyword arguments.
12611264
for keyword in keyword_args:
@@ -1290,7 +1293,7 @@ def visit_call(self, node):
12901293
elif called.args.kwarg is not None:
12911294
# The keyword argument gets assigned to the **kwargs parameter.
12921295
pass
1293-
else:
1296+
elif not overload_function:
12941297
# Unexpected keyword argument.
12951298
self.add_message(
12961299
"unexpected-keyword-arg", node=node, args=(keyword, callable_name)
@@ -1315,7 +1318,7 @@ def visit_call(self, node):
13151318
display_name = "<tuple>"
13161319
else:
13171320
display_name = repr(name)
1318-
if not has_no_context_positional_variadic:
1321+
if not has_no_context_positional_variadic and not overload_function:
13191322
self.add_message(
13201323
"no-value-for-parameter",
13211324
node=node,

pylint/checkers/utils.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,10 @@ def _is_property_decorator(decorator: astroid.Name) -> bool:
753753
return False
754754

755755

756-
def decorated_with(func: astroid.FunctionDef, qnames: Iterable[str]) -> bool:
756+
def decorated_with(
757+
func: Union[astroid.FunctionDef, astroid.BoundMethod, astroid.UnboundMethod],
758+
qnames: Iterable[str],
759+
) -> bool:
757760
"""Determine if the `func` node has a decorator with the qualified name `qname`."""
758761
decorators = func.decorators.nodes if func.decorators else []
759762
for decorator_node in decorators:
@@ -1237,9 +1240,8 @@ def is_overload_stub(node: astroid.node_classes.NodeNG) -> bool:
12371240
:param node: Node to check.
12381241
:returns: True if node is an overload function stub. False otherwise.
12391242
"""
1240-
return isinstance(node, astroid.FunctionDef) and decorated_with(
1241-
node, ["typing.overload"]
1242-
)
1243+
decorators = getattr(node, "decorators", None)
1244+
return bool(decorators and decorated_with(node, ["typing.overload", "overload"]))
12431245

12441246

12451247
def is_protocol_class(cls: astroid.node_classes.NodeNG) -> bool:
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# pylint: disable=missing-function-docstring,missing-module-docstring,missing-class-docstring
2+
# pylint: disable=too-few-public-methods
3+
from typing import overload
4+
5+
6+
class ClassA:
7+
@classmethod
8+
@overload
9+
def method(cls, arg1):
10+
pass
11+
12+
@classmethod
13+
@overload
14+
def method(cls, arg1, arg2):
15+
pass
16+
17+
@classmethod
18+
def method(cls, arg1, arg2=None):
19+
pass
20+
21+
22+
ClassA.method(1, 2)
23+
24+
25+
class ClassB:
26+
@overload
27+
def method(self, arg1):
28+
pass
29+
30+
@overload
31+
def method(self, arg1, arg2):
32+
pass
33+
34+
def method(self, arg1, arg2=None):
35+
pass
36+
37+
38+
ClassB().method(1, arg2=2)

0 commit comments

Comments
 (0)