summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2019-10-17 09:29:53 +0200
committerClaudiu Popa <pcmanticore@gmail.com>2019-10-17 09:30:11 +0200
commitccb1d05636f18231809aead61f73ad9d2ae46458 (patch)
tree6d7e8ccbf7fd9100c4ec48a5be5fddf36b4720e9
parent89a18eff3f10b2ca9bd3a16ced978580586ad89e (diff)
downloadpylint-git-ccb1d05636f18231809aead61f73ad9d2ae46458.tar.gz
``typing.overload`` functions are exempted from ``too-many-function-args``
Close #3170
-rw-r--r--ChangeLog5
-rw-r--r--pylint/checkers/typecheck.py17
-rw-r--r--pylint/checkers/utils.py10
-rw-r--r--tests/functional/too/too_many_arguments_overload.py38
4 files changed, 58 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 80cce6a38..feff058aa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,7 +11,6 @@ Release date: TBA
Close #3148
-
* ``import-outside-toplevel`` is emitted for ``ImportFrom`` nodes as well.
Close #3175
@@ -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?
===========================
diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py
index 53014bc54..472f7d417 100644
--- a/pylint/checkers/typecheck.py
+++ b/pylint/checkers/typecheck.py
@@ -65,6 +65,7 @@ from pylint.checkers.utils import (
is_inside_abstract_class,
is_iterable,
is_mapping,
+ is_overload_stub,
is_super,
node_ignores_exception,
safe_infer,
@@ -1185,6 +1186,7 @@ accessed. Python regular expressions are accepted.",
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()
@@ -1251,11 +1253,12 @@ accessed. Python regular expressions are accepted.",
# 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:
@@ -1290,7 +1293,7 @@ accessed. Python regular expressions are accepted.",
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)
@@ -1315,7 +1318,7 @@ accessed. Python regular expressions are accepted.",
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,
diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py
index 0480cd4f2..2a6820a54 100644
--- a/pylint/checkers/utils.py
+++ b/pylint/checkers/utils.py
@@ -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:
@@ -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:
diff --git a/tests/functional/too/too_many_arguments_overload.py b/tests/functional/too/too_many_arguments_overload.py
new file mode 100644
index 000000000..1155deb0c
--- /dev/null
+++ b/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)