Skip to content

Commit 4392135

Browse files
[used-before-assignment] Fix FP under finally block
Closes #9451
1 parent 6d3e6a9 commit 4392135

File tree

4 files changed

+32
-10
lines changed

4 files changed

+32
-10
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix false positive for ``used-before-assignment`` in a ``finally`` block
2+
when assignments took place in both the ``try`` block and each exception handler.
3+
4+
Closes #9451

pylint/checkers/variables.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ def get_next_to_consume(self, node: nodes.Name) -> list[nodes.NodeNG] | None:
667667
if found_nodes:
668668
uncertain_nodes = (
669669
self._uncertain_nodes_in_try_blocks_when_evaluating_finally_blocks(
670-
found_nodes, node_statement
670+
found_nodes, node_statement, name
671671
)
672672
)
673673
self.consumed_uncertain[node.name] += uncertain_nodes
@@ -1140,7 +1140,9 @@ def _uncertain_nodes_in_try_blocks_when_evaluating_except_blocks(
11401140

11411141
@staticmethod
11421142
def _uncertain_nodes_in_try_blocks_when_evaluating_finally_blocks(
1143-
found_nodes: list[nodes.NodeNG], node_statement: _base_nodes.Statement
1143+
found_nodes: list[nodes.NodeNG],
1144+
node_statement: _base_nodes.Statement,
1145+
name: str,
11441146
) -> list[nodes.NodeNG]:
11451147
uncertain_nodes: list[nodes.NodeNG] = []
11461148
(
@@ -1187,6 +1189,12 @@ def _uncertain_nodes_in_try_blocks_when_evaluating_finally_blocks(
11871189
)
11881190
):
11891191
continue
1192+
# Is the name defined in all exception clauses?
1193+
if other_node_try_finally_ancestor.handlers and all(
1194+
NamesConsumer._defines_name_raises_or_returns_recursive(name, handler)
1195+
for handler in other_node_try_finally_ancestor.handlers
1196+
):
1197+
continue
11901198
# Passed all tests for uncertain execution
11911199
uncertain_nodes.append(other_node)
11921200
return uncertain_nodes

tests/functional/u/used/used_before_assignment_issue85.py

+10
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ def try_except_finally_assignment_in_final_block():
3434
print(res)
3535

3636

37+
def try_except_finally_assignment_in_both_try_and_except():
38+
"""Assignment of the name in both try and except blocks is fine."""
39+
try:
40+
res = 1 / 0
41+
except ZeroDivisionError:
42+
res = 0
43+
finally:
44+
print(res)
45+
46+
3747
def try_except_finally_nested_try_finally_in_try():
3848
"""Don't confuse assignments in different finally statements where
3949
one is nested inside a try.
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
used-before-assignment:8:14:8:17:main:Using variable 'res' before assignment:CONTROL_FLOW
22
used-before-assignment:20:14:20:17:try_except_finally:Using variable 'res' before assignment:CONTROL_FLOW
3-
used-before-assignment:45:18:45:21:try_except_finally_nested_try_finally_in_try:Using variable 'res' before assignment:HIGH
4-
used-before-assignment:70:18:70:29:try_except_finally_nested_in_finally:Using variable 'outer_times' before assignment:CONTROL_FLOW
5-
used-before-assignment:84:18:84:29:try_except_finally_nested_in_finally_2:Using variable 'inner_times' before assignment:CONTROL_FLOW
6-
used-before-assignment:85:14:85:25:try_except_finally_nested_in_finally_2:Using variable 'outer_times' before assignment:CONTROL_FLOW
7-
used-before-assignment:100:18:100:29:try_except_finally_nested_in_finally_3:Using variable 'inner_times' before assignment:CONTROL_FLOW
8-
used-before-assignment:101:18:101:29:try_except_finally_nested_in_finally_3:Using variable 'outer_times' before assignment:CONTROL_FLOW
9-
used-before-assignment:122:22:122:33:try_except_finally_nested_in_finally_4:Using variable 'inner_times' before assignment:CONTROL_FLOW
10-
used-before-assignment:123:22:123:33:try_except_finally_nested_in_finally_4:Using variable 'outer_times' before assignment:CONTROL_FLOW
3+
used-before-assignment:55:18:55:21:try_except_finally_nested_try_finally_in_try:Using variable 'res' before assignment:HIGH
4+
used-before-assignment:80:18:80:29:try_except_finally_nested_in_finally:Using variable 'outer_times' before assignment:CONTROL_FLOW
5+
used-before-assignment:94:18:94:29:try_except_finally_nested_in_finally_2:Using variable 'inner_times' before assignment:CONTROL_FLOW
6+
used-before-assignment:95:14:95:25:try_except_finally_nested_in_finally_2:Using variable 'outer_times' before assignment:CONTROL_FLOW
7+
used-before-assignment:110:18:110:29:try_except_finally_nested_in_finally_3:Using variable 'inner_times' before assignment:CONTROL_FLOW
8+
used-before-assignment:111:18:111:29:try_except_finally_nested_in_finally_3:Using variable 'outer_times' before assignment:CONTROL_FLOW
9+
used-before-assignment:132:22:132:33:try_except_finally_nested_in_finally_4:Using variable 'inner_times' before assignment:CONTROL_FLOW
10+
used-before-assignment:133:22:133:33:try_except_finally_nested_in_finally_4:Using variable 'outer_times' before assignment:CONTROL_FLOW

0 commit comments

Comments
 (0)