diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2019-10-17 09:29:53 +0200 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2019-10-17 09:30:11 +0200 |
commit | ccb1d05636f18231809aead61f73ad9d2ae46458 (patch) | |
tree | 6d7e8ccbf7fd9100c4ec48a5be5fddf36b4720e9 | |
parent | 89a18eff3f10b2ca9bd3a16ced978580586ad89e (diff) | |
download | pylint-git-ccb1d05636f18231809aead61f73ad9d2ae46458.tar.gz |
``typing.overload`` functions are exempted from ``too-many-function-args``
Close #3170
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | pylint/checkers/typecheck.py | 17 | ||||
-rw-r--r-- | pylint/checkers/utils.py | 10 | ||||
-rw-r--r-- | tests/functional/too/too_many_arguments_overload.py | 38 |
4 files changed, 58 insertions, 12 deletions
@@ -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) |