Skip to content

Commit

Permalink
typing.overload functions are exempted from ``too-many-function-a…
Browse files Browse the repository at this point in the history
…rgs``

Close #3170
  • Loading branch information
PCManticore committed Oct 17, 2019
1 parent 89a18ef commit ccb1d05
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 12 deletions.
5 changes: 4 additions & 1 deletion ChangeLog
Expand Up @@ -11,7 +11,6 @@ Release date: TBA

Close #3148


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

Close #3175
Expand All @@ -34,6 +33,10 @@ Release date: TBA

Closes #3185

* ``typing.overload`` functions are exempted from ``too-many-function-args``

Close #3170


What's New in Pylint 2.4.2?
===========================
Expand Down
17 changes: 10 additions & 7 deletions pylint/checkers/typecheck.py
Expand Up @@ -65,6 +65,7 @@
is_inside_abstract_class,
is_iterable,
is_mapping,
is_overload_stub,
is_super,
node_ignores_exception,
safe_infer,
Expand Down Expand Up @@ -1185,6 +1186,7 @@ def visit_call(self, node):

num_positional_args = len(call_site.positional_arguments)
keyword_args = list(call_site.keyword_arguments.keys())
overload_function = is_overload_stub(called)

# Determine if we don't have a context for our call and we use variadics.
node_scope = node.scope()
Expand Down Expand Up @@ -1251,11 +1253,12 @@ def visit_call(self, node):
# parameter.
break
else:
# Too many positional arguments.
self.add_message(
"too-many-function-args", node=node, args=(callable_name,)
)
break
if not overload_function:
# Too many positional arguments.
self.add_message(
"too-many-function-args", node=node, args=(callable_name,)
)
break

# 2. Match the keyword arguments.
for keyword in keyword_args:
Expand Down Expand Up @@ -1290,7 +1293,7 @@ def visit_call(self, node):
elif called.args.kwarg is not None:
# The keyword argument gets assigned to the **kwargs parameter.
pass
else:
elif not overload_function:
# Unexpected keyword argument.
self.add_message(
"unexpected-keyword-arg", node=node, args=(keyword, callable_name)
Expand All @@ -1315,7 +1318,7 @@ def visit_call(self, node):
display_name = "<tuple>"
else:
display_name = repr(name)
if not has_no_context_positional_variadic:
if not has_no_context_positional_variadic and not overload_function:
self.add_message(
"no-value-for-parameter",
node=node,
Expand Down
10 changes: 6 additions & 4 deletions pylint/checkers/utils.py
Expand Up @@ -748,7 +748,10 @@ def _is_property_decorator(decorator: astroid.Name) -> bool:
return False


def decorated_with(func: astroid.FunctionDef, qnames: Iterable[str]) -> bool:
def decorated_with(
func: Union[astroid.FunctionDef, astroid.BoundMethod, astroid.UnboundMethod],
qnames: Iterable[str],
) -> bool:
"""Determine if the `func` node has a decorator with the qualified name `qname`."""
decorators = func.decorators.nodes if func.decorators else []
for decorator_node in decorators:
Expand Down Expand Up @@ -1232,9 +1235,8 @@ def is_overload_stub(node: astroid.node_classes.NodeNG) -> bool:
:param node: Node to check.
:returns: True if node is an overload function stub. False otherwise.
"""
return isinstance(node, astroid.FunctionDef) and decorated_with(
node, ["typing.overload"]
)
decorators = getattr(node, "decorators", None)
return bool(decorators and decorated_with(node, ["typing.overload", "overload"]))


def is_protocol_class(cls: astroid.node_classes.NodeNG) -> bool:
Expand Down
38 changes: 38 additions & 0 deletions tests/functional/too/too_many_arguments_overload.py
@@ -0,0 +1,38 @@
# pylint: disable=missing-function-docstring,missing-module-docstring,missing-class-docstring
# pylint: disable=too-few-public-methods
from typing import overload


class ClassA:
@classmethod
@overload
def method(cls, arg1):
pass

@classmethod
@overload
def method(cls, arg1, arg2):
pass

@classmethod
def method(cls, arg1, arg2=None):
pass


ClassA.method(1, 2)


class ClassB:
@overload
def method(self, arg1):
pass

@overload
def method(self, arg1, arg2):
pass

def method(self, arg1, arg2=None):
pass


ClassB().method(1, arg2=2)

0 comments on commit ccb1d05

Please sign in to comment.