From 9682d47886aed70d33b0178091a0b38756aa3898 Mon Sep 17 00:00:00 2001 From: rogersheu Date: Sun, 11 Aug 2024 14:29:56 -0700 Subject: [PATCH] address isinstance false negative when provided too many arguments - add too-many-function-args call - include handling for too-few-function-args --- doc/whatsnew/fragments/9847.false_negative | 4 +++ pylint/checkers/typecheck.py | 28 ++++++++++++++++--- .../functional/t/too/too_few_function_args.py | 3 ++ .../t/too/too_few_function_args.txt | 1 + tests/functional/t/too/too_many_arguments.txt | 6 ++-- .../t/too/too_many_function_args.py | 5 ++++ .../t/too/too_many_function_args.txt | 3 ++ 7 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 doc/whatsnew/fragments/9847.false_negative create mode 100644 tests/functional/t/too/too_few_function_args.py create mode 100644 tests/functional/t/too/too_few_function_args.txt create mode 100644 tests/functional/t/too/too_many_function_args.txt diff --git a/doc/whatsnew/fragments/9847.false_negative b/doc/whatsnew/fragments/9847.false_negative new file mode 100644 index 0000000000..f0517fefe3 --- /dev/null +++ b/doc/whatsnew/fragments/9847.false_negative @@ -0,0 +1,4 @@ +Fix a false negative when `isinstance` has too many arguments. +Change now provides a `too-many-arguments` output with behavior similar to other `too-many-arguments` calls. + +Closes #9847 diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py index 508a6e1942..148604195f 100644 --- a/pylint/checkers/typecheck.py +++ b/pylint/checkers/typecheck.py @@ -255,7 +255,7 @@ def _missing_member_hint( "Used when a function call passes too few arguments.", ), "E1121": ( - "Too many positional arguments for %s call", + "Too many positional arguments (%s/%s)", "too-many-function-args", "Used when a function call passes too many positional arguments.", ), @@ -377,6 +377,11 @@ def _missing_member_hint( "Used when a slice step is 0 and the object doesn't implement " "a custom __getitem__ method.", ), + "E1145": ( + "Too few positional arguments (%s/%s)", + "too-few-function-args", + "Used when a function or method has fewer arguments than expected.", + ), "W1113": ( "Keyword argument before variable positional arguments list " "in the definition of %s function", @@ -1420,8 +1425,21 @@ def _check_argument_order( self.add_message("arguments-out-of-order", node=node, args=()) def _check_isinstance_args(self, node: nodes.Call) -> None: - if len(node.args) != 2: - # isinstance called with wrong number of args + if len(node.args) > 2: + # for when isinstance called with too many args + self.add_message( + "too-many-function-args", + node=node, + args=(len(node.args), 2), + confidence=HIGH, + ) + elif len(node.args) < 2: + self.add_message( + "too-few-function-args", + node=node, + args=(len(node.args), 2), + confidence=HIGH, + ) return second_arg = node.args[1] @@ -1554,7 +1572,9 @@ def visit_call(self, node: nodes.Call) -> None: elif not overload_function: # Too many positional arguments. self.add_message( - "too-many-function-args", node=node, args=(callable_name,) + "too-many-function-args", + node=node, + args=(len(parameters), num_positional_args), ) break diff --git a/tests/functional/t/too/too_few_function_args.py b/tests/functional/t/too/too_few_function_args.py new file mode 100644 index 0000000000..fb106bf80c --- /dev/null +++ b/tests/functional/t/too/too_few_function_args.py @@ -0,0 +1,3 @@ +# pylint: disable=missing-docstring + +isinstance(1) # [too-few-function-args] diff --git a/tests/functional/t/too/too_few_function_args.txt b/tests/functional/t/too/too_few_function_args.txt new file mode 100644 index 0000000000..f971d89f99 --- /dev/null +++ b/tests/functional/t/too/too_few_function_args.txt @@ -0,0 +1 @@ +too-few-function-args:3:0:3:13::Too few positional arguments (1/2):HIGH diff --git a/tests/functional/t/too/too_many_arguments.txt b/tests/functional/t/too/too_many_arguments.txt index b996058196..b68a80b863 100644 --- a/tests/functional/t/too/too_many_arguments.txt +++ b/tests/functional/t/too/too_many_arguments.txt @@ -1,3 +1,3 @@ -too-many-arguments:4:0:4:19:stupid_function:Too many arguments (9/5):UNDEFINED -too-many-positional-arguments:4:0:4:19:stupid_function:Too many positional arguments (9/5):HIGH -too-many-arguments:37:0:37:9:name1:Too many arguments (6/5):UNDEFINED +too-many-arguments:4:0:4:19:stupid_function:Too many arguments (9/5):UNDEFINED +too-many-positional-arguments:4:0:4:19:stupid_function:Too many positional arguments (9/5):HIGH +too-many-arguments:37:0:37:9:name1:Too many arguments (6/5):UNDEFINED diff --git a/tests/functional/t/too/too_many_function_args.py b/tests/functional/t/too/too_many_function_args.py index 9ba49565eb..848cbd1a0c 100644 --- a/tests/functional/t/too/too_many_function_args.py +++ b/tests/functional/t/too/too_many_function_args.py @@ -17,3 +17,8 @@ def main(param): if param == 0: tmp = add return tmp(1, 1.01) + + +# Negative case, see `_check_isinstance_args` in `./pylint/checkers/typecheck.py` +isinstance(1, int, int) # [too-many-function-args] +isinstance(1, 1, int) # [too-many-function-args, isinstance-second-argument-not-valid-type] diff --git a/tests/functional/t/too/too_many_function_args.txt b/tests/functional/t/too/too_many_function_args.txt new file mode 100644 index 0000000000..98aed584a1 --- /dev/null +++ b/tests/functional/t/too/too_many_function_args.txt @@ -0,0 +1,3 @@ +too-many-function-args:23:0:23:23::Too many positional arguments (3/2):HIGH +isinstance-second-argument-not-valid-type:24:0:24:21::Second argument of isinstance is not a type:INFERENCE +too-many-function-args:24:0:24:21::Too many positional arguments (3/2):HIGH