diff --git a/.gitignore b/.gitignore index d807609565..e8ec590f5b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ build-stamp .pytest_cache/ .mypy_cache/ .benchmarks/ +venv diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py index 8448a0f13b..8a5c051db0 100644 --- a/pylint/checkers/typecheck.py +++ b/pylint/checkers/typecheck.py @@ -381,6 +381,11 @@ def _missing_member_hint( "Used when a slice step is 0 and the object doesn't implement " "a custom __getitem__ method.", ), + "E1145": ( + "", + "decorator-preserves-signature", + "Ignore invalid argument errors on calls to this function", + ), "W1113": ( "Keyword argument before variable positional arguments list " "in the definition of %s function", @@ -1454,10 +1459,18 @@ def visit_call(self, node: nodes.Call) -> None: return # Has the function signature changed in ways we cannot reliably detect? - if hasattr(called, "decorators") and decorated_with( - called, self.linter.config.signature_mutators - ): - return + if getattr(called, "decorators", None): + if decorated_with(called, self.linter.config.signature_mutators): + return + + called_decorator: astroid.NodeNG + for called_decorator in filter( + None, map(safe_infer, called.decorators.nodes) + ): + if not self.linter.file_state._module_msgs_state.get("E1145", {}).get( + called_decorator.lineno, True + ): + return num_positional_args = len(call_site.positional_arguments) keyword_args = list(call_site.keyword_arguments.keys()) diff --git a/tests/functional/a/arguments.py b/tests/functional/a/arguments.py index 6929b98500..bf77dcbc69 100644 --- a/tests/functional/a/arguments.py +++ b/tests/functional/a/arguments.py @@ -240,6 +240,17 @@ def wrapper(*args, do_something=True, **kwargs): return wrapper +def yet_another_mutation_decorator(fun): # pylint: disable=decorator-preserves-signature + """Yet another decorator that changes a function's signature""" + def wrapper(*args, do_something=True, **kwargs): + if do_something: + return fun(*args, **kwargs) + + return None + + return wrapper + + @mutation_decorator def mutated_function(arg): return arg @@ -250,11 +261,17 @@ def mutated(arg): return arg +@yet_another_mutation_decorator +def another_mutated_function(arg): + return arg + + mutated_function(do_something=False) mutated_function() mutated(do_something=True) +another_mutated_function(do_something=False) def func(one, two, three): return one + two + three