Skip to content

Commit 80b0793

Browse files
Fix pylint-dev#2615 -- Extend solution to Except Handlers
Also fix bug where different TryFinally nodes were mixed up
1 parent a48f62b commit 80b0793

File tree

5 files changed

+36
-10
lines changed

5 files changed

+36
-10
lines changed

ChangeLog

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ Release date: TBA
99
..
1010
Put new features here and also in 'doc/whatsnew/2.13.rst'
1111

12-
* ``used-before-assignment`` now considers that assignments in the try block
13-
of a try/finally clause may not have occurred when the final block is
14-
executed.
12+
* ``used-before-assignment`` now considers that assignments in a try block
13+
may not have occurred when the except or finally blocks are executed.
1514

16-
Closes #85
15+
Closes #85, #2615
1716

1817
..
1918
Insert your changelog randomly, it will reduce merge conflicts

doc/whatsnew/2.13.rst

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ Other Changes
2424

2525
Closes #5065
2626

27-
* ``used-before-assignment`` now considers that assignments in the try block
28-
of a try/finally clause may not have occurred when the final block is
29-
executed.
27+
* ``used-before-assignment`` now considers that assignments in a try block
28+
may not have occurred when the except or finally blocks are executed.
3029

31-
Closes #85
30+
Closes #85, #2615

pylint/checkers/variables.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ def _has_locals_call_after_node(stmt, scope):
392392
"Using variable %r before assignment",
393393
"used-before-assignment",
394394
"Used when a local variable is accessed before its assignment or in "
395-
"a finally block without being defined outside the try block.",
395+
"except or finally blocks without being defined before the try block.",
396396
),
397397
"E0602": (
398398
"Undefined variable %r",
@@ -622,14 +622,32 @@ def get_next_to_consume(self, node):
622622
n
623623
for n in found_nodes
624624
if not (
625-
isinstance(n.statement(future=True).parent, nodes.TryFinally)
625+
n.statement(future=True).parent is node.statement(future=True).parent
626626
and n.statement(future=True) in n.statement(future=True).parent.body
627627
)
628628
]
629629
difference = set(found_nodes) - set(filtered_nodes)
630630
self.mark_as_consumed(name, difference)
631631
found_nodes = filtered_nodes
632632

633+
# If this node is in an ExceptHandler,
634+
# filter out assignments in the try portion, assuming they may fail
635+
if found_nodes and isinstance(
636+
node.statement(future=True).parent, nodes.ExceptHandler
637+
):
638+
filtered_nodes = [
639+
n
640+
for n in found_nodes
641+
if not (
642+
isinstance(n.statement(future=True).parent, nodes.TryExcept)
643+
and n.statement(future=True) in n.statement(future=True).parent.body
644+
and node.statement(future=True).parent in n.statement(future=True).parent.handlers
645+
)
646+
]
647+
difference = set(found_nodes) - set(filtered_nodes)
648+
self.mark_as_consumed(name, difference)
649+
found_nodes = filtered_nodes
650+
633651
return found_nodes
634652

635653

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"""https://github.com/PyCQA/pylint/issues/2615"""
2+
def main():
3+
"""When evaluating except blocks, assume try statements fail."""
4+
try:
5+
res = 1 / 0
6+
res = 42
7+
except ZeroDivisionError:
8+
print(res) # [used-before-assignment]
9+
print(res)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
used-before-assignment:8:14:8:17:main:Using variable 'res' before assignment:UNDEFINED

0 commit comments

Comments
 (0)