From 67b7791094545a5bf841d36e61de43a20e449047 Mon Sep 17 00:00:00 2001 From: Mark Byrne Date: Mon, 27 May 2024 23:27:07 +0200 Subject: [PATCH 1/4] Fix a false positive for ``redefined-outer-name`` when there is a name defined in an exception-handling block which shares the same name as a local variable that has been defined in a function body. Closes #9671 --- doc/whatsnew/fragments/9671.false_positive | 3 +++ pylint/checkers/variables.py | 2 ++ .../r/redefined/redefined_except_handler.py | 15 +++++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 doc/whatsnew/fragments/9671.false_positive diff --git a/doc/whatsnew/fragments/9671.false_positive b/doc/whatsnew/fragments/9671.false_positive new file mode 100644 index 0000000000..23dafff10f --- /dev/null +++ b/doc/whatsnew/fragments/9671.false_positive @@ -0,0 +1,3 @@ +Fix a false positive for ``redefined-outer-name`` when there is a name defined in an exception-handling block which shares the same name as a local variable that has been defined in a function body. + +Closes #9671 diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index 6c33a05556..1742041145 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -1520,6 +1520,8 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None: continue line = definition.fromlineno + if line > stmt.lineno: + continue if not self._is_name_ignored(stmt, name): self.add_message( "redefined-outer-name", args=(name, line), node=stmt diff --git a/tests/functional/r/redefined/redefined_except_handler.py b/tests/functional/r/redefined/redefined_except_handler.py index b774e32f2f..e5d2a28297 100644 --- a/tests/functional/r/redefined/redefined_except_handler.py +++ b/tests/functional/r/redefined/redefined_except_handler.py @@ -70,3 +70,18 @@ def func(): # pylint:disable-next=invalid-name, unused-variable except IOError as CustomException: # [redefined-outer-name] pass + + +def function_before(): + """https://github.com/pylint-dev/pylint/issues/9671 + + The local variable `e` should not trigger `redefined-outer-name` + when `e` is also defined in the subsequent exception handling block. + """ + e = 42 + return e + +try: + raise ValueError('outer') +except ValueError as e: + print(e) From 805663a8493166812322f86a52b7df4490fbf09a Mon Sep 17 00:00:00 2001 From: Mark Byrne Date: Mon, 27 May 2024 23:42:35 +0200 Subject: [PATCH 2/4] Fix: `Useless suppression of 'redefined-outer-name'`. --- tests/conftest.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index a2512b4140..8dca2b17a1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,8 +2,6 @@ # For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE # Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt -# pylint: disable=redefined-outer-name - from __future__ import annotations import os From 5ad2dec41bc71e3d73c9e67153a5d9417d1a21d3 Mon Sep 17 00:00:00 2001 From: Mark Byrne Date: Thu, 30 May 2024 10:17:04 +0200 Subject: [PATCH 3/4] Check if the outer node is in the scope of an exception assignment and do not emit ``redefined-outer-name`` if that is the case. --- pylint/checkers/variables.py | 11 +++++++++-- tests/conftest.py | 2 ++ .../r/redefined/redefined_except_handler.py | 14 +++++++++++--- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index 1742041145..8447320b89 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -1519,9 +1519,16 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None: ): continue - line = definition.fromlineno - if line > stmt.lineno: + # Suppress emitting the message if the outer name is in the + # scope of an exception assignment. + # For example: the `e` in `except ValueError as e` + global_node = globs[name][0] + if isinstance(global_node, nodes.AssignName) and isinstance( + global_node.parent, nodes.ExceptHandler + ): continue + + line = definition.fromlineno if not self._is_name_ignored(stmt, name): self.add_message( "redefined-outer-name", args=(name, line), node=stmt diff --git a/tests/conftest.py b/tests/conftest.py index 8dca2b17a1..a2512b4140 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,6 +2,8 @@ # For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE # Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt +# pylint: disable=redefined-outer-name + from __future__ import annotations import os diff --git a/tests/functional/r/redefined/redefined_except_handler.py b/tests/functional/r/redefined/redefined_except_handler.py index e5d2a28297..5dcb854856 100644 --- a/tests/functional/r/redefined/redefined_except_handler.py +++ b/tests/functional/r/redefined/redefined_except_handler.py @@ -72,10 +72,9 @@ def func(): pass +# https://github.com/pylint-dev/pylint/issues/9671 def function_before(): - """https://github.com/pylint-dev/pylint/issues/9671 - - The local variable `e` should not trigger `redefined-outer-name` + """The local variable `e` should not trigger `redefined-outer-name` when `e` is also defined in the subsequent exception handling block. """ e = 42 @@ -85,3 +84,12 @@ def function_before(): raise ValueError('outer') except ValueError as e: print(e) + + +def function_after(): + """function defined after exception handler at module level + The local variable `e` should not trigger `redefined-outer-name` + when `e` is also defined in the subsequent exception handling block. + """ + e = 42 + return e From 84f189c62b10861bfc6b37dcc7a93e419ea097a2 Mon Sep 17 00:00:00 2001 From: Mark Byrne Date: Thu, 30 May 2024 10:35:46 +0200 Subject: [PATCH 4/4] Tidy up the accuracy of the test docstring. --- tests/functional/r/redefined/redefined_except_handler.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/functional/r/redefined/redefined_except_handler.py b/tests/functional/r/redefined/redefined_except_handler.py index 5dcb854856..d621496263 100644 --- a/tests/functional/r/redefined/redefined_except_handler.py +++ b/tests/functional/r/redefined/redefined_except_handler.py @@ -73,7 +73,7 @@ def func(): # https://github.com/pylint-dev/pylint/issues/9671 -def function_before(): +def function_before_exception(): """The local variable `e` should not trigger `redefined-outer-name` when `e` is also defined in the subsequent exception handling block. """ @@ -86,10 +86,9 @@ def function_before(): print(e) -def function_after(): - """function defined after exception handler at module level - The local variable `e` should not trigger `redefined-outer-name` - when `e` is also defined in the subsequent exception handling block. +def function_after_exception(): + """The local variable `e` should not trigger `redefined-outer-name` + when `e` is also defined in the preceding exception handling block. """ e = 42 return e