From e2d6de5b75f66cd5d78074699fb5365a57c5b55f Mon Sep 17 00:00:00 2001 From: azinneck0485 <123660683+azinneck0485@users.noreply.github.com> Date: Fri, 27 Oct 2023 00:16:32 -0400 Subject: [PATCH 01/12] add method visit_trystar to exceptions.py --- pylint/checkers/exceptions.py | 77 +++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/pylint/checkers/exceptions.py b/pylint/checkers/exceptions.py index ce3f9367f0..8ca342cc2d 100644 --- a/pylint/checkers/exceptions.py +++ b/pylint/checkers/exceptions.py @@ -556,6 +556,83 @@ def visit_compare(self, node: nodes.Compare) -> None: "catching-non-exception", "duplicate-except", ) + def visit_trystar(self, node: nodes.TryStar) -> None: + """Check for empty except*.""" + self._check_try_except_raise(node) + exceptions_classes: list[Any] = [] + nb_handlers = len(node.handlers) + for index, handler in enumerate(node.handlers): + if handler.type is None: # TODO - create tests for each of these also? + if not _is_raising(handler.body): + self.add_message("bare-except", node=handler, confidence=HIGH) + + # check if an "except:" is followed by some other + # except + if index < (nb_handlers - 1): + msg = "empty except clause should always appear last" + self.add_message( + "bad-except-order", node=node, args=msg, confidence=HIGH + ) + + elif isinstance(handler.type, nodes.BoolOp): + self.add_message( + "binary-op-exception", + node=handler, + args=handler.type.op, + confidence=HIGH, + ) + else: + try: + exceptions = list(_annotated_unpack_infer(handler.type)) + except astroid.InferenceError: + continue + + for part, exception in exceptions: + if isinstance( + exception, astroid.Instance + ) and utils.inherit_from_std_ex(exception): + exception = exception._proxied + + self._check_catching_non_exception(handler, exception, part) + + if not isinstance(exception, nodes.ClassDef): + continue + + exc_ancestors = [ + anc + for anc in exception.ancestors() + if isinstance(anc, nodes.ClassDef) + ] + + for previous_exc in exceptions_classes: + if previous_exc in exc_ancestors: + msg = f"{previous_exc.name} is an ancestor class of {exception.name}" + self.add_message( + "bad-except-order", + node=handler.type, + args=msg, + confidence=INFERENCE, + ) + if self._is_overgeneral_exception(exception) and not _is_raising( + handler.body + ): + self.add_message( + "broad-exception-caught", + args=exception.name, + node=handler.type, + confidence=INFERENCE, + ) + + if exception in exceptions_classes: + self.add_message( + "duplicate-except", + args=exception.name, + node=handler.type, + confidence=INFERENCE, + ) + + exceptions_classes += [exc for _, exc in exceptions] + def visit_try(self, node: nodes.Try) -> None: """Check for empty except.""" self._check_try_except_raise(node) From da2fe7b8718b90c8c055a995db37d38761553ddb Mon Sep 17 00:00:00 2001 From: azinneck0485 <123660683+azinneck0485@users.noreply.github.com> Date: Fri, 27 Oct 2023 14:36:21 -0400 Subject: [PATCH 02/12] replace content of visit_trystar with call to visit_try to avoid replicated code --- pylint/checkers/exceptions.py | 75 +---------------------------------- 1 file changed, 1 insertion(+), 74 deletions(-) diff --git a/pylint/checkers/exceptions.py b/pylint/checkers/exceptions.py index 8ca342cc2d..edc72c22ea 100644 --- a/pylint/checkers/exceptions.py +++ b/pylint/checkers/exceptions.py @@ -558,80 +558,7 @@ def visit_compare(self, node: nodes.Compare) -> None: ) def visit_trystar(self, node: nodes.TryStar) -> None: """Check for empty except*.""" - self._check_try_except_raise(node) - exceptions_classes: list[Any] = [] - nb_handlers = len(node.handlers) - for index, handler in enumerate(node.handlers): - if handler.type is None: # TODO - create tests for each of these also? - if not _is_raising(handler.body): - self.add_message("bare-except", node=handler, confidence=HIGH) - - # check if an "except:" is followed by some other - # except - if index < (nb_handlers - 1): - msg = "empty except clause should always appear last" - self.add_message( - "bad-except-order", node=node, args=msg, confidence=HIGH - ) - - elif isinstance(handler.type, nodes.BoolOp): - self.add_message( - "binary-op-exception", - node=handler, - args=handler.type.op, - confidence=HIGH, - ) - else: - try: - exceptions = list(_annotated_unpack_infer(handler.type)) - except astroid.InferenceError: - continue - - for part, exception in exceptions: - if isinstance( - exception, astroid.Instance - ) and utils.inherit_from_std_ex(exception): - exception = exception._proxied - - self._check_catching_non_exception(handler, exception, part) - - if not isinstance(exception, nodes.ClassDef): - continue - - exc_ancestors = [ - anc - for anc in exception.ancestors() - if isinstance(anc, nodes.ClassDef) - ] - - for previous_exc in exceptions_classes: - if previous_exc in exc_ancestors: - msg = f"{previous_exc.name} is an ancestor class of {exception.name}" - self.add_message( - "bad-except-order", - node=handler.type, - args=msg, - confidence=INFERENCE, - ) - if self._is_overgeneral_exception(exception) and not _is_raising( - handler.body - ): - self.add_message( - "broad-exception-caught", - args=exception.name, - node=handler.type, - confidence=INFERENCE, - ) - - if exception in exceptions_classes: - self.add_message( - "duplicate-except", - args=exception.name, - node=handler.type, - confidence=INFERENCE, - ) - - exceptions_classes += [exc for _, exc in exceptions] + self.visit_try(node) def visit_try(self, node: nodes.Try) -> None: """Check for empty except.""" From 5e833b848506155dfe4a6dba12c64104231ba00b Mon Sep 17 00:00:00 2001 From: azinneck0485 <123660683+azinneck0485@users.noreply.github.com> Date: Fri, 27 Oct 2023 14:41:58 -0400 Subject: [PATCH 03/12] add logic in basic_checker.py to detect try-except* and not issue pointless-statement message on try-clause body --- pylint/checkers/base/basic_checker.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pylint/checkers/base/basic_checker.py b/pylint/checkers/base/basic_checker.py index 3505ee7082..45faf05767 100644 --- a/pylint/checkers/base/basic_checker.py +++ b/pylint/checkers/base/basic_checker.py @@ -479,6 +479,7 @@ def visit_expr(self, node: nodes.Expr) -> None: if ( isinstance(expr, (nodes.Yield, nodes.Await)) or (isinstance(node.parent, nodes.Try) and node.parent.body == [node]) + or (isinstance(node.parent, nodes.TryStar) and node.parent.body == [node]) or (isinstance(expr, nodes.Const) and expr.value is Ellipsis) ): return From fa173283a4ba2b35e0fe63ef228d479effdef4ea Mon Sep 17 00:00:00 2001 From: azinneck0485 <123660683+azinneck0485@users.noreply.github.com> Date: Fri, 27 Oct 2023 17:11:27 -0400 Subject: [PATCH 04/12] update functional testing for broad-exception-caught to include try-except* --- tests/functional/b/broad_exception_caught.py | 30 +++++++++++++++++++ tests/functional/b/broad_exception_caught.txt | 9 ++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/tests/functional/b/broad_exception_caught.py b/tests/functional/b/broad_exception_caught.py index 0a69a70156..b9bb48063e 100644 --- a/tests/functional/b/broad_exception_caught.py +++ b/tests/functional/b/broad_exception_caught.py @@ -37,3 +37,33 @@ class CustomNarrowException(CustomBroadException): __revision__ += 1 except CustomNarrowException: print('error') + + +try: + __revision__ += 1 +except* Exception: # [broad-exception-caught] + print('error') + + +try: + __revision__ += 1 +except* BaseException: # [broad-exception-caught] + print('error') + + +try: + __revision__ += 1 +except* ValueError: + print('error') + + +try: + __revision__ += 1 +except* CustomBroadException: # [broad-exception-caught] + print('error') + + +try: + __revision__ += 1 +except* CustomNarrowException: + print('error') diff --git a/tests/functional/b/broad_exception_caught.txt b/tests/functional/b/broad_exception_caught.txt index 386423b63f..b54d74ae33 100644 --- a/tests/functional/b/broad_exception_caught.txt +++ b/tests/functional/b/broad_exception_caught.txt @@ -1,3 +1,6 @@ -broad-exception-caught:14:7:14:16::Catching too general exception Exception:INFERENCE -broad-exception-caught:20:7:20:20::Catching too general exception BaseException:INFERENCE -broad-exception-caught:32:7:32:27::Catching too general exception CustomBroadException:INFERENCE +broad-exception-caught:14:7:14:16::Catching too general exception Exception:INFERENCE +broad-exception-caught:20:7:20:20::Catching too general exception BaseException:INFERENCE +broad-exception-caught:32:7:32:27::Catching too general exception CustomBroadException:INFERENCE +broad-exception-caught:44:8:44:17::Catching too general exception Exception:INFERENCE +broad-exception-caught:50:8:50:21::Catching too general exception BaseException:INFERENCE +broad-exception-caught:62:8:62:28::Catching too general exception CustomBroadException:INFERENCE From e7f6d5369fe56aa790a7d1865f24e6f5137580ea Mon Sep 17 00:00:00 2001 From: azinneck0485 <123660683+azinneck0485@users.noreply.github.com> Date: Fri, 27 Oct 2023 17:22:22 -0400 Subject: [PATCH 05/12] update functional testing for broad-exception-raised to include try-except* --- tests/functional/b/broad_exception_raised.py | 31 +++++++++++++++++++ tests/functional/b/broad_exception_raised.txt | 20 +++++++----- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/tests/functional/b/broad_exception_raised.py b/tests/functional/b/broad_exception_raised.py index c6ce64b462..38873d2620 100644 --- a/tests/functional/b/broad_exception_raised.py +++ b/tests/functional/b/broad_exception_raised.py @@ -50,3 +50,34 @@ def raise_catch_raise_using_alias(): raise CustomBroadException() # [broad-exception-raised] raise IndexError from None raise CustomNarrowException() from None + + +def raise_and_catch_star(): + try: + raise Exception("Oh No!!") # [broad-exception-raised] + except* Exception as ex: # [broad-exception-caught] + print(ex) + + +def raise_catch_reraise_star(): + try: + exploding_apple("apple") + except* Exception as ex: + print(ex) + raise ex + + +def raise_catch_raise_star(): + try: + exploding_apple("apple") + except* Exception as ex: + print(ex) + raise Exception() from None # [broad-exception-raised] + + +def raise_catch_raise_using_alias_star(): + try: + exploding_apple("apple") + except* Exception as ex: + print(ex) + raise ExceptionAlias() from None # [broad-exception-raised] diff --git a/tests/functional/b/broad_exception_raised.txt b/tests/functional/b/broad_exception_raised.txt index 1e27b23f98..c42e4ecc8b 100644 --- a/tests/functional/b/broad_exception_raised.txt +++ b/tests/functional/b/broad_exception_raised.txt @@ -1,8 +1,12 @@ -broad-exception-raised:15:4:15:41:exploding_apple:"Raising too general exception: Exception":INFERENCE -broad-exception-raised:20:8:20:34:raise_and_catch:"Raising too general exception: Exception":INFERENCE -broad-exception-caught:21:11:21:20:raise_and_catch:Catching too general exception Exception:INFERENCE -broad-exception-raised:38:8:38:35:raise_catch_raise:"Raising too general exception: Exception":INFERENCE -broad-exception-raised:46:8:46:40:raise_catch_raise_using_alias:"Raising too general exception: Exception":INFERENCE -broad-exception-raised:48:0:48:17::"Raising too general exception: Exception":INFERENCE -broad-exception-raised:49:0:49:21::"Raising too general exception: BaseException":INFERENCE -broad-exception-raised:50:0:50:28::"Raising too general exception: CustomBroadException":INFERENCE +broad-exception-raised:15:4:15:41:exploding_apple:"Raising too general exception: Exception":INFERENCE +broad-exception-raised:20:8:20:34:raise_and_catch:"Raising too general exception: Exception":INFERENCE +broad-exception-caught:21:11:21:20:raise_and_catch:Catching too general exception Exception:INFERENCE +broad-exception-raised:38:8:38:35:raise_catch_raise:"Raising too general exception: Exception":INFERENCE +broad-exception-raised:46:8:46:40:raise_catch_raise_using_alias:"Raising too general exception: Exception":INFERENCE +broad-exception-raised:48:0:48:17::"Raising too general exception: Exception":INFERENCE +broad-exception-raised:49:0:49:21::"Raising too general exception: BaseException":INFERENCE +broad-exception-raised:50:0:50:28::"Raising too general exception: CustomBroadException":INFERENCE +broad-exception-raised:57:8:57:34:raise_and_catch_star:"Raising too general exception: Exception":INFERENCE +broad-exception-caught:58:12:58:21:raise_and_catch_star:Catching too general exception Exception:INFERENCE +broad-exception-raised:75:8:75:35:raise_catch_raise_star:"Raising too general exception: Exception":INFERENCE +broad-exception-raised:83:8:83:40:raise_catch_raise_using_alias_star:"Raising too general exception: Exception":INFERENCE From fdd9fec406b1f82660730fa4b1640a20e3da9f8d Mon Sep 17 00:00:00 2001 From: azinneck0485 <123660683+azinneck0485@users.noreply.github.com> Date: Sat, 28 Oct 2023 16:22:43 -0400 Subject: [PATCH 06/12] added documentation for fix --- doc/whatsnew/fragments/8827.false_negative | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 doc/whatsnew/fragments/8827.false_negative diff --git a/doc/whatsnew/fragments/8827.false_negative b/doc/whatsnew/fragments/8827.false_negative new file mode 100644 index 0000000000..42b84e712d --- /dev/null +++ b/doc/whatsnew/fragments/8827.false_negative @@ -0,0 +1,3 @@ +Extend broad-exception-raised and broad-exception-caught to except*. + +Closes #8827 From 9086a5a9b5be25e1cf356363ce5f9600e2bb659e Mon Sep 17 00:00:00 2001 From: azinneck0485 <123660683+azinneck0485@users.noreply.github.com> Date: Sat, 28 Oct 2023 16:51:34 -0400 Subject: [PATCH 07/12] update logic in basic_checker.py Co-authored-by: Pierre Sassoulas --- pylint/checkers/base/basic_checker.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pylint/checkers/base/basic_checker.py b/pylint/checkers/base/basic_checker.py index 45faf05767..644bf44bea 100644 --- a/pylint/checkers/base/basic_checker.py +++ b/pylint/checkers/base/basic_checker.py @@ -478,8 +478,7 @@ def visit_expr(self, node: nodes.Expr) -> None: # side effects), else pointless-statement if ( isinstance(expr, (nodes.Yield, nodes.Await)) - or (isinstance(node.parent, nodes.Try) and node.parent.body == [node]) - or (isinstance(node.parent, nodes.TryStar) and node.parent.body == [node]) + or (isinstance(node.parent, (nodes.Try, nodes.TryStar) and node.parent.body == [node]) or (isinstance(expr, nodes.Const) and expr.value is Ellipsis) ): return From 5550da4f4a8d68183a1056b0d386176966f74a4b Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sat, 28 Oct 2023 22:59:45 +0200 Subject: [PATCH 08/12] Update pylint/checkers/base/basic_checker.py --- pylint/checkers/base/basic_checker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylint/checkers/base/basic_checker.py b/pylint/checkers/base/basic_checker.py index 644bf44bea..d99a720d97 100644 --- a/pylint/checkers/base/basic_checker.py +++ b/pylint/checkers/base/basic_checker.py @@ -478,7 +478,7 @@ def visit_expr(self, node: nodes.Expr) -> None: # side effects), else pointless-statement if ( isinstance(expr, (nodes.Yield, nodes.Await)) - or (isinstance(node.parent, (nodes.Try, nodes.TryStar) and node.parent.body == [node]) + or (isinstance(node.parent, (nodes.Try, nodes.TryStar)) and node.parent.body == [node]) or (isinstance(expr, nodes.Const) and expr.value is Ellipsis) ): return From a6d4f568682adadcfc3eb210d4a201cb06141d75 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 28 Oct 2023 21:00:26 +0000 Subject: [PATCH 09/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- pylint/checkers/base/basic_checker.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pylint/checkers/base/basic_checker.py b/pylint/checkers/base/basic_checker.py index d99a720d97..9f122a411a 100644 --- a/pylint/checkers/base/basic_checker.py +++ b/pylint/checkers/base/basic_checker.py @@ -478,7 +478,10 @@ def visit_expr(self, node: nodes.Expr) -> None: # side effects), else pointless-statement if ( isinstance(expr, (nodes.Yield, nodes.Await)) - or (isinstance(node.parent, (nodes.Try, nodes.TryStar)) and node.parent.body == [node]) + or ( + isinstance(node.parent, (nodes.Try, nodes.TryStar)) + and node.parent.body == [node] + ) or (isinstance(expr, nodes.Const) and expr.value is Ellipsis) ): return From 8a1880f03dc38bcaeeb0634d477e711e2f35a682 Mon Sep 17 00:00:00 2001 From: azinneck0485 <123660683+azinneck0485@users.noreply.github.com> Date: Mon, 6 Nov 2023 22:15:03 -0500 Subject: [PATCH 10/12] separate try and try* tests for broad_exception_raised/caught to be able to specify only testing try* for Python 3.11 and higher --- .../broad_exception/broad_exception_caught.py | 39 ++++++++++++++ .../broad_exception/broad_exception_caught.rc | 5 ++ .../broad_exception_caught.txt | 3 ++ .../broad_exception_caught_trystar.py} | 32 +----------- .../broad_exception_caught_trystar.rc | 8 +++ .../broad_exception_caught_trystar.txt | 3 ++ .../broad_exception/broad_exception_raised.py | 52 +++++++++++++++++++ .../broad_exception/broad_exception_raised.rc | 5 ++ .../broad_exception_raised.txt | 4 -- .../broad_exception_raised_trystar.py} | 43 +++------------ .../broad_exception_raised_trystar.rc | 7 +++ .../broad_exception_raised_trystar.txt | 8 +++ tests/functional/b/broad_exception_caught.rc | 4 -- tests/functional/b/broad_exception_caught.txt | 6 --- tests/functional/b/broad_exception_raised.rc | 4 -- 15 files changed, 137 insertions(+), 86 deletions(-) create mode 100644 tests/functional/b/broad_exception/broad_exception_caught.py create mode 100644 tests/functional/b/broad_exception/broad_exception_caught.rc create mode 100644 tests/functional/b/broad_exception/broad_exception_caught.txt rename tests/functional/b/{broad_exception_caught.py => broad_exception/broad_exception_caught_trystar.py} (57%) create mode 100644 tests/functional/b/broad_exception/broad_exception_caught_trystar.rc create mode 100644 tests/functional/b/broad_exception/broad_exception_caught_trystar.txt create mode 100644 tests/functional/b/broad_exception/broad_exception_raised.py create mode 100644 tests/functional/b/broad_exception/broad_exception_raised.rc rename tests/functional/b/{ => broad_exception}/broad_exception_raised.txt (63%) rename tests/functional/b/{broad_exception_raised.py => broad_exception/broad_exception_raised_trystar.py} (64%) create mode 100644 tests/functional/b/broad_exception/broad_exception_raised_trystar.rc create mode 100644 tests/functional/b/broad_exception/broad_exception_raised_trystar.txt delete mode 100644 tests/functional/b/broad_exception_caught.rc delete mode 100644 tests/functional/b/broad_exception_caught.txt delete mode 100644 tests/functional/b/broad_exception_raised.rc diff --git a/tests/functional/b/broad_exception/broad_exception_caught.py b/tests/functional/b/broad_exception/broad_exception_caught.py new file mode 100644 index 0000000000..0a69a70156 --- /dev/null +++ b/tests/functional/b/broad_exception/broad_exception_caught.py @@ -0,0 +1,39 @@ +# pylint: disable=missing-docstring +__revision__ = 0 + +class CustomBroadException(Exception): + pass + + +class CustomNarrowException(CustomBroadException): + pass + + +try: + __revision__ += 1 +except Exception: # [broad-exception-caught] + print('error') + + +try: + __revision__ += 1 +except BaseException: # [broad-exception-caught] + print('error') + + +try: + __revision__ += 1 +except ValueError: + print('error') + + +try: + __revision__ += 1 +except CustomBroadException: # [broad-exception-caught] + print('error') + + +try: + __revision__ += 1 +except CustomNarrowException: + print('error') diff --git a/tests/functional/b/broad_exception/broad_exception_caught.rc b/tests/functional/b/broad_exception/broad_exception_caught.rc new file mode 100644 index 0000000000..5af8705b60 --- /dev/null +++ b/tests/functional/b/broad_exception/broad_exception_caught.rc @@ -0,0 +1,5 @@ +[EXCEPTIONS] +overgeneral-exceptions=builtins.BaseException, + builtins.Exception, + functional.b.broad_exception.broad_exception_caught.CustomBroadException, + broad_exception_caught.CustomBroadException diff --git a/tests/functional/b/broad_exception/broad_exception_caught.txt b/tests/functional/b/broad_exception/broad_exception_caught.txt new file mode 100644 index 0000000000..817e620172 --- /dev/null +++ b/tests/functional/b/broad_exception/broad_exception_caught.txt @@ -0,0 +1,3 @@ +broad-exception-caught:14:7:14:16::Catching too general exception Exception:INFERENCE +broad-exception-caught:20:7:20:20::Catching too general exception BaseException:INFERENCE +broad-exception-caught:32:7:32:27::Catching too general exception CustomBroadException:INFERENCE diff --git a/tests/functional/b/broad_exception_caught.py b/tests/functional/b/broad_exception/broad_exception_caught_trystar.py similarity index 57% rename from tests/functional/b/broad_exception_caught.py rename to tests/functional/b/broad_exception/broad_exception_caught_trystar.py index b9bb48063e..a50c1e4dda 100644 --- a/tests/functional/b/broad_exception_caught.py +++ b/tests/functional/b/broad_exception/broad_exception_caught_trystar.py @@ -9,36 +9,6 @@ class CustomNarrowException(CustomBroadException): pass -try: - __revision__ += 1 -except Exception: # [broad-exception-caught] - print('error') - - -try: - __revision__ += 1 -except BaseException: # [broad-exception-caught] - print('error') - - -try: - __revision__ += 1 -except ValueError: - print('error') - - -try: - __revision__ += 1 -except CustomBroadException: # [broad-exception-caught] - print('error') - - -try: - __revision__ += 1 -except CustomNarrowException: - print('error') - - try: __revision__ += 1 except* Exception: # [broad-exception-caught] @@ -59,7 +29,7 @@ class CustomNarrowException(CustomBroadException): try: __revision__ += 1 -except* CustomBroadException: # [broad-exception-caught] +except CustomBroadException: # [broad-exception-caught] print('error') diff --git a/tests/functional/b/broad_exception/broad_exception_caught_trystar.rc b/tests/functional/b/broad_exception/broad_exception_caught_trystar.rc new file mode 100644 index 0000000000..e47a4eb9f6 --- /dev/null +++ b/tests/functional/b/broad_exception/broad_exception_caught_trystar.rc @@ -0,0 +1,8 @@ +[EXCEPTIONS] +overgeneral-exceptions=builtins.BaseException, + builtins.Exception, + functional.b.broad_exception.broad_exception_caught_trystar.CustomBroadException, + broad_exception_caught_trystar.CustomBroadException + +[testoptions] +min_pyver=3.11 diff --git a/tests/functional/b/broad_exception/broad_exception_caught_trystar.txt b/tests/functional/b/broad_exception/broad_exception_caught_trystar.txt new file mode 100644 index 0000000000..da8725e57a --- /dev/null +++ b/tests/functional/b/broad_exception/broad_exception_caught_trystar.txt @@ -0,0 +1,3 @@ +broad-exception-caught:14:8:14:17::Catching too general exception Exception:INFERENCE +broad-exception-caught:20:8:20:21::Catching too general exception BaseException:INFERENCE +broad-exception-caught:32:7:32:27::Catching too general exception CustomBroadException:INFERENCE diff --git a/tests/functional/b/broad_exception/broad_exception_raised.py b/tests/functional/b/broad_exception/broad_exception_raised.py new file mode 100644 index 0000000000..c6ce64b462 --- /dev/null +++ b/tests/functional/b/broad_exception/broad_exception_raised.py @@ -0,0 +1,52 @@ +# pylint: disable=missing-docstring, unreachable + +ExceptionAlias = Exception + +class CustomBroadException(Exception): + pass + + +class CustomNarrowException(CustomBroadException): + pass + + +def exploding_apple(apple): + print(f"{apple} is about to explode") + raise Exception("{apple} exploded !") # [broad-exception-raised] + + +def raise_and_catch(): + try: + raise Exception("Oh No!!") # [broad-exception-raised] + except Exception as ex: # [broad-exception-caught] + print(ex) + + +def raise_catch_reraise(): + try: + exploding_apple("apple") + except Exception as ex: + print(ex) + raise ex + + +def raise_catch_raise(): + try: + exploding_apple("apple") + except Exception as ex: + print(ex) + raise Exception() from None # [broad-exception-raised] + + +def raise_catch_raise_using_alias(): + try: + exploding_apple("apple") + except Exception as ex: + print(ex) + raise ExceptionAlias() from None # [broad-exception-raised] + +raise Exception() # [broad-exception-raised] +raise BaseException() # [broad-exception-raised] +raise CustomBroadException() # [broad-exception-raised] +raise IndexError from None +raise CustomNarrowException() from None diff --git a/tests/functional/b/broad_exception/broad_exception_raised.rc b/tests/functional/b/broad_exception/broad_exception_raised.rc new file mode 100644 index 0000000000..bc73576c00 --- /dev/null +++ b/tests/functional/b/broad_exception/broad_exception_raised.rc @@ -0,0 +1,5 @@ +[EXCEPTIONS] +overgeneral-exceptions=builtins.BaseException, + builtins.Exception, + functional.b.broad_exception.broad_exception_raised.CustomBroadException, + broad_exception_raised.CustomBroadException diff --git a/tests/functional/b/broad_exception_raised.txt b/tests/functional/b/broad_exception/broad_exception_raised.txt similarity index 63% rename from tests/functional/b/broad_exception_raised.txt rename to tests/functional/b/broad_exception/broad_exception_raised.txt index c42e4ecc8b..705bf45cd8 100644 --- a/tests/functional/b/broad_exception_raised.txt +++ b/tests/functional/b/broad_exception/broad_exception_raised.txt @@ -6,7 +6,3 @@ broad-exception-raised:46:8:46:40:raise_catch_raise_using_alias:"Raising too gen broad-exception-raised:48:0:48:17::"Raising too general exception: Exception":INFERENCE broad-exception-raised:49:0:49:21::"Raising too general exception: BaseException":INFERENCE broad-exception-raised:50:0:50:28::"Raising too general exception: CustomBroadException":INFERENCE -broad-exception-raised:57:8:57:34:raise_and_catch_star:"Raising too general exception: Exception":INFERENCE -broad-exception-caught:58:12:58:21:raise_and_catch_star:Catching too general exception Exception:INFERENCE -broad-exception-raised:75:8:75:35:raise_catch_raise_star:"Raising too general exception: Exception":INFERENCE -broad-exception-raised:83:8:83:40:raise_catch_raise_using_alias_star:"Raising too general exception: Exception":INFERENCE diff --git a/tests/functional/b/broad_exception_raised.py b/tests/functional/b/broad_exception/broad_exception_raised_trystar.py similarity index 64% rename from tests/functional/b/broad_exception_raised.py rename to tests/functional/b/broad_exception/broad_exception_raised_trystar.py index 38873d2620..850fce4754 100644 --- a/tests/functional/b/broad_exception_raised.py +++ b/tests/functional/b/broad_exception/broad_exception_raised_trystar.py @@ -15,43 +15,6 @@ def exploding_apple(apple): raise Exception("{apple} exploded !") # [broad-exception-raised] -def raise_and_catch(): - try: - raise Exception("Oh No!!") # [broad-exception-raised] - except Exception as ex: # [broad-exception-caught] - print(ex) - - -def raise_catch_reraise(): - try: - exploding_apple("apple") - except Exception as ex: - print(ex) - raise ex - - -def raise_catch_raise(): - try: - exploding_apple("apple") - except Exception as ex: - print(ex) - raise Exception() from None # [broad-exception-raised] - - -def raise_catch_raise_using_alias(): - try: - exploding_apple("apple") - except Exception as ex: - print(ex) - raise ExceptionAlias() from None # [broad-exception-raised] - -raise Exception() # [broad-exception-raised] -raise BaseException() # [broad-exception-raised] -raise CustomBroadException() # [broad-exception-raised] -raise IndexError from None -raise CustomNarrowException() from None - - def raise_and_catch_star(): try: raise Exception("Oh No!!") # [broad-exception-raised] @@ -81,3 +44,9 @@ def raise_catch_raise_using_alias_star(): except* Exception as ex: print(ex) raise ExceptionAlias() from None # [broad-exception-raised] + +raise Exception() # [broad-exception-raised] +raise BaseException() # [broad-exception-raised] +raise CustomBroadException() # [broad-exception-raised] +raise IndexError from None +raise CustomNarrowException() from None diff --git a/tests/functional/b/broad_exception/broad_exception_raised_trystar.rc b/tests/functional/b/broad_exception/broad_exception_raised_trystar.rc new file mode 100644 index 0000000000..48fca7d55b --- /dev/null +++ b/tests/functional/b/broad_exception/broad_exception_raised_trystar.rc @@ -0,0 +1,7 @@ +[EXCEPTIONS] +overgeneral-exceptions=builtins.BaseException, + builtins.Exception, + functional.b.broad_exception.broad_exception_raised_trystar.CustomBroadException, + broad_exception_raised_trystar.CustomBroadException +[testoptions] +min_pyver=3.11 diff --git a/tests/functional/b/broad_exception/broad_exception_raised_trystar.txt b/tests/functional/b/broad_exception/broad_exception_raised_trystar.txt new file mode 100644 index 0000000000..c88b26b4be --- /dev/null +++ b/tests/functional/b/broad_exception/broad_exception_raised_trystar.txt @@ -0,0 +1,8 @@ +broad-exception-raised:15:4:15:41:exploding_apple:"Raising too general exception: Exception":INFERENCE +broad-exception-raised:20:8:20:34:raise_and_catch_star:"Raising too general exception: Exception":INFERENCE +broad-exception-caught:21:12:21:21:raise_and_catch_star:Catching too general exception Exception:INFERENCE +broad-exception-raised:38:8:38:35:raise_catch_raise_star:"Raising too general exception: Exception":INFERENCE +broad-exception-raised:46:8:46:40:raise_catch_raise_using_alias_star:"Raising too general exception: Exception":INFERENCE +broad-exception-raised:48:0:48:17::"Raising too general exception: Exception":INFERENCE +broad-exception-raised:49:0:49:21::"Raising too general exception: BaseException":INFERENCE +broad-exception-raised:50:0:50:28::"Raising too general exception: CustomBroadException":INFERENCE diff --git a/tests/functional/b/broad_exception_caught.rc b/tests/functional/b/broad_exception_caught.rc deleted file mode 100644 index e0e1a7b6c5..0000000000 --- a/tests/functional/b/broad_exception_caught.rc +++ /dev/null @@ -1,4 +0,0 @@ -[EXCEPTIONS] -overgeneral-exceptions=builtins.BaseException, - builtins.Exception, - functional.b.broad_exception_caught.CustomBroadException diff --git a/tests/functional/b/broad_exception_caught.txt b/tests/functional/b/broad_exception_caught.txt deleted file mode 100644 index b54d74ae33..0000000000 --- a/tests/functional/b/broad_exception_caught.txt +++ /dev/null @@ -1,6 +0,0 @@ -broad-exception-caught:14:7:14:16::Catching too general exception Exception:INFERENCE -broad-exception-caught:20:7:20:20::Catching too general exception BaseException:INFERENCE -broad-exception-caught:32:7:32:27::Catching too general exception CustomBroadException:INFERENCE -broad-exception-caught:44:8:44:17::Catching too general exception Exception:INFERENCE -broad-exception-caught:50:8:50:21::Catching too general exception BaseException:INFERENCE -broad-exception-caught:62:8:62:28::Catching too general exception CustomBroadException:INFERENCE diff --git a/tests/functional/b/broad_exception_raised.rc b/tests/functional/b/broad_exception_raised.rc deleted file mode 100644 index 4f85d2933f..0000000000 --- a/tests/functional/b/broad_exception_raised.rc +++ /dev/null @@ -1,4 +0,0 @@ -[EXCEPTIONS] -overgeneral-exceptions=builtins.BaseException, - builtins.Exception, - functional.b.broad_exception_raised.CustomBroadException From 702dd553e3c2ca7362abc9ed3a54c515fe0659d8 Mon Sep 17 00:00:00 2001 From: azinneck0485 <123660683+azinneck0485@users.noreply.github.com> Date: Mon, 6 Nov 2023 22:16:50 -0500 Subject: [PATCH 11/12] add visit_trystar to functional test files for class diagrams to address testing failures --- .../functional/class_diagrams/colorized_output/colorized.puml | 1 + .../class_diagrams/colorized_output/custom_colors.dot | 2 +- .../class_diagrams/colorized_output/custom_colors.puml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/pyreverse/functional/class_diagrams/colorized_output/colorized.puml b/tests/pyreverse/functional/class_diagrams/colorized_output/colorized.puml index dc9b7034ba..a0c8a31280 100644 --- a/tests/pyreverse/functional/class_diagrams/colorized_output/colorized.puml +++ b/tests/pyreverse/functional/class_diagrams/colorized_output/colorized.puml @@ -21,6 +21,7 @@ class "ExceptionsChecker" as pylint.checkers.exceptions.ExceptionsChecker #44BB9 visit_compare(node: nodes.Compare) -> None visit_raise(node: nodes.Raise) -> None visit_try(node: nodes.Try) -> None + visit_trystar(node: nodes.TryStar) -> None } class "StdlibChecker" as pylint.checkers.stdlib.StdlibChecker #44BB99 { msgs : dict[str, MessageDefinitionTuple] diff --git a/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.dot b/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.dot index 84c8142a35..18aa746d74 100644 --- a/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.dot +++ b/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.dot @@ -3,7 +3,7 @@ rankdir=BT charset="utf-8" "custom_colors.CheckerCollector" [color="red", fontcolor="black", label=<{CheckerCollector|checker1
checker2
checker3
|}>, shape="record", style="filled"]; "pylint.extensions.check_elif.ElseifUsedChecker" [color="#44BB88", fontcolor="black", label=<{ElseifUsedChecker|msgs : dict
name : str
|leave_module(_: nodes.Module): None
process_tokens(tokens: list[TokenInfo]): None
visit_if(node: nodes.If): None
}>, shape="record", style="filled"]; -"pylint.checkers.exceptions.ExceptionsChecker" [color="yellow", fontcolor="black", label=<{ExceptionsChecker|msgs : dict
name : str
options : tuple
|open(): None
visit_binop(node: nodes.BinOp): None
visit_compare(node: nodes.Compare): None
visit_raise(node: nodes.Raise): None
visit_try(node: nodes.Try): None
}>, shape="record", style="filled"]; +"pylint.checkers.exceptions.ExceptionsChecker" [color="yellow", fontcolor="black", label=<{ExceptionsChecker|msgs : dict
name : str
options : tuple
|open(): None
visit_binop(node: nodes.BinOp): None
visit_compare(node: nodes.Compare): None
visit_raise(node: nodes.Raise): None
visit_try(node: nodes.Try): None
visit_trystar(node: nodes.TryStar): None
}>, shape="record", style="filled"]; "pylint.checkers.stdlib.StdlibChecker" [color="yellow", fontcolor="black", label=<{StdlibChecker|msgs : dict[str, MessageDefinitionTuple]
name : str
|deprecated_arguments(method: str): tuple[tuple[int \| None, str], ...]
deprecated_classes(module: str): Iterable[str]
deprecated_decorators(): Iterable[str]
deprecated_methods(): set[str]
visit_boolop(node: nodes.BoolOp): None
visit_call(node: nodes.Call): None
visit_functiondef(node: nodes.FunctionDef): None
visit_if(node: nodes.If): None
visit_ifexp(node: nodes.IfExp): None
visit_unaryop(node: nodes.UnaryOp): None
}>, shape="record", style="filled"]; "pylint.checkers.exceptions.ExceptionsChecker" -> "custom_colors.CheckerCollector" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="checker1", style="solid"]; "pylint.checkers.stdlib.StdlibChecker" -> "custom_colors.CheckerCollector" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="checker3", style="solid"]; diff --git a/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.puml b/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.puml index 7119900639..adef4f03bb 100644 --- a/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.puml +++ b/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.puml @@ -21,6 +21,7 @@ class "ExceptionsChecker" as pylint.checkers.exceptions.ExceptionsChecker #yello visit_compare(node: nodes.Compare) -> None visit_raise(node: nodes.Raise) -> None visit_try(node: nodes.Try) -> None + visit_trystar(node: nodes.TryStar) -> None } class "StdlibChecker" as pylint.checkers.stdlib.StdlibChecker #yellow { msgs : dict[str, MessageDefinitionTuple] From 400c41dc2cefb3a9c73b69e546cae2473edfc71b Mon Sep 17 00:00:00 2001 From: azinneck0485 <123660683+azinneck0485@users.noreply.github.com> Date: Thu, 9 Nov 2023 20:50:01 -0500 Subject: [PATCH 12/12] fix custom_colors.dot that was messed up during previous merge --- .../class_diagrams/colorized_output/custom_colors.dot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.dot b/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.dot index 18aa746d74..bdf7ed2f0f 100644 --- a/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.dot +++ b/tests/pyreverse/functional/class_diagrams/colorized_output/custom_colors.dot @@ -4,7 +4,7 @@ charset="utf-8" "custom_colors.CheckerCollector" [color="red", fontcolor="black", label=<{CheckerCollector|checker1
checker2
checker3
|}>, shape="record", style="filled"]; "pylint.extensions.check_elif.ElseifUsedChecker" [color="#44BB88", fontcolor="black", label=<{ElseifUsedChecker|msgs : dict
name : str
|leave_module(_: nodes.Module): None
process_tokens(tokens: list[TokenInfo]): None
visit_if(node: nodes.If): None
}>, shape="record", style="filled"]; "pylint.checkers.exceptions.ExceptionsChecker" [color="yellow", fontcolor="black", label=<{ExceptionsChecker|msgs : dict
name : str
options : tuple
|open(): None
visit_binop(node: nodes.BinOp): None
visit_compare(node: nodes.Compare): None
visit_raise(node: nodes.Raise): None
visit_try(node: nodes.Try): None
visit_trystar(node: nodes.TryStar): None
}>, shape="record", style="filled"]; -"pylint.checkers.stdlib.StdlibChecker" [color="yellow", fontcolor="black", label=<{StdlibChecker|msgs : dict[str, MessageDefinitionTuple]
name : str
|deprecated_arguments(method: str): tuple[tuple[int \| None, str], ...]
deprecated_classes(module: str): Iterable[str]
deprecated_decorators(): Iterable[str]
deprecated_methods(): set[str]
visit_boolop(node: nodes.BoolOp): None
visit_call(node: nodes.Call): None
visit_functiondef(node: nodes.FunctionDef): None
visit_if(node: nodes.If): None
visit_ifexp(node: nodes.IfExp): None
visit_unaryop(node: nodes.UnaryOp): None
}>, shape="record", style="filled"]; +"pylint.checkers.stdlib.StdlibChecker" [color="yellow", fontcolor="black", label=<{StdlibChecker|msgs : dict[str, MessageDefinitionTuple]
name : str
|deprecated_arguments(method: str): tuple[tuple[int \| None, str], ...]
deprecated_attributes(): Iterable[str]
deprecated_classes(module: str): Iterable[str]
deprecated_decorators(): Iterable[str]
deprecated_methods(): set[str]
visit_boolop(node: nodes.BoolOp): None
visit_call(node: nodes.Call): None
visit_functiondef(node: nodes.FunctionDef): None
visit_if(node: nodes.If): None
visit_ifexp(node: nodes.IfExp): None
visit_unaryop(node: nodes.UnaryOp): None
}>, shape="record", style="filled"]; "pylint.checkers.exceptions.ExceptionsChecker" -> "custom_colors.CheckerCollector" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="checker1", style="solid"]; "pylint.checkers.stdlib.StdlibChecker" -> "custom_colors.CheckerCollector" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="checker3", style="solid"]; "pylint.extensions.check_elif.ElseifUsedChecker" -> "custom_colors.CheckerCollector" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="checker2", style="solid"];